/*
 * 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;
  };
})();
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(11);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(config__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var widget_shared_jsonp__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(795);
/* harmony import */ var widget_shared_script_loader__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(796);
/* harmony import */ var widget_shared_url__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(310);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }





var query = Object(widget_shared_url__WEBPACK_IMPORTED_MODULE_3__[/* queryStringToObject */ "b"])();
var preview = query.live_preview && (query.live_preview === 1 || query.live_preview === '1' || query.live_preview === 'true' || query.live_preview === true);

function start() {
  Object(widget_shared_jsonp__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"])("".concat(config__WEBPACK_IMPORTED_MODULE_0___default.a.dashboardRootUrl, "/version"), '_WidgetJPCB_Version', function (response) {
    var scriptUrl = "".concat(config__WEBPACK_IMPORTED_MODULE_0___default.a.cdnUrl).concat(response.assets['modern.js']);
    Object(widget_shared_script_loader__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"])(scriptUrl, function () {
      var settings = window.widgetSettings.WidgetSettings; // eslint-disable-next-line no-underscore-dangle

      window._pcWidgetInitializer.start(_objectSpread({}, settings, {}, preview ? window.parent.currentWidgetSettings.toJSON() : {}, {
        ChatBoxEnabled: true,
        isDemo: preview,
        isDirectAccess: true,
        renderInto: '.purechat-direct-container'
      }));

      window.purechatApi.on('chatbox:ready', function () {
        document.body.style.visibility = 'visible';
      });
    });
  });
}

start();/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return loadScript; });
function loadScript(url, success, error) {
  var script = document.createElement('script');
  script.async = true;
  script.type = 'text/javascript';

  if (typeof url === 'string') {
    script.src = url;
  } else {
    var scriptUrl = url.url,
        sha = url.sha;
    script.crossOrigin = 'anonymous';
    script.integrity = sha;
    script.src = scriptUrl;
  }

  var scriptReady = false;
  if (error && typeof error === 'function') script.onerror = error;

  function readyFn() {
    if (!scriptReady && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) {
      scriptReady = true;
      success(script);
    }
  }

  script.onload = readyFn;
  script.onreadystatechange = readyFn;
  document.body.appendChild(script);
}var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(42),
	__webpack_require__(97),
	__webpack_require__(194),
	__webpack_require__(123),
	__webpack_require__(277),
	__webpack_require__(574),
	__webpack_require__(196),
	__webpack_require__(575),
	__webpack_require__(579),
	__webpack_require__(98),
	__webpack_require__(297),
	__webpack_require__(583),
	__webpack_require__(149),
	__webpack_require__(585),
	__webpack_require__(589),
	__webpack_require__(124),
	__webpack_require__(590),
	__webpack_require__(591),
	__webpack_require__(99),
	__webpack_require__(592),
	__webpack_require__(593),
	__webpack_require__(594),
	__webpack_require__(595),
	__webpack_require__(597),
	__webpack_require__(197),
	__webpack_require__(598),
	__webpack_require__(599),
	__webpack_require__(600),
	__webpack_require__(601),
	__webpack_require__(602)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

return ( window.jQuery = window.$ = jQuery );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/* WEBPACK VAR INJECTION */(function(jQuery) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(122),
	__webpack_require__(37),
	__webpack_require__(191),
	__webpack_require__(271),
	__webpack_require__(272),
	__webpack_require__(192),
	__webpack_require__(193),
	__webpack_require__(569),
	__webpack_require__(273),
	__webpack_require__(96)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( arr, document, slice, concat, push, indexOf, class2type, toString, hasOwn, support ) {

var
	version = "@VERSION",

	// Define a local copy of jQuery
	jQuery = function( selector, context ) {

		// The jQuery object is actually just the init constructor 'enhanced'
		// Need init if jQuery is called (just allow error to be thrown if not included)
		return new jQuery.fn.init( selector, context );
	},

	// Support: Android<4.1
	// Make sure we trim BOM and NBSP
	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,

	// Matches dashed string for camelizing
	rmsPrefix = /^-ms-/,
	rdashAlpha = /-([\da-z])/gi,

	// Used by jQuery.camelCase as callback to replace()
	fcamelCase = function( all, letter ) {
		return letter.toUpperCase();
	};

jQuery.fn = jQuery.prototype = {

	// The current version of jQuery being used
	jquery: version,

	constructor: jQuery,

	// Start with an empty selector
	selector: "",

	// The default length of a jQuery object is 0
	length: 0,

	toArray: function() {
		return slice.call( this );
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num != null ?

			// Return just the one element from the set
			( num < 0 ? this[ num + this.length ] : this[ num ] ) :

			// Return all the elements in a clean array
			slice.call( this );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems ) {

		// Build a new jQuery matched element set
		var ret = jQuery.merge( this.constructor(), elems );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;
		ret.context = this.context;

		// Return the newly-formed element set
		return ret;
	},

	// Execute a callback for every element in the matched set.
	each: function( callback ) {
		return jQuery.each( this, callback );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map( this, function( elem, i ) {
			return callback.call( elem, i, elem );
		} ) );
	},

	slice: function() {
		return this.pushStack( slice.apply( this, arguments ) );
	},

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	eq: function( i ) {
		var len = this.length,
			j = +i + ( i < 0 ? len : 0 );
		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
	},

	end: function() {
		return this.prevObject || this.constructor();
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: push,
	sort: arr.sort,
	splice: arr.splice
};

jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[ 0 ] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;

		// Skip the boolean and the target
		target = arguments[ i ] || {};
		i++;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
		target = {};
	}

	// Extend jQuery itself if only one argument is passed
	if ( i === length ) {
		target = this;
		i--;
	}

	for ( ; i < length; i++ ) {

		// Only deal with non-null/undefined values
		if ( ( options = arguments[ i ] ) != null ) {

			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
					( copyIsArray = jQuery.isArray( copy ) ) ) ) {

					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray( src ) ? src : [];

					} else {
						clone = src && jQuery.isPlainObject( src ) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend( {

	// Unique for each copy of jQuery on the page
	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),

	// Assume jQuery is ready without the ready module
	isReady: true,

	error: function( msg ) {
		throw new Error( msg );
	},

	noop: function() {},

	isFunction: function( obj ) {
		return jQuery.type( obj ) === "function";
	},

	isArray: Array.isArray,

	isWindow: function( obj ) {
		return obj != null && obj === obj.window;
	},

	isNumeric: function( obj ) {

		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
		// subtraction forces infinities to NaN
		// adding 1 corrects loss of precision from parseFloat (#15100)
		var realStringObj = obj && obj.toString();
		return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
	},

	isPlainObject: function( obj ) {
		var key;

		// Not plain objects:
		// - Any object or value whose internal [[Class]] property is not "[object Object]"
		// - DOM nodes
		// - window
		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
			return false;
		}

		// Not own constructor property must be Object
		if ( obj.constructor &&
				!hasOwn.call( obj, "constructor" ) &&
				!hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) {
			return false;
		}

		// Own properties are enumerated firstly, so to speed up,
		// if last one is own, then all properties are own
		for ( key in obj ) {}

		return key === undefined || hasOwn.call( obj, key );
	},

	isEmptyObject: function( obj ) {
		var name;
		for ( name in obj ) {
			return false;
		}
		return true;
	},

	type: function( obj ) {
		if ( obj == null ) {
			return obj + "";
		}

		// Support: Android<4.0, iOS<6 (functionish RegExp)
		return typeof obj === "object" || typeof obj === "function" ?
			class2type[ toString.call( obj ) ] || "object" :
			typeof obj;
	},

	// Evaluates a script in a global context
	globalEval: function( code ) {
		var script,
			indirect = eval;

		code = jQuery.trim( code );

		if ( code ) {

			// If the code includes a valid, prologue position
			// strict mode pragma, execute code by injecting a
			// script tag into the document.
			if ( code.indexOf( "use strict" ) === 1 ) {
				script = document.createElement( "script" );
				script.text = code;
				document.head.appendChild( script ).parentNode.removeChild( script );
			} else {

				// Otherwise, avoid the DOM node creation, insertion
				// and removal by using an indirect global eval

				indirect( code );
			}
		}
	},

	// Convert dashed to camelCase; used by the css and data modules
	// Support: IE9-11+
	// Microsoft forgot to hump their vendor prefix (#9572)
	camelCase: function( string ) {
		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
	},

	each: function( obj, callback ) {
		var length, i = 0;

		if ( isArrayLike( obj ) ) {
			length = obj.length;
			for ( ; i < length; i++ ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		} else {
			for ( i in obj ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		}

		return obj;
	},

	// Support: Android<4.1
	trim: function( text ) {
		return text == null ?
			"" :
			( text + "" ).replace( rtrim, "" );
	},

	// results is for internal usage only
	makeArray: function( arr, results ) {
		var ret = results || [];

		if ( arr != null ) {
			if ( isArrayLike( Object( arr ) ) ) {
				jQuery.merge( ret,
					typeof arr === "string" ?
					[ arr ] : arr
				);
			} else {
				push.call( ret, arr );
			}
		}

		return ret;
	},

	inArray: function( elem, arr, i ) {
		return arr == null ? -1 : indexOf.call( arr, elem, i );
	},

	merge: function( first, second ) {
		var len = +second.length,
			j = 0,
			i = first.length;

		for ( ; j < len; j++ ) {
			first[ i++ ] = second[ j ];
		}

		first.length = i;

		return first;
	},

	grep: function( elems, callback, invert ) {
		var callbackInverse,
			matches = [],
			i = 0,
			length = elems.length,
			callbackExpect = !invert;

		// Go through the array, only saving the items
		// that pass the validator function
		for ( ; i < length; i++ ) {
			callbackInverse = !callback( elems[ i ], i );
			if ( callbackInverse !== callbackExpect ) {
				matches.push( elems[ i ] );
			}
		}

		return matches;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		var length, value,
			i = 0,
			ret = [];

		// Go through the array, translating each of the items to their new values
		if ( isArrayLike( elems ) ) {
			length = elems.length;
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}

		// Go through every key on the object,
		} else {
			for ( i in elems ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}
		}

		// Flatten any nested arrays
		return concat.apply( [], ret );
	},

	// A global GUID counter for objects
	guid: 1,

	// Bind a function to a context, optionally partially applying any
	// arguments.
	proxy: function( fn, context ) {
		var tmp, args, proxy;

		if ( typeof context === "string" ) {
			tmp = fn[ context ];
			context = fn;
			fn = tmp;
		}

		// Quick check to determine if target is callable, in the spec
		// this throws a TypeError, but we will just return undefined.
		if ( !jQuery.isFunction( fn ) ) {
			return undefined;
		}

		// Simulated bind
		args = slice.call( arguments, 2 );
		proxy = function() {
			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
		};

		// Set the guid of unique handler to the same of original handler, so it can be removed
		proxy.guid = fn.guid = fn.guid || jQuery.guid++;

		return proxy;
	},

	now: Date.now,

	// jQuery.support is not used in Core but other projects attach their
	// properties to it so it needs to exist.
	support: support
} );

// JSHint would error on this code due to the Symbol not being defined in ES5.
// Defining this global in .jshintrc would create a danger of using the global
// unguarded in another place, it seems safer to just disable JSHint for these
// three lines.
/* jshint ignore: start */
if ( typeof Symbol === "function" ) {
	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
}
/* jshint ignore: end */

// Populate the class2type map
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
function( i, name ) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
} );

function isArrayLike( obj ) {

	// Support: iOS 8.2 (not reproducible in simulator)
	// `in` check used to prevent JIT error (gh-2145)
	// hasOwn isn't used here due to false negatives
	// regarding Nodelist length in IE
	var length = !!obj && "length" in obj && obj.length,
		type = jQuery.type( obj );

	if ( type === "function" || jQuery.isWindow( obj ) ) {
		return false;
	}

	return type === "array" || length === 0 ||
		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(0)))var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return [];
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return window.document;
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(122)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( arr ) {
	return arr.slice;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(122)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( arr ) {
	return arr.concat;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(122)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( arr ) {
	return arr.push;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(122)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( arr ) {
	return arr.indexOf;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

	// [[Class]] -> type pairs
	return {};
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(193)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( class2type ) {
	return class2type.toString;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(193)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( class2type ) {
	return class2type.hasOwnProperty;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

	// All support tests are defined in their respective modules.
	return {};
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(570) ], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(571)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, Sizzle ) {

jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[ ":" ] = jQuery.expr.pseudos;
jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;/*!
 * Sizzle CSS Selector Engine v2.2.1
 * http://sizzlejs.com/
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2015-10-17
 */
(function( window ) {

var i,
	support,
	Expr,
	getText,
	isXML,
	tokenize,
	compile,
	select,
	outermostContext,
	sortInput,
	hasDuplicate,

	// Local document vars
	setDocument,
	document,
	docElem,
	documentIsHTML,
	rbuggyQSA,
	rbuggyMatches,
	matches,
	contains,

	// Instance-specific data
	expando = "sizzle" + 1 * new Date(),
	preferredDoc = window.document,
	dirruns = 0,
	done = 0,
	classCache = createCache(),
	tokenCache = createCache(),
	compilerCache = createCache(),
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
		}
		return 0;
	},

	// General-purpose constants
	MAX_NEGATIVE = 1 << 31,

	// Instance methods
	hasOwn = ({}).hasOwnProperty,
	arr = [],
	pop = arr.pop,
	push_native = arr.push,
	push = arr.push,
	slice = arr.slice,
	// Use a stripped-down indexOf as it's faster than native
	// http://jsperf.com/thor-indexof-vs-for/5
	indexOf = function( list, elem ) {
		var i = 0,
			len = list.length;
		for ( ; i < len; i++ ) {
			if ( list[i] === elem ) {
				return i;
			}
		}
		return -1;
	},

	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

	// Regular expressions

	// http://www.w3.org/TR/css3-selectors/#whitespace
	whitespace = "[\\x20\\t\\r\\n\\f]",

	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
	identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
		// Operator (capture 2)
		"*([*^$|!~]?=)" + whitespace +
		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
		"*\\]",

	pseudos = ":(" + identifier + ")(?:\\((" +
		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
		// 1. quoted (capture 3; capture 4 or capture 5)
		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
		// 2. simple (capture 6)
		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
		// 3. anything else (capture 2)
		".*" +
		")\\)|)",

	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
	rwhitespace = new RegExp( whitespace + "+", "g" ),
	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),

	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),

	rpseudo = new RegExp( pseudos ),
	ridentifier = new RegExp( "^" + identifier + "$" ),

	matchExpr = {
		"ID": new RegExp( "^#(" + identifier + ")" ),
		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
		"ATTR": new RegExp( "^" + attributes ),
		"PSEUDO": new RegExp( "^" + pseudos ),
		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
		// For use in libraries implementing .is()
		// We use this for POS matching in `select`
		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
	},

	rinputs = /^(?:input|select|textarea|button)$/i,
	rheader = /^h\d$/i,

	rnative = /^[^{]+\{\s*\[native \w/,

	// Easily-parseable/retrievable ID or TAG or CLASS selectors
	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

	rsibling = /[+~]/,
	rescape = /'|\\/g,

	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
	funescape = function( _, escaped, escapedWhitespace ) {
		var high = "0x" + escaped - 0x10000;
		// NaN means non-codepoint
		// Support: Firefox<24
		// Workaround erroneous numeric interpretation of +"0x"
		return high !== high || escapedWhitespace ?
			escaped :
			high < 0 ?
				// BMP codepoint
				String.fromCharCode( high + 0x10000 ) :
				// Supplemental Plane codepoint (surrogate pair)
				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
	},

	// Used for iframes
	// See setDocument()
	// Removing the function wrapper causes a "Permission Denied"
	// error in IE
	unloadHandler = function() {
		setDocument();
	};

// Optimize for push.apply( _, NodeList )
try {
	push.apply(
		(arr = slice.call( preferredDoc.childNodes )),
		preferredDoc.childNodes
	);
	// Support: Android<4.0
	// Detect silently failing push.apply
	arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
	push = { apply: arr.length ?

		// Leverage slice if possible
		function( target, els ) {
			push_native.apply( target, slice.call(els) );
		} :

		// Support: IE<9
		// Otherwise append directly
		function( target, els ) {
			var j = target.length,
				i = 0;
			// Can't trust NodeList.length
			while ( (target[j++] = els[i++]) ) {}
			target.length = j - 1;
		}
	};
}

function Sizzle( selector, context, results, seed ) {
	var m, i, elem, nid, nidselect, match, groups, newSelector,
		newContext = context && context.ownerDocument,

		// nodeType defaults to 9, since context defaults to document
		nodeType = context ? context.nodeType : 9;

	results = results || [];

	// Return early from calls with invalid selector or context
	if ( typeof selector !== "string" || !selector ||
		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

		return results;
	}

	// Try to shortcut find operations (as opposed to filters) in HTML documents
	if ( !seed ) {

		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
			setDocument( context );
		}
		context = context || document;

		if ( documentIsHTML ) {

			// If the selector is sufficiently simple, try using a "get*By*" DOM method
			// (excepting DocumentFragment context, where the methods don't exist)
			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {

				// ID selector
				if ( (m = match[1]) ) {

					// Document context
					if ( nodeType === 9 ) {
						if ( (elem = context.getElementById( m )) ) {

							// Support: IE, Opera, Webkit
							// TODO: identify versions
							// getElementById can match elements by name instead of ID
							if ( elem.id === m ) {
								results.push( elem );
								return results;
							}
						} else {
							return results;
						}

					// Element context
					} else {

						// Support: IE, Opera, Webkit
						// TODO: identify versions
						// getElementById can match elements by name instead of ID
						if ( newContext && (elem = newContext.getElementById( m )) &&
							contains( context, elem ) &&
							elem.id === m ) {

							results.push( elem );
							return results;
						}
					}

				// Type selector
				} else if ( match[2] ) {
					push.apply( results, context.getElementsByTagName( selector ) );
					return results;

				// Class selector
				} else if ( (m = match[3]) && support.getElementsByClassName &&
					context.getElementsByClassName ) {

					push.apply( results, context.getElementsByClassName( m ) );
					return results;
				}
			}

			// Take advantage of querySelectorAll
			if ( support.qsa &&
				!compilerCache[ selector + " " ] &&
				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

				if ( nodeType !== 1 ) {
					newContext = context;
					newSelector = selector;

				// qSA looks outside Element context, which is not what we want
				// Thanks to Andrew Dupont for this workaround technique
				// Support: IE <=8
				// Exclude object elements
				} else if ( context.nodeName.toLowerCase() !== "object" ) {

					// Capture the context ID, setting it first if necessary
					if ( (nid = context.getAttribute( "id" )) ) {
						nid = nid.replace( rescape, "\\$&" );
					} else {
						context.setAttribute( "id", (nid = expando) );
					}

					// Prefix every selector in the list
					groups = tokenize( selector );
					i = groups.length;
					nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
					while ( i-- ) {
						groups[i] = nidselect + " " + toSelector( groups[i] );
					}
					newSelector = groups.join( "," );

					// Expand context for sibling selectors
					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
						context;
				}

				if ( newSelector ) {
					try {
						push.apply( results,
							newContext.querySelectorAll( newSelector )
						);
						return results;
					} catch ( qsaError ) {
					} finally {
						if ( nid === expando ) {
							context.removeAttribute( "id" );
						}
					}
				}
			}
		}
	}

	// All others
	return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

/**
 * Create key-value caches of limited size
 * @returns {function(string, object)} Returns the Object data after storing it on itself with
 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
 *	deleting the oldest entry
 */
function createCache() {
	var keys = [];

	function cache( key, value ) {
		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
		if ( keys.push( key + " " ) > Expr.cacheLength ) {
			// Only keep the most recent entries
			delete cache[ keys.shift() ];
		}
		return (cache[ key + " " ] = value);
	}
	return cache;
}

/**
 * Mark a function for special use by Sizzle
 * @param {Function} fn The function to mark
 */
function markFunction( fn ) {
	fn[ expando ] = true;
	return fn;
}

/**
 * Support testing using an element
 * @param {Function} fn Passed the created div and expects a boolean result
 */
function assert( fn ) {
	var div = document.createElement("div");

	try {
		return !!fn( div );
	} catch (e) {
		return false;
	} finally {
		// Remove from its parent by default
		if ( div.parentNode ) {
			div.parentNode.removeChild( div );
		}
		// release memory in IE
		div = null;
	}
}

/**
 * Adds the same handler for all of the specified attrs
 * @param {String} attrs Pipe-separated list of attributes
 * @param {Function} handler The method that will be applied
 */
function addHandle( attrs, handler ) {
	var arr = attrs.split("|"),
		i = arr.length;

	while ( i-- ) {
		Expr.attrHandle[ arr[i] ] = handler;
	}
}

/**
 * Checks document order of two siblings
 * @param {Element} a
 * @param {Element} b
 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
 */
function siblingCheck( a, b ) {
	var cur = b && a,
		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
			( ~b.sourceIndex || MAX_NEGATIVE ) -
			( ~a.sourceIndex || MAX_NEGATIVE );

	// Use IE sourceIndex if available on both nodes
	if ( diff ) {
		return diff;
	}

	// Check if b follows a
	if ( cur ) {
		while ( (cur = cur.nextSibling) ) {
			if ( cur === b ) {
				return -1;
			}
		}
	}

	return a ? 1 : -1;
}

/**
 * Returns a function to use in pseudos for input types
 * @param {String} type
 */
function createInputPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return name === "input" && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for buttons
 * @param {String} type
 */
function createButtonPseudo( type ) {
	return function( elem ) {
		var name = elem.nodeName.toLowerCase();
		return (name === "input" || name === "button") && elem.type === type;
	};
}

/**
 * Returns a function to use in pseudos for positionals
 * @param {Function} fn
 */
function createPositionalPseudo( fn ) {
	return markFunction(function( argument ) {
		argument = +argument;
		return markFunction(function( seed, matches ) {
			var j,
				matchIndexes = fn( [], seed.length, argument ),
				i = matchIndexes.length;

			// Match elements found at the specified indexes
			while ( i-- ) {
				if ( seed[ (j = matchIndexes[i]) ] ) {
					seed[j] = !(matches[j] = seed[j]);
				}
			}
		});
	});
}

/**
 * Checks a node for validity as a Sizzle context
 * @param {Element|Object=} context
 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
 */
function testContext( context ) {
	return context && typeof context.getElementsByTagName !== "undefined" && context;
}

// Expose support vars for convenience
support = Sizzle.support = {};

/**
 * Detects XML nodes
 * @param {Element|Object} elem An element or a document
 * @returns {Boolean} True iff elem is a non-HTML XML node
 */
isXML = Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833)
	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

/**
 * Sets document-related variables once based on the current document
 * @param {Element|Object} [doc] An element or document object to use to set the document
 * @returns {Object} Returns the current document
 */
setDocument = Sizzle.setDocument = function( node ) {
	var hasCompare, parent,
		doc = node ? node.ownerDocument || node : preferredDoc;

	// Return early if doc is invalid or already selected
	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
		return document;
	}

	// Update global variables
	document = doc;
	docElem = document.documentElement;
	documentIsHTML = !isXML( document );

	// Support: IE 9-11, Edge
	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
	if ( (parent = document.defaultView) && parent.top !== parent ) {
		// Support: IE 11
		if ( parent.addEventListener ) {
			parent.addEventListener( "unload", unloadHandler, false );

		// Support: IE 9 - 10 only
		} else if ( parent.attachEvent ) {
			parent.attachEvent( "onunload", unloadHandler );
		}
	}

	/* Attributes
	---------------------------------------------------------------------- */

	// Support: IE<8
	// Verify that getAttribute really returns attributes and not properties
	// (excepting IE8 booleans)
	support.attributes = assert(function( div ) {
		div.className = "i";
		return !div.getAttribute("className");
	});

	/* getElement(s)By*
	---------------------------------------------------------------------- */

	// Check if getElementsByTagName("*") returns only elements
	support.getElementsByTagName = assert(function( div ) {
		div.appendChild( document.createComment("") );
		return !div.getElementsByTagName("*").length;
	});

	// Support: IE<9
	support.getElementsByClassName = rnative.test( document.getElementsByClassName );

	// Support: IE<10
	// Check if getElementById returns elements by name
	// The broken getElementById methods don't pick up programatically-set names,
	// so use a roundabout getElementsByName test
	support.getById = assert(function( div ) {
		docElem.appendChild( div ).id = expando;
		return !document.getElementsByName || !document.getElementsByName( expando ).length;
	});

	// ID find and filter
	if ( support.getById ) {
		Expr.find["ID"] = function( id, context ) {
			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
				var m = context.getElementById( id );
				return m ? [ m ] : [];
			}
		};
		Expr.filter["ID"] = function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				return elem.getAttribute("id") === attrId;
			};
		};
	} else {
		// Support: IE6/7
		// getElementById is not reliable as a find shortcut
		delete Expr.find["ID"];

		Expr.filter["ID"] =  function( id ) {
			var attrId = id.replace( runescape, funescape );
			return function( elem ) {
				var node = typeof elem.getAttributeNode !== "undefined" &&
					elem.getAttributeNode("id");
				return node && node.value === attrId;
			};
		};
	}

	// Tag
	Expr.find["TAG"] = support.getElementsByTagName ?
		function( tag, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( tag );

			// DocumentFragment nodes don't have gEBTN
			} else if ( support.qsa ) {
				return context.querySelectorAll( tag );
			}
		} :

		function( tag, context ) {
			var elem,
				tmp = [],
				i = 0,
				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
				results = context.getElementsByTagName( tag );

			// Filter out possible comments
			if ( tag === "*" ) {
				while ( (elem = results[i++]) ) {
					if ( elem.nodeType === 1 ) {
						tmp.push( elem );
					}
				}

				return tmp;
			}
			return results;
		};

	// Class
	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
			return context.getElementsByClassName( className );
		}
	};

	/* QSA/matchesSelector
	---------------------------------------------------------------------- */

	// QSA and matchesSelector support

	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
	rbuggyMatches = [];

	// qSa(:focus) reports false when true (Chrome 21)
	// We allow this because of a bug in IE8/9 that throws an error
	// whenever `document.activeElement` is accessed on an iframe
	// So, we allow :focus to pass through QSA all the time to avoid the IE error
	// See http://bugs.jquery.com/ticket/13378
	rbuggyQSA = [];

	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
		// Build QSA regex
		// Regex strategy adopted from Diego Perini
		assert(function( div ) {
			// Select is set to empty string on purpose
			// This is to test IE's treatment of not explicitly
			// setting a boolean content attribute,
			// since its presence should be enough
			// http://bugs.jquery.com/ticket/12359
			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
				"<option selected=''></option></select>";

			// Support: IE8, Opera 11-12.16
			// Nothing should be selected when empty strings follow ^= or $= or *=
			// The test attribute must be unknown in Opera but "safe" for WinRT
			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
			}

			// Support: IE8
			// Boolean attributes and "value" are not treated correctly
			if ( !div.querySelectorAll("[selected]").length ) {
				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
			}

			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
				rbuggyQSA.push("~=");
			}

			// Webkit/Opera - :checked should return selected option elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":checked").length ) {
				rbuggyQSA.push(":checked");
			}

			// Support: Safari 8+, iOS 8+
			// https://bugs.webkit.org/show_bug.cgi?id=136851
			// In-page `selector#id sibing-combinator selector` fails
			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
				rbuggyQSA.push(".#.+[+~]");
			}
		});

		assert(function( div ) {
			// Support: Windows 8 Native Apps
			// The type and name attributes are restricted during .innerHTML assignment
			var input = document.createElement("input");
			input.setAttribute( "type", "hidden" );
			div.appendChild( input ).setAttribute( "name", "D" );

			// Support: IE8
			// Enforce case-sensitivity of name attribute
			if ( div.querySelectorAll("[name=d]").length ) {
				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
			}

			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
			// IE8 throws error here and will not see later tests
			if ( !div.querySelectorAll(":enabled").length ) {
				rbuggyQSA.push( ":enabled", ":disabled" );
			}

			// Opera 10-11 does not throw on post-comma invalid pseudos
			div.querySelectorAll("*,:x");
			rbuggyQSA.push(",.*:");
		});
	}

	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
		docElem.webkitMatchesSelector ||
		docElem.mozMatchesSelector ||
		docElem.oMatchesSelector ||
		docElem.msMatchesSelector) )) ) {

		assert(function( div ) {
			// Check to see if it's possible to do matchesSelector
			// on a disconnected node (IE 9)
			support.disconnectedMatch = matches.call( div, "div" );

			// This should fail with an exception
			// Gecko does not error, returns false instead
			matches.call( div, "[s!='']:x" );
			rbuggyMatches.push( "!=", pseudos );
		});
	}

	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );

	/* Contains
	---------------------------------------------------------------------- */
	hasCompare = rnative.test( docElem.compareDocumentPosition );

	// Element contains another
	// Purposefully self-exclusive
	// As in, an element does not contain itself
	contains = hasCompare || rnative.test( docElem.contains ) ?
		function( a, b ) {
			var adown = a.nodeType === 9 ? a.documentElement : a,
				bup = b && b.parentNode;
			return a === bup || !!( bup && bup.nodeType === 1 && (
				adown.contains ?
					adown.contains( bup ) :
					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
			));
		} :
		function( a, b ) {
			if ( b ) {
				while ( (b = b.parentNode) ) {
					if ( b === a ) {
						return true;
					}
				}
			}
			return false;
		};

	/* Sorting
	---------------------------------------------------------------------- */

	// Document order sorting
	sortOrder = hasCompare ?
	function( a, b ) {

		// Flag for duplicate removal
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		// Sort on method existence if only one input has compareDocumentPosition
		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
		if ( compare ) {
			return compare;
		}

		// Calculate position if both inputs belong to the same document
		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
			a.compareDocumentPosition( b ) :

			// Otherwise we know they are disconnected
			1;

		// Disconnected nodes
		if ( compare & 1 ||
			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {

			// Choose the first element that is related to our preferred document
			if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
				return -1;
			}
			if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
				return 1;
			}

			// Maintain original order
			return sortInput ?
				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
				0;
		}

		return compare & 4 ? -1 : 1;
	} :
	function( a, b ) {
		// Exit early if the nodes are identical
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		var cur,
			i = 0,
			aup = a.parentNode,
			bup = b.parentNode,
			ap = [ a ],
			bp = [ b ];

		// Parentless nodes are either documents or disconnected
		if ( !aup || !bup ) {
			return a === document ? -1 :
				b === document ? 1 :
				aup ? -1 :
				bup ? 1 :
				sortInput ?
				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
				0;

		// If the nodes are siblings, we can do a quick check
		} else if ( aup === bup ) {
			return siblingCheck( a, b );
		}

		// Otherwise we need full lists of their ancestors for comparison
		cur = a;
		while ( (cur = cur.parentNode) ) {
			ap.unshift( cur );
		}
		cur = b;
		while ( (cur = cur.parentNode) ) {
			bp.unshift( cur );
		}

		// Walk down the tree looking for a discrepancy
		while ( ap[i] === bp[i] ) {
			i++;
		}

		return i ?
			// Do a sibling check if the nodes have a common ancestor
			siblingCheck( ap[i], bp[i] ) :

			// Otherwise nodes in our document sort first
			ap[i] === preferredDoc ? -1 :
			bp[i] === preferredDoc ? 1 :
			0;
	};

	return document;
};

Sizzle.matches = function( expr, elements ) {
	return Sizzle( expr, null, null, elements );
};

Sizzle.matchesSelector = function( elem, expr ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	// Make sure that attribute selectors are quoted
	expr = expr.replace( rattributeQuotes, "='$1']" );

	if ( support.matchesSelector && documentIsHTML &&
		!compilerCache[ expr + " " ] &&
		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {

		try {
			var ret = matches.call( elem, expr );

			// IE 9's matchesSelector returns false on disconnected nodes
			if ( ret || support.disconnectedMatch ||
					// As well, disconnected nodes are said to be in a document
					// fragment in IE 9
					elem.document && elem.document.nodeType !== 11 ) {
				return ret;
			}
		} catch (e) {}
	}

	return Sizzle( expr, document, null, [ elem ] ).length > 0;
};

Sizzle.contains = function( context, elem ) {
	// Set document vars if needed
	if ( ( context.ownerDocument || context ) !== document ) {
		setDocument( context );
	}
	return contains( context, elem );
};

Sizzle.attr = function( elem, name ) {
	// Set document vars if needed
	if ( ( elem.ownerDocument || elem ) !== document ) {
		setDocument( elem );
	}

	var fn = Expr.attrHandle[ name.toLowerCase() ],
		// Don't get fooled by Object.prototype properties (jQuery #13807)
		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
			fn( elem, name, !documentIsHTML ) :
			undefined;

	return val !== undefined ?
		val :
		support.attributes || !documentIsHTML ?
			elem.getAttribute( name ) :
			(val = elem.getAttributeNode(name)) && val.specified ?
				val.value :
				null;
};

Sizzle.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Document sorting and removing duplicates
 * @param {ArrayLike} results
 */
Sizzle.uniqueSort = function( results ) {
	var elem,
		duplicates = [],
		j = 0,
		i = 0;

	// Unless we *know* we can detect duplicates, assume their presence
	hasDuplicate = !support.detectDuplicates;
	sortInput = !support.sortStable && results.slice( 0 );
	results.sort( sortOrder );

	if ( hasDuplicate ) {
		while ( (elem = results[i++]) ) {
			if ( elem === results[ i ] ) {
				j = duplicates.push( i );
			}
		}
		while ( j-- ) {
			results.splice( duplicates[ j ], 1 );
		}
	}

	// Clear input after sorting to release objects
	// See https://github.com/jquery/sizzle/pull/225
	sortInput = null;

	return results;
};

/**
 * Utility function for retrieving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
getText = Sizzle.getText = function( elem ) {
	var node,
		ret = "",
		i = 0,
		nodeType = elem.nodeType;

	if ( !nodeType ) {
		// If no nodeType, this is expected to be an array
		while ( (node = elem[i++]) ) {
			// Do not traverse comment nodes
			ret += getText( node );
		}
	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
		// Use textContent for elements
		// innerText usage removed for consistency of new lines (jQuery #11153)
		if ( typeof elem.textContent === "string" ) {
			return elem.textContent;
		} else {
			// Traverse its children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				ret += getText( elem );
			}
		}
	} else if ( nodeType === 3 || nodeType === 4 ) {
		return elem.nodeValue;
	}
	// Do not include comment or processing instruction nodes

	return ret;
};

Expr = Sizzle.selectors = {

	// Can be adjusted by the user
	cacheLength: 50,

	createPseudo: markFunction,

	match: matchExpr,

	attrHandle: {},

	find: {},

	relative: {
		">": { dir: "parentNode", first: true },
		" ": { dir: "parentNode" },
		"+": { dir: "previousSibling", first: true },
		"~": { dir: "previousSibling" }
	},

	preFilter: {
		"ATTR": function( match ) {
			match[1] = match[1].replace( runescape, funescape );

			// Move the given value to match[3] whether quoted or unquoted
			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );

			if ( match[2] === "~=" ) {
				match[3] = " " + match[3] + " ";
			}

			return match.slice( 0, 4 );
		},

		"CHILD": function( match ) {
			/* matches from matchExpr["CHILD"]
				1 type (only|nth|...)
				2 what (child|of-type)
				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
				4 xn-component of xn+y argument ([+-]?\d*n|)
				5 sign of xn-component
				6 x of xn-component
				7 sign of y-component
				8 y of y-component
			*/
			match[1] = match[1].toLowerCase();

			if ( match[1].slice( 0, 3 ) === "nth" ) {
				// nth-* requires argument
				if ( !match[3] ) {
					Sizzle.error( match[0] );
				}

				// numeric x and y parameters for Expr.filter.CHILD
				// remember that false/true cast respectively to 0/1
				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );

			// other types prohibit arguments
			} else if ( match[3] ) {
				Sizzle.error( match[0] );
			}

			return match;
		},

		"PSEUDO": function( match ) {
			var excess,
				unquoted = !match[6] && match[2];

			if ( matchExpr["CHILD"].test( match[0] ) ) {
				return null;
			}

			// Accept quoted arguments as-is
			if ( match[3] ) {
				match[2] = match[4] || match[5] || "";

			// Strip excess characters from unquoted arguments
			} else if ( unquoted && rpseudo.test( unquoted ) &&
				// Get excess from tokenize (recursively)
				(excess = tokenize( unquoted, true )) &&
				// advance to the next closing parenthesis
				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {

				// excess is a negative index
				match[0] = match[0].slice( 0, excess );
				match[2] = unquoted.slice( 0, excess );
			}

			// Return only captures needed by the pseudo filter method (type and argument)
			return match.slice( 0, 3 );
		}
	},

	filter: {

		"TAG": function( nodeNameSelector ) {
			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
			return nodeNameSelector === "*" ?
				function() { return true; } :
				function( elem ) {
					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
				};
		},

		"CLASS": function( className ) {
			var pattern = classCache[ className + " " ];

			return pattern ||
				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
				classCache( className, function( elem ) {
					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
				});
		},

		"ATTR": function( name, operator, check ) {
			return function( elem ) {
				var result = Sizzle.attr( elem, name );

				if ( result == null ) {
					return operator === "!=";
				}
				if ( !operator ) {
					return true;
				}

				result += "";

				return operator === "=" ? result === check :
					operator === "!=" ? result !== check :
					operator === "^=" ? check && result.indexOf( check ) === 0 :
					operator === "*=" ? check && result.indexOf( check ) > -1 :
					operator === "$=" ? check && result.slice( -check.length ) === check :
					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
					false;
			};
		},

		"CHILD": function( type, what, argument, first, last ) {
			var simple = type.slice( 0, 3 ) !== "nth",
				forward = type.slice( -4 ) !== "last",
				ofType = what === "of-type";

			return first === 1 && last === 0 ?

				// Shortcut for :nth-*(n)
				function( elem ) {
					return !!elem.parentNode;
				} :

				function( elem, context, xml ) {
					var cache, uniqueCache, outerCache, node, nodeIndex, start,
						dir = simple !== forward ? "nextSibling" : "previousSibling",
						parent = elem.parentNode,
						name = ofType && elem.nodeName.toLowerCase(),
						useCache = !xml && !ofType,
						diff = false;

					if ( parent ) {

						// :(first|last|only)-(child|of-type)
						if ( simple ) {
							while ( dir ) {
								node = elem;
								while ( (node = node[ dir ]) ) {
									if ( ofType ?
										node.nodeName.toLowerCase() === name :
										node.nodeType === 1 ) {

										return false;
									}
								}
								// Reverse direction for :only-* (if we haven't yet done so)
								start = dir = type === "only" && !start && "nextSibling";
							}
							return true;
						}

						start = [ forward ? parent.firstChild : parent.lastChild ];

						// non-xml :nth-child(...) stores cache data on `parent`
						if ( forward && useCache ) {

							// Seek `elem` from a previously-cached index

							// ...in a gzip-friendly way
							node = parent;
							outerCache = node[ expando ] || (node[ expando ] = {});

							// Support: IE <9 only
							// Defend against cloned attroperties (jQuery gh-1709)
							uniqueCache = outerCache[ node.uniqueID ] ||
								(outerCache[ node.uniqueID ] = {});

							cache = uniqueCache[ type ] || [];
							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
							diff = nodeIndex && cache[ 2 ];
							node = nodeIndex && parent.childNodes[ nodeIndex ];

							while ( (node = ++nodeIndex && node && node[ dir ] ||

								// Fallback to seeking `elem` from the start
								(diff = nodeIndex = 0) || start.pop()) ) {

								// When found, cache indexes on `parent` and break
								if ( node.nodeType === 1 && ++diff && node === elem ) {
									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
									break;
								}
							}

						} else {
							// Use previously-cached element index if available
							if ( useCache ) {
								// ...in a gzip-friendly way
								node = elem;
								outerCache = node[ expando ] || (node[ expando ] = {});

								// Support: IE <9 only
								// Defend against cloned attroperties (jQuery gh-1709)
								uniqueCache = outerCache[ node.uniqueID ] ||
									(outerCache[ node.uniqueID ] = {});

								cache = uniqueCache[ type ] || [];
								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
								diff = nodeIndex;
							}

							// xml :nth-child(...)
							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
							if ( diff === false ) {
								// Use the same loop as above to seek `elem` from the start
								while ( (node = ++nodeIndex && node && node[ dir ] ||
									(diff = nodeIndex = 0) || start.pop()) ) {

									if ( ( ofType ?
										node.nodeName.toLowerCase() === name :
										node.nodeType === 1 ) &&
										++diff ) {

										// Cache the index of each encountered element
										if ( useCache ) {
											outerCache = node[ expando ] || (node[ expando ] = {});

											// Support: IE <9 only
											// Defend against cloned attroperties (jQuery gh-1709)
											uniqueCache = outerCache[ node.uniqueID ] ||
												(outerCache[ node.uniqueID ] = {});

											uniqueCache[ type ] = [ dirruns, diff ];
										}

										if ( node === elem ) {
											break;
										}
									}
								}
							}
						}

						// Incorporate the offset, then check against cycle size
						diff -= last;
						return diff === first || ( diff % first === 0 && diff / first >= 0 );
					}
				};
		},

		"PSEUDO": function( pseudo, argument ) {
			// pseudo-class names are case-insensitive
			// http://www.w3.org/TR/selectors/#pseudo-classes
			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
			// Remember that setFilters inherits from pseudos
			var args,
				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
					Sizzle.error( "unsupported pseudo: " + pseudo );

			// The user may use createPseudo to indicate that
			// arguments are needed to create the filter function
			// just as Sizzle does
			if ( fn[ expando ] ) {
				return fn( argument );
			}

			// But maintain support for old signatures
			if ( fn.length > 1 ) {
				args = [ pseudo, pseudo, "", argument ];
				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
					markFunction(function( seed, matches ) {
						var idx,
							matched = fn( seed, argument ),
							i = matched.length;
						while ( i-- ) {
							idx = indexOf( seed, matched[i] );
							seed[ idx ] = !( matches[ idx ] = matched[i] );
						}
					}) :
					function( elem ) {
						return fn( elem, 0, args );
					};
			}

			return fn;
		}
	},

	pseudos: {
		// Potentially complex pseudos
		"not": markFunction(function( selector ) {
			// Trim the selector passed to compile
			// to avoid treating leading and trailing
			// spaces as combinators
			var input = [],
				results = [],
				matcher = compile( selector.replace( rtrim, "$1" ) );

			return matcher[ expando ] ?
				markFunction(function( seed, matches, context, xml ) {
					var elem,
						unmatched = matcher( seed, null, xml, [] ),
						i = seed.length;

					// Match elements unmatched by `matcher`
					while ( i-- ) {
						if ( (elem = unmatched[i]) ) {
							seed[i] = !(matches[i] = elem);
						}
					}
				}) :
				function( elem, context, xml ) {
					input[0] = elem;
					matcher( input, null, xml, results );
					// Don't keep the element (issue #299)
					input[0] = null;
					return !results.pop();
				};
		}),

		"has": markFunction(function( selector ) {
			return function( elem ) {
				return Sizzle( selector, elem ).length > 0;
			};
		}),

		"contains": markFunction(function( text ) {
			text = text.replace( runescape, funescape );
			return function( elem ) {
				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
			};
		}),

		// "Whether an element is represented by a :lang() selector
		// is based solely on the element's language value
		// being equal to the identifier C,
		// or beginning with the identifier C immediately followed by "-".
		// The matching of C against the element's language value is performed case-insensitively.
		// The identifier C does not have to be a valid language name."
		// http://www.w3.org/TR/selectors/#lang-pseudo
		"lang": markFunction( function( lang ) {
			// lang value must be a valid identifier
			if ( !ridentifier.test(lang || "") ) {
				Sizzle.error( "unsupported lang: " + lang );
			}
			lang = lang.replace( runescape, funescape ).toLowerCase();
			return function( elem ) {
				var elemLang;
				do {
					if ( (elemLang = documentIsHTML ?
						elem.lang :
						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {

						elemLang = elemLang.toLowerCase();
						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
					}
				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
				return false;
			};
		}),

		// Miscellaneous
		"target": function( elem ) {
			var hash = window.location && window.location.hash;
			return hash && hash.slice( 1 ) === elem.id;
		},

		"root": function( elem ) {
			return elem === docElem;
		},

		"focus": function( elem ) {
			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
		},

		// Boolean properties
		"enabled": function( elem ) {
			return elem.disabled === false;
		},

		"disabled": function( elem ) {
			return elem.disabled === true;
		},

		"checked": function( elem ) {
			// In CSS3, :checked should return both checked and selected elements
			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
			var nodeName = elem.nodeName.toLowerCase();
			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
		},

		"selected": function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}

			return elem.selected === true;
		},

		// Contents
		"empty": function( elem ) {
			// http://www.w3.org/TR/selectors/#empty-pseudo
			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
			//   but not by others (comment: 8; processing instruction: 7; etc.)
			// nodeType < 6 works because attributes (2) do not appear as children
			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
				if ( elem.nodeType < 6 ) {
					return false;
				}
			}
			return true;
		},

		"parent": function( elem ) {
			return !Expr.pseudos["empty"]( elem );
		},

		// Element/input types
		"header": function( elem ) {
			return rheader.test( elem.nodeName );
		},

		"input": function( elem ) {
			return rinputs.test( elem.nodeName );
		},

		"button": function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return name === "input" && elem.type === "button" || name === "button";
		},

		"text": function( elem ) {
			var attr;
			return elem.nodeName.toLowerCase() === "input" &&
				elem.type === "text" &&

				// Support: IE<8
				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
		},

		// Position-in-collection
		"first": createPositionalPseudo(function() {
			return [ 0 ];
		}),

		"last": createPositionalPseudo(function( matchIndexes, length ) {
			return [ length - 1 ];
		}),

		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
			return [ argument < 0 ? argument + length : argument ];
		}),

		"even": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 0;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"odd": createPositionalPseudo(function( matchIndexes, length ) {
			var i = 1;
			for ( ; i < length; i += 2 ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; --i >= 0; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		}),

		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
			var i = argument < 0 ? argument + length : argument;
			for ( ; ++i < length; ) {
				matchIndexes.push( i );
			}
			return matchIndexes;
		})
	}
};

Expr.pseudos["nth"] = Expr.pseudos["eq"];

// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
	Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
	Expr.pseudos[ i ] = createButtonPseudo( i );
}

// Easy API for creating new setFilters
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();

tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
	var matched, match, tokens, type,
		soFar, groups, preFilters,
		cached = tokenCache[ selector + " " ];

	if ( cached ) {
		return parseOnly ? 0 : cached.slice( 0 );
	}

	soFar = selector;
	groups = [];
	preFilters = Expr.preFilter;

	while ( soFar ) {

		// Comma and first run
		if ( !matched || (match = rcomma.exec( soFar )) ) {
			if ( match ) {
				// Don't consume trailing commas as valid
				soFar = soFar.slice( match[0].length ) || soFar;
			}
			groups.push( (tokens = []) );
		}

		matched = false;

		// Combinators
		if ( (match = rcombinators.exec( soFar )) ) {
			matched = match.shift();
			tokens.push({
				value: matched,
				// Cast descendant combinators to space
				type: match[0].replace( rtrim, " " )
			});
			soFar = soFar.slice( matched.length );
		}

		// Filters
		for ( type in Expr.filter ) {
			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
				(match = preFilters[ type ]( match ))) ) {
				matched = match.shift();
				tokens.push({
					value: matched,
					type: type,
					matches: match
				});
				soFar = soFar.slice( matched.length );
			}
		}

		if ( !matched ) {
			break;
		}
	}

	// Return the length of the invalid excess
	// if we're just parsing
	// Otherwise, throw an error or return tokens
	return parseOnly ?
		soFar.length :
		soFar ?
			Sizzle.error( selector ) :
			// Cache the tokens
			tokenCache( selector, groups ).slice( 0 );
};

function toSelector( tokens ) {
	var i = 0,
		len = tokens.length,
		selector = "";
	for ( ; i < len; i++ ) {
		selector += tokens[i].value;
	}
	return selector;
}

function addCombinator( matcher, combinator, base ) {
	var dir = combinator.dir,
		checkNonElements = base && dir === "parentNode",
		doneName = done++;

	return combinator.first ?
		// Check against closest ancestor/preceding element
		function( elem, context, xml ) {
			while ( (elem = elem[ dir ]) ) {
				if ( elem.nodeType === 1 || checkNonElements ) {
					return matcher( elem, context, xml );
				}
			}
		} :

		// Check against all ancestor/preceding elements
		function( elem, context, xml ) {
			var oldCache, uniqueCache, outerCache,
				newCache = [ dirruns, doneName ];

			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
			if ( xml ) {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						if ( matcher( elem, context, xml ) ) {
							return true;
						}
					}
				}
			} else {
				while ( (elem = elem[ dir ]) ) {
					if ( elem.nodeType === 1 || checkNonElements ) {
						outerCache = elem[ expando ] || (elem[ expando ] = {});

						// Support: IE <9 only
						// Defend against cloned attroperties (jQuery gh-1709)
						uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});

						if ( (oldCache = uniqueCache[ dir ]) &&
							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {

							// Assign to newCache so results back-propagate to previous elements
							return (newCache[ 2 ] = oldCache[ 2 ]);
						} else {
							// Reuse newcache so results back-propagate to previous elements
							uniqueCache[ dir ] = newCache;

							// A match means we're done; a fail means we have to keep checking
							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
								return true;
							}
						}
					}
				}
			}
		};
}

function elementMatcher( matchers ) {
	return matchers.length > 1 ?
		function( elem, context, xml ) {
			var i = matchers.length;
			while ( i-- ) {
				if ( !matchers[i]( elem, context, xml ) ) {
					return false;
				}
			}
			return true;
		} :
		matchers[0];
}

function multipleContexts( selector, contexts, results ) {
	var i = 0,
		len = contexts.length;
	for ( ; i < len; i++ ) {
		Sizzle( selector, contexts[i], results );
	}
	return results;
}

function condense( unmatched, map, filter, context, xml ) {
	var elem,
		newUnmatched = [],
		i = 0,
		len = unmatched.length,
		mapped = map != null;

	for ( ; i < len; i++ ) {
		if ( (elem = unmatched[i]) ) {
			if ( !filter || filter( elem, context, xml ) ) {
				newUnmatched.push( elem );
				if ( mapped ) {
					map.push( i );
				}
			}
		}
	}

	return newUnmatched;
}

function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
	if ( postFilter && !postFilter[ expando ] ) {
		postFilter = setMatcher( postFilter );
	}
	if ( postFinder && !postFinder[ expando ] ) {
		postFinder = setMatcher( postFinder, postSelector );
	}
	return markFunction(function( seed, results, context, xml ) {
		var temp, i, elem,
			preMap = [],
			postMap = [],
			preexisting = results.length,

			// Get initial elements from seed or context
			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),

			// Prefilter to get matcher input, preserving a map for seed-results synchronization
			matcherIn = preFilter && ( seed || !selector ) ?
				condense( elems, preMap, preFilter, context, xml ) :
				elems,

			matcherOut = matcher ?
				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

					// ...intermediate processing is necessary
					[] :

					// ...otherwise use results directly
					results :
				matcherIn;

		// Find primary matches
		if ( matcher ) {
			matcher( matcherIn, matcherOut, context, xml );
		}

		// Apply postFilter
		if ( postFilter ) {
			temp = condense( matcherOut, postMap );
			postFilter( temp, [], context, xml );

			// Un-match failing elements by moving them back to matcherIn
			i = temp.length;
			while ( i-- ) {
				if ( (elem = temp[i]) ) {
					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
				}
			}
		}

		if ( seed ) {
			if ( postFinder || preFilter ) {
				if ( postFinder ) {
					// Get the final matcherOut by condensing this intermediate into postFinder contexts
					temp = [];
					i = matcherOut.length;
					while ( i-- ) {
						if ( (elem = matcherOut[i]) ) {
							// Restore matcherIn since elem is not yet a final match
							temp.push( (matcherIn[i] = elem) );
						}
					}
					postFinder( null, (matcherOut = []), temp, xml );
				}

				// Move matched elements from seed to results to keep them synchronized
				i = matcherOut.length;
				while ( i-- ) {
					if ( (elem = matcherOut[i]) &&
						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {

						seed[temp] = !(results[temp] = elem);
					}
				}
			}

		// Add elements to results, through postFinder if defined
		} else {
			matcherOut = condense(
				matcherOut === results ?
					matcherOut.splice( preexisting, matcherOut.length ) :
					matcherOut
			);
			if ( postFinder ) {
				postFinder( null, results, matcherOut, xml );
			} else {
				push.apply( results, matcherOut );
			}
		}
	});
}

function matcherFromTokens( tokens ) {
	var checkContext, matcher, j,
		len = tokens.length,
		leadingRelative = Expr.relative[ tokens[0].type ],
		implicitRelative = leadingRelative || Expr.relative[" "],
		i = leadingRelative ? 1 : 0,

		// The foundational matcher ensures that elements are reachable from top-level context(s)
		matchContext = addCombinator( function( elem ) {
			return elem === checkContext;
		}, implicitRelative, true ),
		matchAnyContext = addCombinator( function( elem ) {
			return indexOf( checkContext, elem ) > -1;
		}, implicitRelative, true ),
		matchers = [ function( elem, context, xml ) {
			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
				(checkContext = context).nodeType ?
					matchContext( elem, context, xml ) :
					matchAnyContext( elem, context, xml ) );
			// Avoid hanging onto element (issue #299)
			checkContext = null;
			return ret;
		} ];

	for ( ; i < len; i++ ) {
		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
		} else {
			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );

			// Return special upon seeing a positional matcher
			if ( matcher[ expando ] ) {
				// Find the next relative operator (if any) for proper handling
				j = ++i;
				for ( ; j < len; j++ ) {
					if ( Expr.relative[ tokens[j].type ] ) {
						break;
					}
				}
				return setMatcher(
					i > 1 && elementMatcher( matchers ),
					i > 1 && toSelector(
						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
					).replace( rtrim, "$1" ),
					matcher,
					i < j && matcherFromTokens( tokens.slice( i, j ) ),
					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
					j < len && toSelector( tokens )
				);
			}
			matchers.push( matcher );
		}
	}

	return elementMatcher( matchers );
}

function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
	var bySet = setMatchers.length > 0,
		byElement = elementMatchers.length > 0,
		superMatcher = function( seed, context, xml, results, outermost ) {
			var elem, j, matcher,
				matchedCount = 0,
				i = "0",
				unmatched = seed && [],
				setMatched = [],
				contextBackup = outermostContext,
				// We must always have either seed elements or outermost context
				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
				// Use integer dirruns iff this is the outermost matcher
				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
				len = elems.length;

			if ( outermost ) {
				outermostContext = context === document || context || outermost;
			}

			// Add elements passing elementMatchers directly to results
			// Support: IE<9, Safari
			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
				if ( byElement && elem ) {
					j = 0;
					if ( !context && elem.ownerDocument !== document ) {
						setDocument( elem );
						xml = !documentIsHTML;
					}
					while ( (matcher = elementMatchers[j++]) ) {
						if ( matcher( elem, context || document, xml) ) {
							results.push( elem );
							break;
						}
					}
					if ( outermost ) {
						dirruns = dirrunsUnique;
					}
				}

				// Track unmatched elements for set filters
				if ( bySet ) {
					// They will have gone through all possible matchers
					if ( (elem = !matcher && elem) ) {
						matchedCount--;
					}

					// Lengthen the array for every element, matched or not
					if ( seed ) {
						unmatched.push( elem );
					}
				}
			}

			// `i` is now the count of elements visited above, and adding it to `matchedCount`
			// makes the latter nonnegative.
			matchedCount += i;

			// Apply set filters to unmatched elements
			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
			// no element matchers and no seed.
			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
			// numerically zero.
			if ( bySet && i !== matchedCount ) {
				j = 0;
				while ( (matcher = setMatchers[j++]) ) {
					matcher( unmatched, setMatched, context, xml );
				}

				if ( seed ) {
					// Reintegrate element matches to eliminate the need for sorting
					if ( matchedCount > 0 ) {
						while ( i-- ) {
							if ( !(unmatched[i] || setMatched[i]) ) {
								setMatched[i] = pop.call( results );
							}
						}
					}

					// Discard index placeholder values to get only actual matches
					setMatched = condense( setMatched );
				}

				// Add matches to results
				push.apply( results, setMatched );

				// Seedless set matches succeeding multiple successful matchers stipulate sorting
				if ( outermost && !seed && setMatched.length > 0 &&
					( matchedCount + setMatchers.length ) > 1 ) {

					Sizzle.uniqueSort( results );
				}
			}

			// Override manipulation of globals by nested matchers
			if ( outermost ) {
				dirruns = dirrunsUnique;
				outermostContext = contextBackup;
			}

			return unmatched;
		};

	return bySet ?
		markFunction( superMatcher ) :
		superMatcher;
}

compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
	var i,
		setMatchers = [],
		elementMatchers = [],
		cached = compilerCache[ selector + " " ];

	if ( !cached ) {
		// Generate a function of recursive functions that can be used to check each element
		if ( !match ) {
			match = tokenize( selector );
		}
		i = match.length;
		while ( i-- ) {
			cached = matcherFromTokens( match[i] );
			if ( cached[ expando ] ) {
				setMatchers.push( cached );
			} else {
				elementMatchers.push( cached );
			}
		}

		// Cache the compiled function
		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );

		// Save selector and tokenization
		cached.selector = selector;
	}
	return cached;
};

/**
 * A low-level selection function that works with Sizzle's compiled
 *  selector functions
 * @param {String|Function} selector A selector or a pre-compiled
 *  selector function built with Sizzle.compile
 * @param {Element} context
 * @param {Array} [results]
 * @param {Array} [seed] A set of elements to match against
 */
select = Sizzle.select = function( selector, context, results, seed ) {
	var i, tokens, token, type, find,
		compiled = typeof selector === "function" && selector,
		match = !seed && tokenize( (selector = compiled.selector || selector) );

	results = results || [];

	// Try to minimize operations if there is only one selector in the list and no seed
	// (the latter of which guarantees us context)
	if ( match.length === 1 ) {

		// Reduce context if the leading compound selector is an ID
		tokens = match[0] = match[0].slice( 0 );
		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
				support.getById && context.nodeType === 9 && documentIsHTML &&
				Expr.relative[ tokens[1].type ] ) {

			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
			if ( !context ) {
				return results;

			// Precompiled matchers will still verify ancestry, so step up a level
			} else if ( compiled ) {
				context = context.parentNode;
			}

			selector = selector.slice( tokens.shift().value.length );
		}

		// Fetch a seed set for right-to-left matching
		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
		while ( i-- ) {
			token = tokens[i];

			// Abort if we hit a combinator
			if ( Expr.relative[ (type = token.type) ] ) {
				break;
			}
			if ( (find = Expr.find[ type ]) ) {
				// Search, expanding context for leading sibling combinators
				if ( (seed = find(
					token.matches[0].replace( runescape, funescape ),
					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
				)) ) {

					// If seed is empty or no tokens remain, we can return early
					tokens.splice( i, 1 );
					selector = seed.length && toSelector( tokens );
					if ( !selector ) {
						push.apply( results, seed );
						return results;
					}

					break;
				}
			}
		}
	}

	// Compile and execute a filtering function if one is not provided
	// Provide `match` to avoid retokenization if we modified the selector above
	( compiled || compile( selector, match ) )(
		seed,
		context,
		!documentIsHTML,
		results,
		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
	);
	return results;
};

// One-time assignments

// Sort stability
support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;

// Support: Chrome 14-35+
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;

// Initialize against the default document
setDocument();

// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert(function( div1 ) {
	// Should return 1, but returns 4 (following)
	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
});

// Support: IE<8
// Prevent attribute/property "interpolation"
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
if ( !assert(function( div ) {
	div.innerHTML = "<a href='#'></a>";
	return div.firstChild.getAttribute("href") === "#" ;
}) ) {
	addHandle( "type|href|height|width", function( elem, name, isXML ) {
		if ( !isXML ) {
			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
		}
	});
}

// Support: IE<9
// Use defaultValue in place of getAttribute("value")
if ( !support.attributes || !assert(function( div ) {
	div.innerHTML = "<input/>";
	div.firstChild.setAttribute( "value", "" );
	return div.firstChild.getAttribute( "value" ) === "";
}) ) {
	addHandle( "value", function( elem, name, isXML ) {
		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
			return elem.defaultValue;
		}
	});
}

// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
if ( !assert(function( div ) {
	return div.getAttribute("disabled") == null;
}) ) {
	addHandle( booleans, function( elem, name, isXML ) {
		var val;
		if ( !isXML ) {
			return elem[ name ] === true ? name.toLowerCase() :
					(val = elem.getAttributeNode( name )) && val.specified ?
					val.value :
				null;
		}
	});
}

// EXPOSE
if ( true ) {
	!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { return Sizzle; }).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
// Sizzle requires that there be a global window in Common-JS like environments
} else {}
// EXPOSE

})( window );
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(192),
	__webpack_require__(572),
	__webpack_require__(573),
	__webpack_require__(274),
	__webpack_require__(52),
	__webpack_require__(276),
	__webpack_require__(42)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, indexOf, dir, siblings, rneedsContext ) {

var rparentsprev = /^(?:parents|prev(?:Until|All))/,

	// Methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique = {
		children: true,
		contents: true,
		next: true,
		prev: true
	};

jQuery.fn.extend( {
	has: function( target ) {
		var targets = jQuery( target, this ),
			l = targets.length;

		return this.filter( function() {
			var i = 0;
			for ( ; i < l; i++ ) {
				if ( jQuery.contains( this, targets[ i ] ) ) {
					return true;
				}
			}
		} );
	},

	closest: function( selectors, context ) {
		var cur,
			i = 0,
			l = this.length,
			matched = [],
			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
				jQuery( selectors, context || this.context ) :
				0;

		for ( ; i < l; i++ ) {
			for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {

				// Always skip document fragments
				if ( cur.nodeType < 11 && ( pos ?
					pos.index( cur ) > -1 :

					// Don't pass non-elements to Sizzle
					cur.nodeType === 1 &&
						jQuery.find.matchesSelector( cur, selectors ) ) ) {

					matched.push( cur );
					break;
				}
			}
		}

		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
	},

	// Determine the position of an element within the set
	index: function( elem ) {

		// No argument, return index in parent
		if ( !elem ) {
			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
		}

		// Index in selector
		if ( typeof elem === "string" ) {
			return indexOf.call( jQuery( elem ), this[ 0 ] );
		}

		// Locate the position of the desired element
		return indexOf.call( this,

			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[ 0 ] : elem
		);
	},

	add: function( selector, context ) {
		return this.pushStack(
			jQuery.uniqueSort(
				jQuery.merge( this.get(), jQuery( selector, context ) )
			)
		);
	},

	addBack: function( selector ) {
		return this.add( selector == null ?
			this.prevObject : this.prevObject.filter( selector )
		);
	}
} );

function sibling( cur, dir ) {
	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
	return cur;
}

jQuery.each( {
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return dir( elem, "parentNode" );
	},
	parentsUntil: function( elem, i, until ) {
		return dir( elem, "parentNode", until );
	},
	next: function( elem ) {
		return sibling( elem, "nextSibling" );
	},
	prev: function( elem ) {
		return sibling( elem, "previousSibling" );
	},
	nextAll: function( elem ) {
		return dir( elem, "nextSibling" );
	},
	prevAll: function( elem ) {
		return dir( elem, "previousSibling" );
	},
	nextUntil: function( elem, i, until ) {
		return dir( elem, "nextSibling", until );
	},
	prevUntil: function( elem, i, until ) {
		return dir( elem, "previousSibling", until );
	},
	siblings: function( elem ) {
		return siblings( ( elem.parentNode || {} ).firstChild, elem );
	},
	children: function( elem ) {
		return siblings( elem.firstChild );
	},
	contents: function( elem ) {
		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function( until, selector ) {
		var matched = jQuery.map( this, fn, until );

		if ( name.slice( -5 ) !== "Until" ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			matched = jQuery.filter( selector, matched );
		}

		if ( this.length > 1 ) {

			// Remove duplicates
			if ( !guaranteedUnique[ name ] ) {
				jQuery.uniqueSort( matched );
			}

			// Reverse order for parents* and prev-derivatives
			if ( rparentsprev.test( name ) ) {
				matched.reverse();
			}
		}

		return this.pushStack( matched );
	};
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

return function( elem, dir, until ) {
	var matched = [],
		truncate = until !== undefined;

	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
		if ( elem.nodeType === 1 ) {
			if ( truncate && jQuery( elem ).is( until ) ) {
				break;
			}
			matched.push( elem );
		}
	}
	return matched;
};

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

return function( n, elem ) {
	var matched = [];

	for ( ; n; n = n.nextSibling ) {
		if ( n.nodeType === 1 && n !== elem ) {
			matched.push( n );
		}
	}

	return matched;
};

}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(42)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {
	return jQuery.expr.match.needsContext;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Initialize a jQuery object
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(275),
	__webpack_require__(276)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document, rsingleTag ) {

// A central reference to the root jQuery(document)
var rootjQuery,

	// A simple way to check for HTML strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	// Strict HTML recognition (#11290: must start with <)
	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

	init = jQuery.fn.init = function( selector, context, root ) {
		var match, elem;

		// HANDLE: $(""), $(null), $(undefined), $(false)
		if ( !selector ) {
			return this;
		}

		// Method init() accepts an alternate rootjQuery
		// so migrate can support jQuery.sub (gh-2101)
		root = root || rootjQuery;

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			if ( selector[ 0 ] === "<" &&
				selector[ selector.length - 1 ] === ">" &&
				selector.length >= 3 ) {

				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				match = rquickExpr.exec( selector );
			}

			// Match html or make sure no context is specified for #id
			if ( match && ( match[ 1 ] || !context ) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[ 1 ] ) {
					context = context instanceof jQuery ? context[ 0 ] : context;

					// Option to run scripts is true for back-compat
					// Intentionally let the error be thrown if parseHTML is not present
					jQuery.merge( this, jQuery.parseHTML(
						match[ 1 ],
						context && context.nodeType ? context.ownerDocument || context : document,
						true
					) );

					// HANDLE: $(html, props)
					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
						for ( match in context ) {

							// Properties of context are called as methods if possible
							if ( jQuery.isFunction( this[ match ] ) ) {
								this[ match ]( context[ match ] );

							// ...and otherwise set as attributes
							} else {
								this.attr( match, context[ match ] );
							}
						}
					}

					return this;

				// HANDLE: $(#id)
				} else {
					elem = document.getElementById( match[ 2 ] );

					// Support: Blackberry 4.6
					// gEBID returns nodes no longer in the document (#6963)
					if ( elem && elem.parentNode ) {

						// Inject the element directly into the jQuery object
						this.length = 1;
						this[ 0 ] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || root ).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(DOMElement)
		} else if ( selector.nodeType ) {
			this.context = this[ 0 ] = selector;
			this.length = 1;
			return this;

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return root.ready !== undefined ?
				root.ready( selector ) :

				// Execute immediately if ready is not present
				selector( jQuery );
		}

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	};

// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

// Initialize central reference
rootjQuery = jQuery( document );

return init;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

	// Match a standalone tag
	return ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(192),
	__webpack_require__(274),
	__webpack_require__(42)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, indexOf, rneedsContext ) {

var risSimple = /^.[^:#\[\.,]*$/;

// Implement the identical functionality for filter and not
function winnow( elements, qualifier, not ) {
	if ( jQuery.isFunction( qualifier ) ) {
		return jQuery.grep( elements, function( elem, i ) {
			/* jshint -W018 */
			return !!qualifier.call( elem, i, elem ) !== not;
		} );

	}

	if ( qualifier.nodeType ) {
		return jQuery.grep( elements, function( elem ) {
			return ( elem === qualifier ) !== not;
		} );

	}

	if ( typeof qualifier === "string" ) {
		if ( risSimple.test( qualifier ) ) {
			return jQuery.filter( qualifier, elements, not );
		}

		qualifier = jQuery.filter( qualifier, elements );
	}

	return jQuery.grep( elements, function( elem ) {
		return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
	} );
}

jQuery.filter = function( expr, elems, not ) {
	var elem = elems[ 0 ];

	if ( not ) {
		expr = ":not(" + expr + ")";
	}

	return elems.length === 1 && elem.nodeType === 1 ?
		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
			return elem.nodeType === 1;
		} ) );
};

jQuery.fn.extend( {
	find: function( selector ) {
		var i,
			len = this.length,
			ret = [],
			self = this;

		if ( typeof selector !== "string" ) {
			return this.pushStack( jQuery( selector ).filter( function() {
				for ( i = 0; i < len; i++ ) {
					if ( jQuery.contains( self[ i ], this ) ) {
						return true;
					}
				}
			} ) );
		}

		for ( i = 0; i < len; i++ ) {
			jQuery.find( selector, self[ i ], ret );
		}

		// Needed because $( selector, context ) becomes $( context ).find( selector )
		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
		ret.selector = this.selector ? this.selector + " " + selector : selector;
		return ret;
	},
	filter: function( selector ) {
		return this.pushStack( winnow( this, selector || [], false ) );
	},
	not: function( selector ) {
		return this.pushStack( winnow( this, selector || [], true ) );
	},
	is: function( selector ) {
		return !!winnow(
			this,

			// If this is a positional/relative selector, check membership in the returned set
			// so $("p:first").is("p:last") won't return true for a doc with two "p".
			typeof selector === "string" && rneedsContext.test( selector ) ?
				jQuery( selector ) :
				selector || [],
			false
		).length;
	}
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(82)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, rnotwhite ) {

// Convert String-formatted options into Object-formatted ones
function createOptions( options ) {
	var object = {};
	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
		object[ flag ] = true;
	} );
	return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *	options: an optional list of space-separated options that will change how
 *			the callback list behaves or a more traditional option object
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible options:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( options ) {

	// Convert options from String-formatted to Object-formatted if needed
	// (we check in cache first)
	options = typeof options === "string" ?
		createOptions( options ) :
		jQuery.extend( {}, options );

	var // Flag to know if list is currently firing
		firing,

		// Last fire value for non-forgettable lists
		memory,

		// Flag to know if list was already fired
		fired,

		// Flag to prevent firing
		locked,

		// Actual callback list
		list = [],

		// Queue of execution data for repeatable lists
		queue = [],

		// Index of currently firing callback (modified by add/remove as needed)
		firingIndex = -1,

		// Fire callbacks
		fire = function() {

			// Enforce single-firing
			locked = options.once;

			// Execute callbacks for all pending executions,
			// respecting firingIndex overrides and runtime changes
			fired = firing = true;
			for ( ; queue.length; firingIndex = -1 ) {
				memory = queue.shift();
				while ( ++firingIndex < list.length ) {

					// Run callback and check for early termination
					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
						options.stopOnFalse ) {

						// Jump to end and forget the data so .add doesn't re-fire
						firingIndex = list.length;
						memory = false;
					}
				}
			}

			// Forget the data if we're done with it
			if ( !options.memory ) {
				memory = false;
			}

			firing = false;

			// Clean up if we're done firing for good
			if ( locked ) {

				// Keep an empty list if we have data for future add calls
				if ( memory ) {
					list = [];

				// Otherwise, this object is spent
				} else {
					list = "";
				}
			}
		},

		// Actual Callbacks object
		self = {

			// Add a callback or a collection of callbacks to the list
			add: function() {
				if ( list ) {

					// If we have memory from a past run, we should fire after adding
					if ( memory && !firing ) {
						firingIndex = list.length - 1;
						queue.push( memory );
					}

					( function add( args ) {
						jQuery.each( args, function( _, arg ) {
							if ( jQuery.isFunction( arg ) ) {
								if ( !options.unique || !self.has( arg ) ) {
									list.push( arg );
								}
							} else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {

								// Inspect recursively
								add( arg );
							}
						} );
					} )( arguments );

					if ( memory && !firing ) {
						fire();
					}
				}
				return this;
			},

			// Remove a callback from the list
			remove: function() {
				jQuery.each( arguments, function( _, arg ) {
					var index;
					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
						list.splice( index, 1 );

						// Handle firing indexes
						if ( index <= firingIndex ) {
							firingIndex--;
						}
					}
				} );
				return this;
			},

			// Check if a given callback is in the list.
			// If no argument is given, return whether or not list has callbacks attached.
			has: function( fn ) {
				return fn ?
					jQuery.inArray( fn, list ) > -1 :
					list.length > 0;
			},

			// Remove all callbacks from the list
			empty: function() {
				if ( list ) {
					list = [];
				}
				return this;
			},

			// Disable .fire and .add
			// Abort any current/pending executions
			// Clear all callbacks and values
			disable: function() {
				locked = queue = [];
				list = memory = "";
				return this;
			},
			disabled: function() {
				return !list;
			},

			// Disable .fire
			// Also disable .add unless we have memory (since it would have no effect)
			// Abort any pending executions
			lock: function() {
				locked = queue = [];
				if ( !memory ) {
					list = memory = "";
				}
				return this;
			},
			locked: function() {
				return !!locked;
			},

			// Call all callbacks with the given context and arguments
			fireWith: function( context, args ) {
				if ( !locked ) {
					args = args || [];
					args = [ context, args.slice ? args.slice() : args ];
					queue.push( args );
					if ( !firing ) {
						fire();
					}
				}
				return this;
			},

			// Call all the callbacks with the given arguments
			fire: function() {
				self.fireWith( this, arguments );
				return this;
			},

			// To know if the callbacks have already been called at least once
			fired: function() {
				return !!fired;
			}
		};

	return self;
};

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return ( /\S+/g );
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(191),
	__webpack_require__(194)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, slice ) {

jQuery.extend( {

	Deferred: function( func ) {
		var tuples = [

				// action, add listener, listener list, final state
				[ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ],
				[ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ],
				[ "notify", "progress", jQuery.Callbacks( "memory" ) ]
			],
			state = "pending",
			promise = {
				state: function() {
					return state;
				},
				always: function() {
					deferred.done( arguments ).fail( arguments );
					return this;
				},
				then: function( /* fnDone, fnFail, fnProgress */ ) {
					var fns = arguments;
					return jQuery.Deferred( function( newDefer ) {
						jQuery.each( tuples, function( i, tuple ) {
							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];

							// deferred[ done | fail | progress ] for forwarding actions to newDefer
							deferred[ tuple[ 1 ] ]( function() {
								var returned = fn && fn.apply( this, arguments );
								if ( returned && jQuery.isFunction( returned.promise ) ) {
									returned.promise()
										.progress( newDefer.notify )
										.done( newDefer.resolve )
										.fail( newDefer.reject );
								} else {
									newDefer[ tuple[ 0 ] + "With" ](
										this === promise ? newDefer.promise() : this,
										fn ? [ returned ] : arguments
									);
								}
							} );
						} );
						fns = null;
					} ).promise();
				},

				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise: function( obj ) {
					return obj != null ? jQuery.extend( obj, promise ) : promise;
				}
			},
			deferred = {};

		// Keep pipe for back-compat
		promise.pipe = promise.then;

		// Add list-specific methods
		jQuery.each( tuples, function( i, tuple ) {
			var list = tuple[ 2 ],
				stateString = tuple[ 3 ];

			// promise[ done | fail | progress ] = list.add
			promise[ tuple[ 1 ] ] = list.add;

			// Handle state
			if ( stateString ) {
				list.add( function() {

					// state = [ resolved | rejected ]
					state = stateString;

				// [ reject_list | resolve_list ].disable; progress_list.lock
				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
			}

			// deferred[ resolve | reject | notify ]
			deferred[ tuple[ 0 ] ] = function() {
				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments );
				return this;
			};
			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
		} );

		// Make the deferred a promise
		promise.promise( deferred );

		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}

		// All done!
		return deferred;
	},

	// Deferred helper
	when: function( subordinate /* , ..., subordinateN */ ) {
		var i = 0,
			resolveValues = slice.call( arguments ),
			length = resolveValues.length,

			// the count of uncompleted subordinates
			remaining = length !== 1 ||
				( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,

			// the master Deferred.
			// If resolveValues consist of only a single Deferred, just use that.
			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),

			// Update function for both resolve and progress values
			updateFunc = function( i, contexts, values ) {
				return function( value ) {
					contexts[ i ] = this;
					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
					if ( values === progressValues ) {
						deferred.notifyWith( contexts, values );
					} else if ( !( --remaining ) ) {
						deferred.resolveWith( contexts, values );
					}
				};
			},

			progressValues, progressContexts, resolveContexts;

		// Add listeners to Deferred subordinates; treat others as resolved
		if ( length > 1 ) {
			progressValues = new Array( length );
			progressContexts = new Array( length );
			resolveContexts = new Array( length );
			for ( ; i < length; i++ ) {
				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
					resolveValues[ i ].promise()
						.progress( updateFunc( i, progressContexts, progressValues ) )
						.done( updateFunc( i, resolveContexts, resolveValues ) )
						.fail( deferred.reject );
				} else {
					--remaining;
				}
			}
		}

		// If we're not waiting on anything, resolve the master
		if ( !remaining ) {
			deferred.resolveWith( resolveContexts, resolveValues );
		}

		return deferred.promise();
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(52),
	__webpack_require__(123)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document ) {

// The deferred used on DOM ready
var readyList;

jQuery.fn.ready = function( fn ) {

	// Add the callback
	jQuery.ready.promise().done( fn );

	return this;
};

jQuery.extend( {

	// Is the DOM ready to be used? Set to true once it occurs.
	isReady: false,

	// A counter to track how many items to wait for before
	// the ready event fires. See #6781
	readyWait: 1,

	// Hold (or release) the ready event
	holdReady: function( hold ) {
		if ( hold ) {
			jQuery.readyWait++;
		} else {
			jQuery.ready( true );
		}
	},

	// Handle when the DOM is ready
	ready: function( wait ) {

		// Abort if there are pending holds or we're already ready
		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
			return;
		}

		// Remember that the DOM is ready
		jQuery.isReady = true;

		// If a normal DOM Ready event fired, decrement, and wait if need be
		if ( wait !== true && --jQuery.readyWait > 0 ) {
			return;
		}

		// If there are functions bound, to execute
		readyList.resolveWith( document, [ jQuery ] );

		// Trigger any bound ready events
		if ( jQuery.fn.triggerHandler ) {
			jQuery( document ).triggerHandler( "ready" );
			jQuery( document ).off( "ready" );
		}
	}
} );

/**
 * The ready event handler and self cleanup method
 */
function completed() {
	document.removeEventListener( "DOMContentLoaded", completed );
	window.removeEventListener( "load", completed );
	jQuery.ready();
}

jQuery.ready.promise = function( obj ) {
	if ( !readyList ) {

		readyList = jQuery.Deferred();

		// Catch cases where $(document).ready() is called
		// after the browser event has already occurred.
		// Support: IE9-10 only
		// Older IE sometimes signals "interactive" too soon
		if ( document.readyState === "complete" ||
			( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

			// Handle it asynchronously to allow scripts the opportunity to delay ready
			window.setTimeout( jQuery.ready );

		} else {

			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", completed );

			// A fallback to window.onload, that will always work
			window.addEventListener( "load", completed );
		}
	}
	return readyList.promise( obj );
};

// Kick off the DOM ready check even if the user does not
jQuery.ready.promise();

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(83),
	__webpack_require__(55),
	__webpack_require__(279)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, access, dataPriv, dataUser ) {

//	Implementation Summary
//
//	1. Enforce API surface and semantic compatibility with 1.9.x branch
//	2. Improve the module's maintainability by reducing the storage
//		paths to a single mechanism.
//	3. Use the same single mechanism to support "private" and "user" data.
//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
//	5. Avoid exposing implementation details on user objects (eg. expando properties)
//	6. Provide a clear path for implementation upgrade to WeakMap in 2014

var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
	rmultiDash = /[A-Z]/g;

function dataAttr( elem, key, data ) {
	var name;

	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {
		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
					data === "false" ? false :
					data === "null" ? null :

					// Only convert to a number if it doesn't change the string
					+data + "" === data ? +data :
					rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch ( e ) {}

			// Make sure we set the data so it isn't changed later
			dataUser.set( elem, key, data );
		} else {
			data = undefined;
		}
	}
	return data;
}

jQuery.extend( {
	hasData: function( elem ) {
		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
	},

	data: function( elem, name, data ) {
		return dataUser.access( elem, name, data );
	},

	removeData: function( elem, name ) {
		dataUser.remove( elem, name );
	},

	// TODO: Now that all calls to _data and _removeData have been replaced
	// with direct calls to dataPriv methods, these can be deprecated.
	_data: function( elem, name, data ) {
		return dataPriv.access( elem, name, data );
	},

	_removeData: function( elem, name ) {
		dataPriv.remove( elem, name );
	}
} );

jQuery.fn.extend( {
	data: function( key, value ) {
		var i, name, data,
			elem = this[ 0 ],
			attrs = elem && elem.attributes;

		// Gets all values
		if ( key === undefined ) {
			if ( this.length ) {
				data = dataUser.get( elem );

				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
					i = attrs.length;
					while ( i-- ) {

						// Support: IE11+
						// The attrs elements can be null (#14894)
						if ( attrs[ i ] ) {
							name = attrs[ i ].name;
							if ( name.indexOf( "data-" ) === 0 ) {
								name = jQuery.camelCase( name.slice( 5 ) );
								dataAttr( elem, name, data[ name ] );
							}
						}
					}
					dataPriv.set( elem, "hasDataAttrs", true );
				}
			}

			return data;
		}

		// Sets multiple values
		if ( typeof key === "object" ) {
			return this.each( function() {
				dataUser.set( this, key );
			} );
		}

		return access( this, function( value ) {
			var data, camelKey;

			// The calling jQuery object (element matches) is not empty
			// (and therefore has an element appears at this[ 0 ]) and the
			// `value` parameter was not undefined. An empty jQuery object
			// will result in `undefined` for elem = this[ 0 ] which will
			// throw an exception if an attempt to read a data cache is made.
			if ( elem && value === undefined ) {

				// Attempt to get data from the cache
				// with the key as-is
				data = dataUser.get( elem, key ) ||

					// Try to find dashed key if it exists (gh-2779)
					// This is for 2.2.x only
					dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() );

				if ( data !== undefined ) {
					return data;
				}

				camelKey = jQuery.camelCase( key );

				// Attempt to get data from the cache
				// with the key camelized
				data = dataUser.get( elem, camelKey );
				if ( data !== undefined ) {
					return data;
				}

				// Attempt to "discover" the data in
				// HTML5 custom data-* attrs
				data = dataAttr( elem, camelKey, undefined );
				if ( data !== undefined ) {
					return data;
				}

				// We tried really hard, but the data doesn't exist.
				return;
			}

			// Set the data...
			camelKey = jQuery.camelCase( key );
			this.each( function() {

				// First, attempt to store a copy or reference of any
				// data that might've been store with a camelCased key.
				var data = dataUser.get( this, camelKey );

				// For HTML5 data-* attribute interop, we have to
				// store property names with dashes in a camelCase form.
				// This might not apply to all properties...*
				dataUser.set( this, camelKey, value );

				// *... In the case of properties that might _actually_
				// have dashes, we need to also store a copy of that
				// unchanged property.
				if ( key.indexOf( "-" ) > -1 && data !== undefined ) {
					dataUser.set( this, key, value );
				}
			} );
		}, null, value, arguments.length > 1, null, true );
	},

	removeData: function( key ) {
		return this.each( function() {
			dataUser.remove( this, key );
		} );
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
	var i = 0,
		len = elems.length,
		bulk = key == null;

	// Sets many values
	if ( jQuery.type( key ) === "object" ) {
		chainable = true;
		for ( i in key ) {
			access( elems, fn, i, key[ i ], true, emptyGet, raw );
		}

	// Sets one value
	} else if ( value !== undefined ) {
		chainable = true;

		if ( !jQuery.isFunction( value ) ) {
			raw = true;
		}

		if ( bulk ) {

			// Bulk operations run against the entire set
			if ( raw ) {
				fn.call( elems, value );
				fn = null;

			// ...except when executing function values
			} else {
				bulk = fn;
				fn = function( elem, key, value ) {
					return bulk.call( jQuery( elem ), value );
				};
			}
		}

		if ( fn ) {
			for ( ; i < len; i++ ) {
				fn(
					elems[ i ], key, raw ?
					value :
					value.call( elems[ i ], i, fn( elems[ i ], key ) )
				);
			}
		}
	}

	return chainable ?
		elems :

		// Gets
		bulk ?
			fn.call( elems ) :
			len ? fn( elems[ 0 ], key ) : emptyGet;
};

return access;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(278)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( Data ) {
	return new Data();
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(82),
	__webpack_require__(195)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, rnotwhite, acceptData ) {

function Data() {
	this.expando = jQuery.expando + Data.uid++;
}

Data.uid = 1;

Data.prototype = {

	register: function( owner, initial ) {
		var value = initial || {};

		// If it is a node unlikely to be stringify-ed or looped over
		// use plain assignment
		if ( owner.nodeType ) {
			owner[ this.expando ] = value;

		// Otherwise secure it in a non-enumerable, non-writable property
		// configurability must be true to allow the property to be
		// deleted with the delete operator
		} else {
			Object.defineProperty( owner, this.expando, {
				value: value,
				writable: true,
				configurable: true
			} );
		}
		return owner[ this.expando ];
	},
	cache: function( owner ) {

		// We can accept data for non-element nodes in modern browsers,
		// but we should not, see #8335.
		// Always return an empty object.
		if ( !acceptData( owner ) ) {
			return {};
		}

		// Check if the owner object already has a cache
		var value = owner[ this.expando ];

		// If not, create one
		if ( !value ) {
			value = {};

			// We can accept data for non-element nodes in modern browsers,
			// but we should not, see #8335.
			// Always return an empty object.
			if ( acceptData( owner ) ) {

				// If it is a node unlikely to be stringify-ed or looped over
				// use plain assignment
				if ( owner.nodeType ) {
					owner[ this.expando ] = value;

				// Otherwise secure it in a non-enumerable property
				// configurable must be true to allow the property to be
				// deleted when data is removed
				} else {
					Object.defineProperty( owner, this.expando, {
						value: value,
						configurable: true
					} );
				}
			}
		}

		return value;
	},
	set: function( owner, data, value ) {
		var prop,
			cache = this.cache( owner );

		// Handle: [ owner, key, value ] args
		if ( typeof data === "string" ) {
			cache[ data ] = value;

		// Handle: [ owner, { properties } ] args
		} else {

			// Copy the properties one-by-one to the cache object
			for ( prop in data ) {
				cache[ prop ] = data[ prop ];
			}
		}
		return cache;
	},
	get: function( owner, key ) {
		return key === undefined ?
			this.cache( owner ) :
			owner[ this.expando ] && owner[ this.expando ][ key ];
	},
	access: function( owner, key, value ) {
		var stored;

		// In cases where either:
		//
		//   1. No key was specified
		//   2. A string key was specified, but no value provided
		//
		// Take the "read" path and allow the get method to determine
		// which value to return, respectively either:
		//
		//   1. The entire cache object
		//   2. The data stored at the key
		//
		if ( key === undefined ||
				( ( key && typeof key === "string" ) && value === undefined ) ) {

			stored = this.get( owner, key );

			return stored !== undefined ?
				stored : this.get( owner, jQuery.camelCase( key ) );
		}

		// When the key is not a string, or both a key and value
		// are specified, set or extend (existing objects) with either:
		//
		//   1. An object of properties
		//   2. A key and value
		//
		this.set( owner, key, value );

		// Since the "set" path can have two possible entry points
		// return the expected data based on which path was taken[*]
		return value !== undefined ? value : key;
	},
	remove: function( owner, key ) {
		var i, name, camel,
			cache = owner[ this.expando ];

		if ( cache === undefined ) {
			return;
		}

		if ( key === undefined ) {
			this.register( owner );

		} else {

			// Support array or space separated string of keys
			if ( jQuery.isArray( key ) ) {

				// If "name" is an array of keys...
				// When data is initially created, via ("key", "val") signature,
				// keys will be converted to camelCase.
				// Since there is no way to tell _how_ a key was added, remove
				// both plain key and camelCase key. #12786
				// This will only penalize the array argument path.
				name = key.concat( key.map( jQuery.camelCase ) );
			} else {
				camel = jQuery.camelCase( key );

				// Try the string as a key before any manipulation
				if ( key in cache ) {
					name = [ key, camel ];
				} else {

					// If a key with the spaces exists, use it.
					// Otherwise, create an array by matching non-whitespace
					name = camel;
					name = name in cache ?
						[ name ] : ( name.match( rnotwhite ) || [] );
				}
			}

			i = name.length;

			while ( i-- ) {
				delete cache[ name[ i ] ];
			}
		}

		// Remove the expando if there's no more data
		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {

			// Support: Chrome <= 35-45+
			// Webkit & Blink performance suffers when deleting properties
			// from DOM nodes, so set to undefined instead
			// https://code.google.com/p/chromium/issues/detail?id=378607
			if ( owner.nodeType ) {
				owner[ this.expando ] = undefined;
			} else {
				delete owner[ this.expando ];
			}
		}
	},
	hasData: function( owner ) {
		var cache = owner[ this.expando ];
		return cache !== undefined && !jQuery.isEmptyObject( cache );
	}
};

return Data;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

/**
 * Determines whether an object can have data
 */
return function( owner ) {

	// Accepts only:
	//  - Node
	//    - Node.ELEMENT_NODE
	//    - Node.DOCUMENT_NODE
	//  - Object
	//    - Any
	/* jshint -W018 */
	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
};

}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(278)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( Data ) {
	return new Data();
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(55),
	__webpack_require__(123),
	__webpack_require__(194)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, dataPriv ) {

jQuery.extend( {
	queue: function( elem, type, data ) {
		var queue;

		if ( elem ) {
			type = ( type || "fx" ) + "queue";
			queue = dataPriv.get( elem, type );

			// Speed up dequeue by getting out quickly if this is just a lookup
			if ( data ) {
				if ( !queue || jQuery.isArray( data ) ) {
					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
				} else {
					queue.push( data );
				}
			}
			return queue || [];
		}
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ),
			startLength = queue.length,
			fn = queue.shift(),
			hooks = jQuery._queueHooks( elem, type ),
			next = function() {
				jQuery.dequeue( elem, type );
			};

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
			startLength--;
		}

		if ( fn ) {

			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift( "inprogress" );
			}

			// Clear up the last queue stop function
			delete hooks.stop;
			fn.call( elem, next, hooks );
		}

		if ( !startLength && hooks ) {
			hooks.empty.fire();
		}
	},

	// Not public - generate a queueHooks object, or return the current one
	_queueHooks: function( elem, type ) {
		var key = type + "queueHooks";
		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
			empty: jQuery.Callbacks( "once memory" ).add( function() {
				dataPriv.remove( elem, [ type + "queue", key ] );
			} )
		} );
	}
} );

jQuery.fn.extend( {
	queue: function( type, data ) {
		var setter = 2;

		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
			setter--;
		}

		if ( arguments.length < setter ) {
			return jQuery.queue( this[ 0 ], type );
		}

		return data === undefined ?
			this :
			this.each( function() {
				var queue = jQuery.queue( this, type, data );

				// Ensure a hooks for this queue
				jQuery._queueHooks( this, type );

				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
					jQuery.dequeue( this, type );
				}
			} );
	},
	dequeue: function( type ) {
		return this.each( function() {
			jQuery.dequeue( this, type );
		} );
	},
	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	},

	// Get a promise resolved when queues of a certain type
	// are emptied (fx is the type by default)
	promise: function( type, obj ) {
		var tmp,
			count = 1,
			defer = jQuery.Deferred(),
			elements = this,
			i = this.length,
			resolve = function() {
				if ( !( --count ) ) {
					defer.resolveWith( elements, [ elements ] );
				}
			};

		if ( typeof type !== "string" ) {
			obj = type;
			type = undefined;
		}
		type = type || "fx";

		while ( i-- ) {
			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
			if ( tmp && tmp.empty ) {
				count++;
				tmp.empty.add( resolve );
			}
		}
		resolve();
		return defer.promise( obj );
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(196),
	__webpack_require__(197) // Delay is optional because of this dependency
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Based off of the plugin by Clint Helfers, with permission.
// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
jQuery.fn.delay = function( time, type ) {
	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
	type = type || "fx";

	return this.queue( type, function( next, hooks ) {
		var timeout = window.setTimeout( next, time );
		hooks.stop = function() {
			window.clearTimeout( timeout );
		};
	} );
};

return jQuery.fn.delay;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(198),
	__webpack_require__(280),
	__webpack_require__(82),
	__webpack_require__(281),
	__webpack_require__(282),
	__webpack_require__(283),
	__webpack_require__(55),

	__webpack_require__(52),
	__webpack_require__(577),
	__webpack_require__(196),
	__webpack_require__(124),
	__webpack_require__(123),
	__webpack_require__(97)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document, rcssNum, cssExpand, rnotwhite,
	isHidden, adjustCSS, defaultDisplay, dataPriv ) {

var
	fxNow, timerId,
	rfxtypes = /^(?:toggle|show|hide)$/,
	rrun = /queueHooks$/;

// Animations created synchronously will run synchronously
function createFxNow() {
	window.setTimeout( function() {
		fxNow = undefined;
	} );
	return ( fxNow = jQuery.now() );
}

// Generate parameters to create a standard animation
function genFx( type, includeWidth ) {
	var which,
		i = 0,
		attrs = { height: type };

	// If we include width, step value is 1 to do all cssExpand values,
	// otherwise step value is 2 to skip over Left and Right
	includeWidth = includeWidth ? 1 : 0;
	for ( ; i < 4 ; i += 2 - includeWidth ) {
		which = cssExpand[ i ];
		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
	}

	if ( includeWidth ) {
		attrs.opacity = attrs.width = type;
	}

	return attrs;
}

function createTween( value, prop, animation ) {
	var tween,
		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
		index = 0,
		length = collection.length;
	for ( ; index < length; index++ ) {
		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {

			// We're done with this property
			return tween;
		}
	}
}

function defaultPrefilter( elem, props, opts ) {
	/* jshint validthis: true */
	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
		anim = this,
		orig = {},
		style = elem.style,
		hidden = elem.nodeType && isHidden( elem ),
		dataShow = dataPriv.get( elem, "fxshow" );

	// Handle queue: false promises
	if ( !opts.queue ) {
		hooks = jQuery._queueHooks( elem, "fx" );
		if ( hooks.unqueued == null ) {
			hooks.unqueued = 0;
			oldfire = hooks.empty.fire;
			hooks.empty.fire = function() {
				if ( !hooks.unqueued ) {
					oldfire();
				}
			};
		}
		hooks.unqueued++;

		anim.always( function() {

			// Ensure the complete handler is called before this completes
			anim.always( function() {
				hooks.unqueued--;
				if ( !jQuery.queue( elem, "fx" ).length ) {
					hooks.empty.fire();
				}
			} );
		} );
	}

	// Height/width overflow pass
	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {

		// Make sure that nothing sneaks out
		// Record all 3 overflow attributes because IE9-10 do not
		// change the overflow attribute when overflowX and
		// overflowY are set to the same value
		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];

		// Set display property to inline-block for height/width
		// animations on inline elements that are having width/height animated
		display = jQuery.css( elem, "display" );

		// Test default display if display is currently "none"
		checkDisplay = display === "none" ?
			dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;

		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
			style.display = "inline-block";
		}
	}

	if ( opts.overflow ) {
		style.overflow = "hidden";
		anim.always( function() {
			style.overflow = opts.overflow[ 0 ];
			style.overflowX = opts.overflow[ 1 ];
			style.overflowY = opts.overflow[ 2 ];
		} );
	}

	// show/hide pass
	for ( prop in props ) {
		value = props[ prop ];
		if ( rfxtypes.exec( value ) ) {
			delete props[ prop ];
			toggle = toggle || value === "toggle";
			if ( value === ( hidden ? "hide" : "show" ) ) {

				// If there is dataShow left over from a stopped hide or show
				// and we are going to proceed with show, we should pretend to be hidden
				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
					hidden = true;
				} else {
					continue;
				}
			}
			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );

		// Any non-fx value stops us from restoring the original display value
		} else {
			display = undefined;
		}
	}

	if ( !jQuery.isEmptyObject( orig ) ) {
		if ( dataShow ) {
			if ( "hidden" in dataShow ) {
				hidden = dataShow.hidden;
			}
		} else {
			dataShow = dataPriv.access( elem, "fxshow", {} );
		}

		// Store state if its toggle - enables .stop().toggle() to "reverse"
		if ( toggle ) {
			dataShow.hidden = !hidden;
		}
		if ( hidden ) {
			jQuery( elem ).show();
		} else {
			anim.done( function() {
				jQuery( elem ).hide();
			} );
		}
		anim.done( function() {
			var prop;

			dataPriv.remove( elem, "fxshow" );
			for ( prop in orig ) {
				jQuery.style( elem, prop, orig[ prop ] );
			}
		} );
		for ( prop in orig ) {
			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );

			if ( !( prop in dataShow ) ) {
				dataShow[ prop ] = tween.start;
				if ( hidden ) {
					tween.end = tween.start;
					tween.start = prop === "width" || prop === "height" ? 1 : 0;
				}
			}
		}

	// If this is a noop like .hide().hide(), restore an overwritten display value
	} else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) {
		style.display = display;
	}
}

function propFilter( props, specialEasing ) {
	var index, name, easing, value, hooks;

	// camelCase, specialEasing and expand cssHook pass
	for ( index in props ) {
		name = jQuery.camelCase( index );
		easing = specialEasing[ name ];
		value = props[ index ];
		if ( jQuery.isArray( value ) ) {
			easing = value[ 1 ];
			value = props[ index ] = value[ 0 ];
		}

		if ( index !== name ) {
			props[ name ] = value;
			delete props[ index ];
		}

		hooks = jQuery.cssHooks[ name ];
		if ( hooks && "expand" in hooks ) {
			value = hooks.expand( value );
			delete props[ name ];

			// Not quite $.extend, this won't overwrite existing keys.
			// Reusing 'index' because we have the correct "name"
			for ( index in value ) {
				if ( !( index in props ) ) {
					props[ index ] = value[ index ];
					specialEasing[ index ] = easing;
				}
			}
		} else {
			specialEasing[ name ] = easing;
		}
	}
}

function Animation( elem, properties, options ) {
	var result,
		stopped,
		index = 0,
		length = Animation.prefilters.length,
		deferred = jQuery.Deferred().always( function() {

			// Don't match elem in the :animated selector
			delete tick.elem;
		} ),
		tick = function() {
			if ( stopped ) {
				return false;
			}
			var currentTime = fxNow || createFxNow(),
				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),

				// Support: Android 2.3
				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
				temp = remaining / animation.duration || 0,
				percent = 1 - temp,
				index = 0,
				length = animation.tweens.length;

			for ( ; index < length ; index++ ) {
				animation.tweens[ index ].run( percent );
			}

			deferred.notifyWith( elem, [ animation, percent, remaining ] );

			if ( percent < 1 && length ) {
				return remaining;
			} else {
				deferred.resolveWith( elem, [ animation ] );
				return false;
			}
		},
		animation = deferred.promise( {
			elem: elem,
			props: jQuery.extend( {}, properties ),
			opts: jQuery.extend( true, {
				specialEasing: {},
				easing: jQuery.easing._default
			}, options ),
			originalProperties: properties,
			originalOptions: options,
			startTime: fxNow || createFxNow(),
			duration: options.duration,
			tweens: [],
			createTween: function( prop, end ) {
				var tween = jQuery.Tween( elem, animation.opts, prop, end,
						animation.opts.specialEasing[ prop ] || animation.opts.easing );
				animation.tweens.push( tween );
				return tween;
			},
			stop: function( gotoEnd ) {
				var index = 0,

					// If we are going to the end, we want to run all the tweens
					// otherwise we skip this part
					length = gotoEnd ? animation.tweens.length : 0;
				if ( stopped ) {
					return this;
				}
				stopped = true;
				for ( ; index < length ; index++ ) {
					animation.tweens[ index ].run( 1 );
				}

				// Resolve when we played the last frame; otherwise, reject
				if ( gotoEnd ) {
					deferred.notifyWith( elem, [ animation, 1, 0 ] );
					deferred.resolveWith( elem, [ animation, gotoEnd ] );
				} else {
					deferred.rejectWith( elem, [ animation, gotoEnd ] );
				}
				return this;
			}
		} ),
		props = animation.props;

	propFilter( props, animation.opts.specialEasing );

	for ( ; index < length ; index++ ) {
		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
		if ( result ) {
			if ( jQuery.isFunction( result.stop ) ) {
				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
					jQuery.proxy( result.stop, result );
			}
			return result;
		}
	}

	jQuery.map( props, createTween, animation );

	if ( jQuery.isFunction( animation.opts.start ) ) {
		animation.opts.start.call( elem, animation );
	}

	jQuery.fx.timer(
		jQuery.extend( tick, {
			elem: elem,
			anim: animation,
			queue: animation.opts.queue
		} )
	);

	// attach callbacks from options
	return animation.progress( animation.opts.progress )
		.done( animation.opts.done, animation.opts.complete )
		.fail( animation.opts.fail )
		.always( animation.opts.always );
}

jQuery.Animation = jQuery.extend( Animation, {
	tweeners: {
		"*": [ function( prop, value ) {
			var tween = this.createTween( prop, value );
			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
			return tween;
		} ]
	},

	tweener: function( props, callback ) {
		if ( jQuery.isFunction( props ) ) {
			callback = props;
			props = [ "*" ];
		} else {
			props = props.match( rnotwhite );
		}

		var prop,
			index = 0,
			length = props.length;

		for ( ; index < length ; index++ ) {
			prop = props[ index ];
			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
			Animation.tweeners[ prop ].unshift( callback );
		}
	},

	prefilters: [ defaultPrefilter ],

	prefilter: function( callback, prepend ) {
		if ( prepend ) {
			Animation.prefilters.unshift( callback );
		} else {
			Animation.prefilters.push( callback );
		}
	}
} );

jQuery.speed = function( speed, easing, fn ) {
	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
		complete: fn || !fn && easing ||
			jQuery.isFunction( speed ) && speed,
		duration: speed,
		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
	};

	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ?
		opt.duration : opt.duration in jQuery.fx.speeds ?
			jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;

	// Normalize opt.queue - true/undefined/null -> "fx"
	if ( opt.queue == null || opt.queue === true ) {
		opt.queue = "fx";
	}

	// Queueing
	opt.old = opt.complete;

	opt.complete = function() {
		if ( jQuery.isFunction( opt.old ) ) {
			opt.old.call( this );
		}

		if ( opt.queue ) {
			jQuery.dequeue( this, opt.queue );
		}
	};

	return opt;
};

jQuery.fn.extend( {
	fadeTo: function( speed, to, easing, callback ) {

		// Show any hidden elements after setting opacity to 0
		return this.filter( isHidden ).css( "opacity", 0 ).show()

			// Animate to the value specified
			.end().animate( { opacity: to }, speed, easing, callback );
	},
	animate: function( prop, speed, easing, callback ) {
		var empty = jQuery.isEmptyObject( prop ),
			optall = jQuery.speed( speed, easing, callback ),
			doAnimation = function() {

				// Operate on a copy of prop so per-property easing won't be lost
				var anim = Animation( this, jQuery.extend( {}, prop ), optall );

				// Empty animations, or finishing resolves immediately
				if ( empty || dataPriv.get( this, "finish" ) ) {
					anim.stop( true );
				}
			};
			doAnimation.finish = doAnimation;

		return empty || optall.queue === false ?
			this.each( doAnimation ) :
			this.queue( optall.queue, doAnimation );
	},
	stop: function( type, clearQueue, gotoEnd ) {
		var stopQueue = function( hooks ) {
			var stop = hooks.stop;
			delete hooks.stop;
			stop( gotoEnd );
		};

		if ( typeof type !== "string" ) {
			gotoEnd = clearQueue;
			clearQueue = type;
			type = undefined;
		}
		if ( clearQueue && type !== false ) {
			this.queue( type || "fx", [] );
		}

		return this.each( function() {
			var dequeue = true,
				index = type != null && type + "queueHooks",
				timers = jQuery.timers,
				data = dataPriv.get( this );

			if ( index ) {
				if ( data[ index ] && data[ index ].stop ) {
					stopQueue( data[ index ] );
				}
			} else {
				for ( index in data ) {
					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
						stopQueue( data[ index ] );
					}
				}
			}

			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this &&
					( type == null || timers[ index ].queue === type ) ) {

					timers[ index ].anim.stop( gotoEnd );
					dequeue = false;
					timers.splice( index, 1 );
				}
			}

			// Start the next in the queue if the last step wasn't forced.
			// Timers currently will call their complete callbacks, which
			// will dequeue but only if they were gotoEnd.
			if ( dequeue || !gotoEnd ) {
				jQuery.dequeue( this, type );
			}
		} );
	},
	finish: function( type ) {
		if ( type !== false ) {
			type = type || "fx";
		}
		return this.each( function() {
			var index,
				data = dataPriv.get( this ),
				queue = data[ type + "queue" ],
				hooks = data[ type + "queueHooks" ],
				timers = jQuery.timers,
				length = queue ? queue.length : 0;

			// Enable finishing flag on private data
			data.finish = true;

			// Empty the queue first
			jQuery.queue( this, type, [] );

			if ( hooks && hooks.stop ) {
				hooks.stop.call( this, true );
			}

			// Look for any active animations, and finish them
			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
					timers[ index ].anim.stop( true );
					timers.splice( index, 1 );
				}
			}

			// Look for any animations in the old queue and finish them
			for ( index = 0; index < length; index++ ) {
				if ( queue[ index ] && queue[ index ].finish ) {
					queue[ index ].finish.call( this );
				}
			}

			// Turn off finishing flag
			delete data.finish;
		} );
	}
} );

jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
	var cssFn = jQuery.fn[ name ];
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return speed == null || typeof speed === "boolean" ?
			cssFn.apply( this, arguments ) :
			this.animate( genFx( name, true ), speed, easing, callback );
	};
} );

// Generate shortcuts for custom animations
jQuery.each( {
	slideDown: genFx( "show" ),
	slideUp: genFx( "hide" ),
	slideToggle: genFx( "toggle" ),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" },
	fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return this.animate( props, speed, easing, callback );
	};
} );

jQuery.timers = [];
jQuery.fx.tick = function() {
	var timer,
		i = 0,
		timers = jQuery.timers;

	fxNow = jQuery.now();

	for ( ; i < timers.length; i++ ) {
		timer = timers[ i ];

		// Checks the timer has not already been removed
		if ( !timer() && timers[ i ] === timer ) {
			timers.splice( i--, 1 );
		}
	}

	if ( !timers.length ) {
		jQuery.fx.stop();
	}
	fxNow = undefined;
};

jQuery.fx.timer = function( timer ) {
	jQuery.timers.push( timer );
	if ( timer() ) {
		jQuery.fx.start();
	} else {
		jQuery.timers.pop();
	}
};

jQuery.fx.interval = 13;
jQuery.fx.start = function() {
	if ( !timerId ) {
		timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
	}
};

jQuery.fx.stop = function() {
	window.clearInterval( timerId );

	timerId = null;
};

jQuery.fx.speeds = {
	slow: 600,
	fast: 200,

	// Default speed
	_default: 400
};

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(199)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( pnum ) {

return new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return [ "Top", "Right", "Bottom", "Left" ];
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(42)

	// css is assumed
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

	return function( elem, el ) {

		// isHidden might be called from jQuery#filter function;
		// in that case, element will be second argument
		elem = el || elem;
		return jQuery.css( elem, "display" ) === "none" ||
			!jQuery.contains( elem.ownerDocument, elem );
	};
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(198)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, rcssNum ) {

function adjustCSS( elem, prop, valueParts, tween ) {
	var adjusted,
		scale = 1,
		maxIterations = 20,
		currentValue = tween ?
			function() { return tween.cur(); } :
			function() { return jQuery.css( elem, prop, "" ); },
		initial = currentValue(),
		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),

		// Starting value computation is required for potential unit mismatches
		initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
			rcssNum.exec( jQuery.css( elem, prop ) );

	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {

		// Trust units reported by jQuery.css
		unit = unit || initialInUnit[ 3 ];

		// Make sure we update the tween properties later on
		valueParts = valueParts || [];

		// Iteratively approximate from a nonzero starting point
		initialInUnit = +initial || 1;

		do {

			// If previous iteration zeroed out, double until we get *something*.
			// Use string for doubling so we don't accidentally see scale as unchanged below
			scale = scale || ".5";

			// Adjust and apply
			initialInUnit = initialInUnit / scale;
			jQuery.style( elem, prop, initialInUnit + unit );

		// Update scale, tolerating zero or NaN from tween.cur()
		// Break the loop if scale is unchanged or perfect, or if we've just had enough.
		} while (
			scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
		);
	}

	if ( valueParts ) {
		initialInUnit = +initialInUnit || +initial || 0;

		// Apply relative offset (+=/-=) if specified
		adjusted = valueParts[ 1 ] ?
			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
			+valueParts[ 2 ];
		if ( tween ) {
			tween.unit = unit;
			tween.start = initialInUnit;
			tween.end = adjusted;
		}
	}
	return adjusted;
}

return adjustCSS;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(149) // appendTo
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document ) {

var iframe,
	elemdisplay = {

		// Support: Firefox
		// We have to pre-define these values for FF (#10227)
		HTML: "block",
		BODY: "block"
	};

/**
 * Retrieve the actual display of a element
 * @param {String} name nodeName of the element
 * @param {Object} doc Document object
 */

// Called only from within defaultDisplay
function actualDisplay( name, doc ) {
	var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),

		display = jQuery.css( elem[ 0 ], "display" );

	// We don't have any data stored on the element,
	// so use "detach" method as fast way to get rid of the element
	elem.detach();

	return display;
}

/**
 * Try to determine the default display value of an element
 * @param {String} nodeName
 */
function defaultDisplay( nodeName ) {
	var doc = document,
		display = elemdisplay[ nodeName ];

	if ( !display ) {
		display = actualDisplay( nodeName, doc );

		// If the simple way fails, read from inside an iframe
		if ( display === "none" || !display ) {

			// Use the already-created iframe if possible
			iframe = ( iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" ) )
				.appendTo( doc.documentElement );

			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
			doc = iframe[ 0 ].contentDocument;

			// Support: IE
			doc.write();
			doc.close();

			display = actualDisplay( nodeName, doc );
			iframe.detach();
		}

		// Store the correct default display
		elemdisplay[ nodeName ] = display;
	}

	return display;
}

return defaultDisplay;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(271),
	__webpack_require__(272),
	__webpack_require__(83),
	__webpack_require__(284),
	__webpack_require__(285),
	__webpack_require__(286),
	__webpack_require__(287),
	__webpack_require__(288),
	__webpack_require__(289),
	__webpack_require__(290),
	__webpack_require__(576),

	__webpack_require__(55),
	__webpack_require__(279),
	__webpack_require__(195),

	__webpack_require__(52),
	__webpack_require__(97),
	__webpack_require__(42),
	__webpack_require__(98)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, concat, push, access,
	rcheckableType, rtagName, rscriptType,
	wrapMap, getAll, setGlobalEval, buildFragment, support,
	dataPriv, dataUser, acceptData ) {

var
	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,

	// Support: IE 10-11, Edge 10240+
	// In IE/Edge using regex groups here causes severe slowdowns.
	// See https://connect.microsoft.com/IE/feedback/details/1736512/
	rnoInnerhtml = /<script|<style|<link/i,

	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
	rscriptTypeMasked = /^true\/(.*)/,
	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;

// Manipulating tables requires a tbody
function manipulationTarget( elem, content ) {
	return jQuery.nodeName( elem, "table" ) &&
		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?

		elem.getElementsByTagName( "tbody" )[ 0 ] ||
			elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) :
		elem;
}

// Replace/restore the type attribute of script elements for safe DOM manipulation
function disableScript( elem ) {
	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
	return elem;
}
function restoreScript( elem ) {
	var match = rscriptTypeMasked.exec( elem.type );

	if ( match ) {
		elem.type = match[ 1 ];
	} else {
		elem.removeAttribute( "type" );
	}

	return elem;
}

function cloneCopyEvent( src, dest ) {
	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;

	if ( dest.nodeType !== 1 ) {
		return;
	}

	// 1. Copy private data: events, handlers, etc.
	if ( dataPriv.hasData( src ) ) {
		pdataOld = dataPriv.access( src );
		pdataCur = dataPriv.set( dest, pdataOld );
		events = pdataOld.events;

		if ( events ) {
			delete pdataCur.handle;
			pdataCur.events = {};

			for ( type in events ) {
				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
					jQuery.event.add( dest, type, events[ type ][ i ] );
				}
			}
		}
	}

	// 2. Copy user data
	if ( dataUser.hasData( src ) ) {
		udataOld = dataUser.access( src );
		udataCur = jQuery.extend( {}, udataOld );

		dataUser.set( dest, udataCur );
	}
}

// Fix IE bugs, see support tests
function fixInput( src, dest ) {
	var nodeName = dest.nodeName.toLowerCase();

	// Fails to persist the checked state of a cloned checkbox or radio button.
	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
		dest.checked = src.checked;

	// Fails to return the selected option to the default selected state when cloning options
	} else if ( nodeName === "input" || nodeName === "textarea" ) {
		dest.defaultValue = src.defaultValue;
	}
}

function domManip( collection, args, callback, ignored ) {

	// Flatten any nested arrays
	args = concat.apply( [], args );

	var fragment, first, scripts, hasScripts, node, doc,
		i = 0,
		l = collection.length,
		iNoClone = l - 1,
		value = args[ 0 ],
		isFunction = jQuery.isFunction( value );

	// We can't cloneNode fragments that contain checked, in WebKit
	if ( isFunction ||
			( l > 1 && typeof value === "string" &&
				!support.checkClone && rchecked.test( value ) ) ) {
		return collection.each( function( index ) {
			var self = collection.eq( index );
			if ( isFunction ) {
				args[ 0 ] = value.call( this, index, self.html() );
			}
			domManip( self, args, callback, ignored );
		} );
	}

	if ( l ) {
		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
		first = fragment.firstChild;

		if ( fragment.childNodes.length === 1 ) {
			fragment = first;
		}

		// Require either new content or an interest in ignored elements to invoke the callback
		if ( first || ignored ) {
			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
			hasScripts = scripts.length;

			// Use the original fragment for the last item
			// instead of the first because it can end up
			// being emptied incorrectly in certain situations (#8070).
			for ( ; i < l; i++ ) {
				node = fragment;

				if ( i !== iNoClone ) {
					node = jQuery.clone( node, true, true );

					// Keep references to cloned scripts for later restoration
					if ( hasScripts ) {

						// Support: Android<4.1, PhantomJS<2
						// push.apply(_, arraylike) throws on ancient WebKit
						jQuery.merge( scripts, getAll( node, "script" ) );
					}
				}

				callback.call( collection[ i ], node, i );
			}

			if ( hasScripts ) {
				doc = scripts[ scripts.length - 1 ].ownerDocument;

				// Reenable scripts
				jQuery.map( scripts, restoreScript );

				// Evaluate executable scripts on first document insertion
				for ( i = 0; i < hasScripts; i++ ) {
					node = scripts[ i ];
					if ( rscriptType.test( node.type || "" ) &&
						!dataPriv.access( node, "globalEval" ) &&
						jQuery.contains( doc, node ) ) {

						if ( node.src ) {

							// Optional AJAX dependency, but won't run scripts if not present
							if ( jQuery._evalUrl ) {
								jQuery._evalUrl( node.src );
							}
						} else {
							jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
						}
					}
				}
			}
		}
	}

	return collection;
}

function remove( elem, selector, keepData ) {
	var node,
		nodes = selector ? jQuery.filter( selector, elem ) : elem,
		i = 0;

	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
		if ( !keepData && node.nodeType === 1 ) {
			jQuery.cleanData( getAll( node ) );
		}

		if ( node.parentNode ) {
			if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
				setGlobalEval( getAll( node, "script" ) );
			}
			node.parentNode.removeChild( node );
		}
	}

	return elem;
}

jQuery.extend( {
	htmlPrefilter: function( html ) {
		return html.replace( rxhtmlTag, "<$1></$2>" );
	},

	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var i, l, srcElements, destElements,
			clone = elem.cloneNode( true ),
			inPage = jQuery.contains( elem.ownerDocument, elem );

		// Fix IE cloning issues
		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
				!jQuery.isXMLDoc( elem ) ) {

			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
			destElements = getAll( clone );
			srcElements = getAll( elem );

			for ( i = 0, l = srcElements.length; i < l; i++ ) {
				fixInput( srcElements[ i ], destElements[ i ] );
			}
		}

		// Copy the events from the original to the clone
		if ( dataAndEvents ) {
			if ( deepDataAndEvents ) {
				srcElements = srcElements || getAll( elem );
				destElements = destElements || getAll( clone );

				for ( i = 0, l = srcElements.length; i < l; i++ ) {
					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
				}
			} else {
				cloneCopyEvent( elem, clone );
			}
		}

		// Preserve script evaluation history
		destElements = getAll( clone, "script" );
		if ( destElements.length > 0 ) {
			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
		}

		// Return the cloned set
		return clone;
	},

	cleanData: function( elems ) {
		var data, elem, type,
			special = jQuery.event.special,
			i = 0;

		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
			if ( acceptData( elem ) ) {
				if ( ( data = elem[ dataPriv.expando ] ) ) {
					if ( data.events ) {
						for ( type in data.events ) {
							if ( special[ type ] ) {
								jQuery.event.remove( elem, type );

							// This is a shortcut to avoid jQuery.event.remove's overhead
							} else {
								jQuery.removeEvent( elem, type, data.handle );
							}
						}
					}

					// Support: Chrome <= 35-45+
					// Assign undefined instead of using delete, see Data#remove
					elem[ dataPriv.expando ] = undefined;
				}
				if ( elem[ dataUser.expando ] ) {

					// Support: Chrome <= 35-45+
					// Assign undefined instead of using delete, see Data#remove
					elem[ dataUser.expando ] = undefined;
				}
			}
		}
	}
} );

jQuery.fn.extend( {

	// Keep domManip exposed until 3.0 (gh-2225)
	domManip: domManip,

	detach: function( selector ) {
		return remove( this, selector, true );
	},

	remove: function( selector ) {
		return remove( this, selector );
	},

	text: function( value ) {
		return access( this, function( value ) {
			return value === undefined ?
				jQuery.text( this ) :
				this.empty().each( function() {
					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
						this.textContent = value;
					}
				} );
		}, null, value, arguments.length );
	},

	append: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				var target = manipulationTarget( this, elem );
				target.appendChild( elem );
			}
		} );
	},

	prepend: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
				var target = manipulationTarget( this, elem );
				target.insertBefore( elem, target.firstChild );
			}
		} );
	},

	before: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this );
			}
		} );
	},

	after: function() {
		return domManip( this, arguments, function( elem ) {
			if ( this.parentNode ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			}
		} );
	},

	empty: function() {
		var elem,
			i = 0;

		for ( ; ( elem = this[ i ] ) != null; i++ ) {
			if ( elem.nodeType === 1 ) {

				// Prevent memory leaks
				jQuery.cleanData( getAll( elem, false ) );

				// Remove any remaining nodes
				elem.textContent = "";
			}
		}

		return this;
	},

	clone: function( dataAndEvents, deepDataAndEvents ) {
		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

		return this.map( function() {
			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
		} );
	},

	html: function( value ) {
		return access( this, function( value ) {
			var elem = this[ 0 ] || {},
				i = 0,
				l = this.length;

			if ( value === undefined && elem.nodeType === 1 ) {
				return elem.innerHTML;
			}

			// See if we can take a shortcut and just use innerHTML
			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {

				value = jQuery.htmlPrefilter( value );

				try {
					for ( ; i < l; i++ ) {
						elem = this[ i ] || {};

						// Remove element nodes and prevent memory leaks
						if ( elem.nodeType === 1 ) {
							jQuery.cleanData( getAll( elem, false ) );
							elem.innerHTML = value;
						}
					}

					elem = 0;

				// If using innerHTML throws an exception, use the fallback method
				} catch ( e ) {}
			}

			if ( elem ) {
				this.empty().append( value );
			}
		}, null, value, arguments.length );
	},

	replaceWith: function() {
		var ignored = [];

		// Make the changes, replacing each non-ignored context element with the new content
		return domManip( this, arguments, function( elem ) {
			var parent = this.parentNode;

			if ( jQuery.inArray( this, ignored ) < 0 ) {
				jQuery.cleanData( getAll( this ) );
				if ( parent ) {
					parent.replaceChild( elem, this );
				}
			}

		// Force callback invocation
		}, ignored );
	}
} );

jQuery.each( {
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function( name, original ) {
	jQuery.fn[ name ] = function( selector ) {
		var elems,
			ret = [],
			insert = jQuery( selector ),
			last = insert.length - 1,
			i = 0;

		for ( ; i <= last; i++ ) {
			elems = i === last ? this : this.clone( true );
			jQuery( insert[ i ] )[ original ]( elems );

			// Support: QtWebKit
			// .get() because push.apply(_, arraylike) throws
			push.apply( ret, elems.get() );
		}

		return this.pushStack( ret );
	};
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return ( /^(?:checkbox|radio)$/i );
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return ( /<([\w:-]+)/ );
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return ( /^$|\/(?:java|ecma)script/i );
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

// We have to close these tags to support XHTML (#13200)
var wrapMap = {

	// Support: IE9
	option: [ 1, "<select multiple='multiple'>", "</select>" ],

	// XHTML parsers do not magically insert elements in the
	// same way that tag soup parsers do. So we cannot shorten
	// this by omitting <tbody> or other required elements.
	thead: [ 1, "<table>", "</table>" ],
	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],

	_default: [ 0, "", "" ]
};

// Support: IE9
wrapMap.optgroup = wrapMap.option;

wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

return wrapMap;
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

function getAll( context, tag ) {

	// Support: IE9-11+
	// Use typeof to avoid zero-argument method invocation on host objects (#15151)
	var ret = typeof context.getElementsByTagName !== "undefined" ?
			context.getElementsByTagName( tag || "*" ) :
			typeof context.querySelectorAll !== "undefined" ?
				context.querySelectorAll( tag || "*" ) :
			[];

	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
		jQuery.merge( [ context ], ret ) :
		ret;
}

return getAll;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(55)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( dataPriv ) {

// Mark scripts as having already been evaluated
function setGlobalEval( elems, refElements ) {
	var i = 0,
		l = elems.length;

	for ( ; i < l; i++ ) {
		dataPriv.set(
			elems[ i ],
			"globalEval",
			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
		);
	}
}

return setGlobalEval;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(285),
	__webpack_require__(286),
	__webpack_require__(287),
	__webpack_require__(288),
	__webpack_require__(289)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, rtagName, rscriptType, wrapMap, getAll, setGlobalEval ) {

var rhtml = /<|&#?\w+;/;

function buildFragment( elems, context, scripts, selection, ignored ) {
	var elem, tmp, tag, wrap, contains, j,
		fragment = context.createDocumentFragment(),
		nodes = [],
		i = 0,
		l = elems.length;

	for ( ; i < l; i++ ) {
		elem = elems[ i ];

		if ( elem || elem === 0 ) {

			// Add nodes directly
			if ( jQuery.type( elem ) === "object" ) {

				// Support: Android<4.1, PhantomJS<2
				// push.apply(_, arraylike) throws on ancient WebKit
				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );

			// Convert non-html into a text node
			} else if ( !rhtml.test( elem ) ) {
				nodes.push( context.createTextNode( elem ) );

			// Convert html into DOM nodes
			} else {
				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );

				// Deserialize a standard representation
				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
				wrap = wrapMap[ tag ] || wrapMap._default;
				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];

				// Descend through wrappers to the right content
				j = wrap[ 0 ];
				while ( j-- ) {
					tmp = tmp.lastChild;
				}

				// Support: Android<4.1, PhantomJS<2
				// push.apply(_, arraylike) throws on ancient WebKit
				jQuery.merge( nodes, tmp.childNodes );

				// Remember the top-level container
				tmp = fragment.firstChild;

				// Ensure the created nodes are orphaned (#12392)
				tmp.textContent = "";
			}
		}
	}

	// Remove wrapper from fragment
	fragment.textContent = "";

	i = 0;
	while ( ( elem = nodes[ i++ ] ) ) {

		// Skip elements already in the context collection (trac-4087)
		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
			if ( ignored ) {
				ignored.push( elem );
			}
			continue;
		}

		contains = jQuery.contains( elem.ownerDocument, elem );

		// Append to fragment
		tmp = getAll( fragment.appendChild( elem ), "script" );

		// Preserve script evaluation history
		if ( contains ) {
			setGlobalEval( tmp );
		}

		// Capture executables
		if ( scripts ) {
			j = 0;
			while ( ( elem = tmp[ j++ ] ) ) {
				if ( rscriptType.test( elem.type || "" ) ) {
					scripts.push( elem );
				}
			}
		}
	}

	return fragment;
}

return buildFragment;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(37),
	__webpack_require__(96)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( document, support ) {

( function() {
	var fragment = document.createDocumentFragment(),
		div = fragment.appendChild( document.createElement( "div" ) ),
		input = document.createElement( "input" );

	// Support: Android 4.0-4.3, Safari<=5.1
	// Check state lost if the name is set (#11217)
	// Support: Windows Web Apps (WWA)
	// `name` and `type` must use .setAttribute for WWA (#14901)
	input.setAttribute( "type", "radio" );
	input.setAttribute( "checked", "checked" );
	input.setAttribute( "name", "t" );

	div.appendChild( input );

	// Support: Safari<=5.1, Android<4.2
	// Older WebKit doesn't clone checked state correctly in fragments
	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Support: IE<=11+
	// Make sure textarea (and checkbox) defaultValue is properly cloned
	div.innerHTML = "<textarea>x</textarea>";
	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
} )();

return support;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(82),
	__webpack_require__(191),
	__webpack_require__(55),

	__webpack_require__(52),
	__webpack_require__(42)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document, rnotwhite, slice, dataPriv ) {

var
	rkeyEvent = /^key/,
	rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
	rtypenamespace = /^([^.]*)(?:\.(.+)|)/;

function returnTrue() {
	return true;
}

function returnFalse() {
	return false;
}

// Support: IE9
// See #13393 for more info
function safeActiveElement() {
	try {
		return document.activeElement;
	} catch ( err ) { }
}

function on( elem, types, selector, data, fn, one ) {
	var origFn, type;

	// Types can be a map of types/handlers
	if ( typeof types === "object" ) {

		// ( types-Object, selector, data )
		if ( typeof selector !== "string" ) {

			// ( types-Object, data )
			data = data || selector;
			selector = undefined;
		}
		for ( type in types ) {
			on( elem, type, selector, data, types[ type ], one );
		}
		return elem;
	}

	if ( data == null && fn == null ) {

		// ( types, fn )
		fn = selector;
		data = selector = undefined;
	} else if ( fn == null ) {
		if ( typeof selector === "string" ) {

			// ( types, selector, fn )
			fn = data;
			data = undefined;
		} else {

			// ( types, data, fn )
			fn = data;
			data = selector;
			selector = undefined;
		}
	}
	if ( fn === false ) {
		fn = returnFalse;
	} else if ( !fn ) {
		return elem;
	}

	if ( one === 1 ) {
		origFn = fn;
		fn = function( event ) {

			// Can use an empty set, since event contains the info
			jQuery().off( event );
			return origFn.apply( this, arguments );
		};

		// Use same guid so caller can remove using origFn
		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
	}
	return elem.each( function() {
		jQuery.event.add( this, types, fn, data, selector );
	} );
}

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

	global: {},

	add: function( elem, types, handler, data, selector ) {

		var handleObjIn, eventHandle, tmp,
			events, t, handleObj,
			special, handlers, type, namespaces, origType,
			elemData = dataPriv.get( elem );

		// Don't attach events to noData or text/comment nodes (but allow plain objects)
		if ( !elemData ) {
			return;
		}

		// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
			selector = handleObjIn.selector;
		}

		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure and main handler, if this is the first
		if ( !( events = elemData.events ) ) {
			events = elemData.events = {};
		}
		if ( !( eventHandle = elemData.handle ) ) {
			eventHandle = elemData.handle = function( e ) {

				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
			};
		}

		// Handle multiple events separated by a space
		types = ( types || "" ).match( rnotwhite ) || [ "" ];
		t = types.length;
		while ( t-- ) {
			tmp = rtypenamespace.exec( types[ t ] ) || [];
			type = origType = tmp[ 1 ];
			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();

			// There *must* be a type, no attaching namespace-only handlers
			if ( !type ) {
				continue;
			}

			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};

			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;

			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};

			// handleObj is passed to all event handlers
			handleObj = jQuery.extend( {
				type: type,
				origType: origType,
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
				namespace: namespaces.join( "." )
			}, handleObjIn );

			// Init the event handler queue if we're the first
			if ( !( handlers = events[ type ] ) ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;

				// Only use addEventListener if the special events handler returns false
				if ( !special.setup ||
					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {

					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle );
					}
				}
			}

			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}

			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
		}

	},

	// Detach an event or set of events from an element
	remove: function( elem, types, handler, selector, mappedTypes ) {

		var j, origCount, tmp,
			events, t, handleObj,
			special, handlers, type, namespaces, origType,
			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );

		if ( !elemData || !( events = elemData.events ) ) {
			return;
		}

		// Once for each type.namespace in types; type may be omitted
		types = ( types || "" ).match( rnotwhite ) || [ "" ];
		t = types.length;
		while ( t-- ) {
			tmp = rtypenamespace.exec( types[ t ] ) || [];
			type = origType = tmp[ 1 ];
			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();

			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}

			special = jQuery.event.special[ type ] || {};
			type = ( selector ? special.delegateType : special.bindType ) || type;
			handlers = events[ type ] || [];
			tmp = tmp[ 2 ] &&
				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );

			// Remove matching events
			origCount = j = handlers.length;
			while ( j-- ) {
				handleObj = handlers[ j ];

				if ( ( mappedTypes || origType === handleObj.origType ) &&
					( !handler || handler.guid === handleObj.guid ) &&
					( !tmp || tmp.test( handleObj.namespace ) ) &&
					( !selector || selector === handleObj.selector ||
						selector === "**" && handleObj.selector ) ) {
					handlers.splice( j, 1 );

					if ( handleObj.selector ) {
						handlers.delegateCount--;
					}
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}

			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			if ( origCount && !handlers.length ) {
				if ( !special.teardown ||
					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {

					jQuery.removeEvent( elem, type, elemData.handle );
				}

				delete events[ type ];
			}
		}

		// Remove data and the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			dataPriv.remove( elem, "handle events" );
		}
	},

	dispatch: function( event ) {

		// Make a writable jQuery.Event from the native event object
		event = jQuery.event.fix( event );

		var i, j, ret, matched, handleObj,
			handlerQueue = [],
			args = slice.call( arguments ),
			handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
			special = jQuery.event.special[ event.type ] || {};

		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		args[ 0 ] = event;
		event.delegateTarget = this;

		// Call the preDispatch hook for the mapped type, and let it bail if desired
		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
			return;
		}

		// Determine handlers
		handlerQueue = jQuery.event.handlers.call( this, event, handlers );

		// Run delegates first; they may want to stop propagation beneath us
		i = 0;
		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
			event.currentTarget = matched.elem;

			j = 0;
			while ( ( handleObj = matched.handlers[ j++ ] ) &&
				!event.isImmediatePropagationStopped() ) {

				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
				// a subset or equal to those in the bound event (both can have no namespace).
				if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {

					event.handleObj = handleObj;
					event.data = handleObj.data;

					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
						handleObj.handler ).apply( matched.elem, args );

					if ( ret !== undefined ) {
						if ( ( event.result = ret ) === false ) {
							event.preventDefault();
							event.stopPropagation();
						}
					}
				}
			}
		}

		// Call the postDispatch hook for the mapped type
		if ( special.postDispatch ) {
			special.postDispatch.call( this, event );
		}

		return event.result;
	},

	handlers: function( event, handlers ) {
		var i, matches, sel, handleObj,
			handlerQueue = [],
			delegateCount = handlers.delegateCount,
			cur = event.target;

		// Support (at least): Chrome, IE9
		// Find delegate handlers
		// Black-hole SVG <use> instance trees (#13180)
		//
		// Support: Firefox<=42+
		// Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
		if ( delegateCount && cur.nodeType &&
			( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {

			for ( ; cur !== this; cur = cur.parentNode || this ) {

				// Don't check non-elements (#13208)
				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
				if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
					matches = [];
					for ( i = 0; i < delegateCount; i++ ) {
						handleObj = handlers[ i ];

						// Don't conflict with Object.prototype properties (#13203)
						sel = handleObj.selector + " ";

						if ( matches[ sel ] === undefined ) {
							matches[ sel ] = handleObj.needsContext ?
								jQuery( sel, this ).index( cur ) > -1 :
								jQuery.find( sel, this, null, [ cur ] ).length;
						}
						if ( matches[ sel ] ) {
							matches.push( handleObj );
						}
					}
					if ( matches.length ) {
						handlerQueue.push( { elem: cur, handlers: matches } );
					}
				}
			}
		}

		// Add the remaining (directly-bound) handlers
		if ( delegateCount < handlers.length ) {
			handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
		}

		return handlerQueue;
	},

	// Includes some event props shared by KeyEvent and MouseEvent
	props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
		"metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ),

	fixHooks: {},

	keyHooks: {
		props: "char charCode key keyCode".split( " " ),
		filter: function( event, original ) {

			// Add which for key events
			if ( event.which == null ) {
				event.which = original.charCode != null ? original.charCode : original.keyCode;
			}

			return event;
		}
	},

	mouseHooks: {
		props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " +
			"screenX screenY toElement" ).split( " " ),
		filter: function( event, original ) {
			var eventDoc, doc, body,
				button = original.button;

			// Calculate pageX/Y if missing and clientX/Y available
			if ( event.pageX == null && original.clientX != null ) {
				eventDoc = event.target.ownerDocument || document;
				doc = eventDoc.documentElement;
				body = eventDoc.body;

				event.pageX = original.clientX +
					( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
					( doc && doc.clientLeft || body && body.clientLeft || 0 );
				event.pageY = original.clientY +
					( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) -
					( doc && doc.clientTop  || body && body.clientTop  || 0 );
			}

			// Add which for click: 1 === left; 2 === middle; 3 === right
			// Note: button is not normalized, so don't use it
			if ( !event.which && button !== undefined ) {
				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
			}

			return event;
		}
	},

	fix: function( event ) {
		if ( event[ jQuery.expando ] ) {
			return event;
		}

		// Create a writable copy of the event object and normalize some properties
		var i, prop, copy,
			type = event.type,
			originalEvent = event,
			fixHook = this.fixHooks[ type ];

		if ( !fixHook ) {
			this.fixHooks[ type ] = fixHook =
				rmouseEvent.test( type ) ? this.mouseHooks :
				rkeyEvent.test( type ) ? this.keyHooks :
				{};
		}
		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

		event = new jQuery.Event( originalEvent );

		i = copy.length;
		while ( i-- ) {
			prop = copy[ i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Support: Cordova 2.5 (WebKit) (#13255)
		// All events should have a target; Cordova deviceready doesn't
		if ( !event.target ) {
			event.target = document;
		}

		// Support: Safari 6.0+, Chrome<28
		// Target should not be a text node (#504, #13143)
		if ( event.target.nodeType === 3 ) {
			event.target = event.target.parentNode;
		}

		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
	},

	special: {
		load: {

			// Prevent triggered image.load events from bubbling to window.load
			noBubble: true
		},
		focus: {

			// Fire native event if possible so blur/focus sequence is correct
			trigger: function() {
				if ( this !== safeActiveElement() && this.focus ) {
					this.focus();
					return false;
				}
			},
			delegateType: "focusin"
		},
		blur: {
			trigger: function() {
				if ( this === safeActiveElement() && this.blur ) {
					this.blur();
					return false;
				}
			},
			delegateType: "focusout"
		},
		click: {

			// For checkbox, fire native event so checked state will be right
			trigger: function() {
				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
					this.click();
					return false;
				}
			},

			// For cross-browser consistency, don't fire native .click() on links
			_default: function( event ) {
				return jQuery.nodeName( event.target, "a" );
			}
		},

		beforeunload: {
			postDispatch: function( event ) {

				// Support: Firefox 20+
				// Firefox doesn't alert if the returnValue field is not set.
				if ( event.result !== undefined && event.originalEvent ) {
					event.originalEvent.returnValue = event.result;
				}
			}
		}
	}
};

jQuery.removeEvent = function( elem, type, handle ) {

	// This "if" is needed for plain objects
	if ( elem.removeEventListener ) {
		elem.removeEventListener( type, handle );
	}
};

jQuery.Event = function( src, props ) {

	// Allow instantiation without the 'new' keyword
	if ( !( this instanceof jQuery.Event ) ) {
		return new jQuery.Event( src, props );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;

		// Events bubbling up the document may have been marked as prevented
		// by a handler lower down the tree; reflect the correct value.
		this.isDefaultPrevented = src.defaultPrevented ||
				src.defaultPrevented === undefined &&

				// Support: Android<4.0
				src.returnValue === false ?
			returnTrue :
			returnFalse;

	// Event type
	} else {
		this.type = src;
	}

	// Put explicitly provided properties onto the event object
	if ( props ) {
		jQuery.extend( this, props );
	}

	// Create a timestamp if incoming event doesn't have one
	this.timeStamp = src && src.timeStamp || jQuery.now();

	// Mark it as fixed
	this[ jQuery.expando ] = true;
};

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	constructor: jQuery.Event,
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse,
	isSimulated: false,

	preventDefault: function() {
		var e = this.originalEvent;

		this.isDefaultPrevented = returnTrue;

		if ( e && !this.isSimulated ) {
			e.preventDefault();
		}
	},
	stopPropagation: function() {
		var e = this.originalEvent;

		this.isPropagationStopped = returnTrue;

		if ( e && !this.isSimulated ) {
			e.stopPropagation();
		}
	},
	stopImmediatePropagation: function() {
		var e = this.originalEvent;

		this.isImmediatePropagationStopped = returnTrue;

		if ( e && !this.isSimulated ) {
			e.stopImmediatePropagation();
		}

		this.stopPropagation();
	}
};

// Create mouseenter/leave events using mouseover/out and event-time checks
// so that event delegation works in jQuery.
// Do the same for pointerenter/pointerleave and pointerover/pointerout
//
// Support: Safari 7 only
// Safari sends mouseenter too often; see:
// https://code.google.com/p/chromium/issues/detail?id=470258
// for the description of the bug (it existed in older Chrome versions as well).
jQuery.each( {
	mouseenter: "mouseover",
	mouseleave: "mouseout",
	pointerenter: "pointerover",
	pointerleave: "pointerout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		delegateType: fix,
		bindType: fix,

		handle: function( event ) {
			var ret,
				target = this,
				related = event.relatedTarget,
				handleObj = event.handleObj;

			// For mouseenter/leave call the handler if related is outside the target.
			// NB: No relatedTarget if the mouse left/entered the browser window
			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
				event.type = handleObj.origType;
				ret = handleObj.handler.apply( this, arguments );
				event.type = fix;
			}
			return ret;
		}
	};
} );

jQuery.fn.extend( {
	on: function( types, selector, data, fn ) {
		return on( this, types, selector, data, fn );
	},
	one: function( types, selector, data, fn ) {
		return on( this, types, selector, data, fn, 1 );
	},
	off: function( types, selector, fn ) {
		var handleObj, type;
		if ( types && types.preventDefault && types.handleObj ) {

			// ( event )  dispatched jQuery.Event
			handleObj = types.handleObj;
			jQuery( types.delegateTarget ).off(
				handleObj.namespace ?
					handleObj.origType + "." + handleObj.namespace :
					handleObj.origType,
				handleObj.selector,
				handleObj.handler
			);
			return this;
		}
		if ( typeof types === "object" ) {

			// ( types-object [, selector] )
			for ( type in types ) {
				this.off( type, selector, types[ type ] );
			}
			return this;
		}
		if ( selector === false || typeof selector === "function" ) {

			// ( types [, fn] )
			fn = selector;
			selector = undefined;
		}
		if ( fn === false ) {
			fn = returnFalse;
		}
		return this.each( function() {
			jQuery.event.remove( this, types, fn, selector );
		} );
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(124)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

function Tween( elem, options, prop, end, easing ) {
	return new Tween.prototype.init( elem, options, prop, end, easing );
}
jQuery.Tween = Tween;

Tween.prototype = {
	constructor: Tween,
	init: function( elem, options, prop, end, easing, unit ) {
		this.elem = elem;
		this.prop = prop;
		this.easing = easing || jQuery.easing._default;
		this.options = options;
		this.start = this.now = this.cur();
		this.end = end;
		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
	},
	cur: function() {
		var hooks = Tween.propHooks[ this.prop ];

		return hooks && hooks.get ?
			hooks.get( this ) :
			Tween.propHooks._default.get( this );
	},
	run: function( percent ) {
		var eased,
			hooks = Tween.propHooks[ this.prop ];

		if ( this.options.duration ) {
			this.pos = eased = jQuery.easing[ this.easing ](
				percent, this.options.duration * percent, 0, 1, this.options.duration
			);
		} else {
			this.pos = eased = percent;
		}
		this.now = ( this.end - this.start ) * eased + this.start;

		if ( this.options.step ) {
			this.options.step.call( this.elem, this.now, this );
		}

		if ( hooks && hooks.set ) {
			hooks.set( this );
		} else {
			Tween.propHooks._default.set( this );
		}
		return this;
	}
};

Tween.prototype.init.prototype = Tween.prototype;

Tween.propHooks = {
	_default: {
		get: function( tween ) {
			var result;

			// Use a property on the element directly when it is not a DOM element,
			// or when there is no matching style property that exists.
			if ( tween.elem.nodeType !== 1 ||
				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
				return tween.elem[ tween.prop ];
			}

			// Passing an empty string as a 3rd parameter to .css will automatically
			// attempt a parseFloat and fallback to a string if the parse fails.
			// Simple values such as "10px" are parsed to Float;
			// complex values such as "rotate(1rad)" are returned as-is.
			result = jQuery.css( tween.elem, tween.prop, "" );

			// Empty strings, null, undefined and "auto" are converted to 0.
			return !result || result === "auto" ? 0 : result;
		},
		set: function( tween ) {

			// Use step hook for back compat.
			// Use cssHook if its there.
			// Use .style if available and use plain properties where available.
			if ( jQuery.fx.step[ tween.prop ] ) {
				jQuery.fx.step[ tween.prop ]( tween );
			} else if ( tween.elem.nodeType === 1 &&
				( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
					jQuery.cssHooks[ tween.prop ] ) ) {
				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
			} else {
				tween.elem[ tween.prop ] = tween.now;
			}
		}
	}
};

// Support: IE9
// Panic based approach to setting things on disconnected nodes
Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
	set: function( tween ) {
		if ( tween.elem.nodeType && tween.elem.parentNode ) {
			tween.elem[ tween.prop ] = tween.now;
		}
	}
};

jQuery.easing = {
	linear: function( p ) {
		return p;
	},
	swing: function( p ) {
		return 0.5 - Math.cos( p * Math.PI ) / 2;
	},
	_default: "swing"
};

jQuery.fx = Tween.prototype.init;

// Back Compat <1.8 extension point
jQuery.fx.step = {};

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(199),
	__webpack_require__(83),
	__webpack_require__(291),
	__webpack_require__(37),
	__webpack_require__(198),
	__webpack_require__(200),
	__webpack_require__(280),
	__webpack_require__(281),
	__webpack_require__(292),
	__webpack_require__(578),
	__webpack_require__(293),
	__webpack_require__(282),
	__webpack_require__(283),
	__webpack_require__(295),
	__webpack_require__(201),
	__webpack_require__(55),

	__webpack_require__(52),
	__webpack_require__(277),
	__webpack_require__(42) // contains
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, pnum, access, rmargin, document, rcssNum, rnumnonpx, cssExpand, isHidden,
	getStyles, swap, curCSS, adjustCSS, defaultDisplay, addGetHookIf, support, dataPriv ) {

var

	// Swappable if display is none or starts with table
	// except "table", "table-cell", or "table-caption"
	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
	rdisplayswap = /^(none|table(?!-c[ea]).+)/,

	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssNormalTransform = {
		letterSpacing: "0",
		fontWeight: "400"
	},

	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
	emptyStyle = document.createElement( "div" ).style;

// Return a css property mapped to a potentially vendor prefixed property
function vendorPropName( name ) {

	// Shortcut for names that are not vendor prefixed
	if ( name in emptyStyle ) {
		return name;
	}

	// Check for vendor prefixed names
	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
		i = cssPrefixes.length;

	while ( i-- ) {
		name = cssPrefixes[ i ] + capName;
		if ( name in emptyStyle ) {
			return name;
		}
	}
}

function setPositiveNumber( elem, value, subtract ) {

	// Any relative (+/-) values have already been
	// normalized at this point
	var matches = rcssNum.exec( value );
	return matches ?

		// Guard against undefined "subtract", e.g., when used as in cssHooks
		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
		value;
}

function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
	var i = extra === ( isBorderBox ? "border" : "content" ) ?

		// If we already have the right measurement, avoid augmentation
		4 :

		// Otherwise initialize for horizontal or vertical properties
		name === "width" ? 1 : 0,

		val = 0;

	for ( ; i < 4; i += 2 ) {

		// Both box models exclude margin, so add it if we want it
		if ( extra === "margin" ) {
			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
		}

		if ( isBorderBox ) {

			// border-box includes padding, so remove it if we want content
			if ( extra === "content" ) {
				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
			}

			// At this point, extra isn't border nor margin, so remove border
			if ( extra !== "margin" ) {
				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
			}
		} else {

			// At this point, extra isn't content, so add padding
			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );

			// At this point, extra isn't content nor padding, so add border
			if ( extra !== "padding" ) {
				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
			}
		}
	}

	return val;
}

function getWidthOrHeight( elem, name, extra ) {

	// Start with offset property, which is equivalent to the border-box value
	var valueIsBorderBox = true,
		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
		styles = getStyles( elem ),
		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";

	// Some non-html elements return undefined for offsetWidth, so check for null/undefined
	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
	if ( val <= 0 || val == null ) {

		// Fall back to computed then uncomputed css if necessary
		val = curCSS( elem, name, styles );
		if ( val < 0 || val == null ) {
			val = elem.style[ name ];
		}

		// Computed unit is not pixels. Stop here and return.
		if ( rnumnonpx.test( val ) ) {
			return val;
		}

		// Check for style in case a browser which returns unreliable values
		// for getComputedStyle silently falls back to the reliable elem.style
		valueIsBorderBox = isBorderBox &&
			( support.boxSizingReliable() || val === elem.style[ name ] );

		// Normalize "", auto, and prepare for extra
		val = parseFloat( val ) || 0;
	}

	// Use the active box-sizing model to add/subtract irrelevant styles
	return ( val +
		augmentWidthOrHeight(
			elem,
			name,
			extra || ( isBorderBox ? "border" : "content" ),
			valueIsBorderBox,
			styles
		)
	) + "px";
}

function showHide( elements, show ) {
	var display, elem, hidden,
		values = [],
		index = 0,
		length = elements.length;

	for ( ; index < length; index++ ) {
		elem = elements[ index ];
		if ( !elem.style ) {
			continue;
		}

		values[ index ] = dataPriv.get( elem, "olddisplay" );
		display = elem.style.display;
		if ( show ) {

			// Reset the inline display of this element to learn if it is
			// being hidden by cascaded rules or not
			if ( !values[ index ] && display === "none" ) {
				elem.style.display = "";
			}

			// Set elements which have been overridden with display: none
			// in a stylesheet to whatever the default browser style is
			// for such an element
			if ( elem.style.display === "" && isHidden( elem ) ) {
				values[ index ] = dataPriv.access(
					elem,
					"olddisplay",
					defaultDisplay( elem.nodeName )
				);
			}
		} else {
			hidden = isHidden( elem );

			if ( display !== "none" || !hidden ) {
				dataPriv.set(
					elem,
					"olddisplay",
					hidden ? display : jQuery.css( elem, "display" )
				);
			}
		}
	}

	// Set the display of most of the elements in a second loop
	// to avoid the constant reflow
	for ( index = 0; index < length; index++ ) {
		elem = elements[ index ];
		if ( !elem.style ) {
			continue;
		}
		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
			elem.style.display = show ? values[ index ] || "" : "none";
		}
	}

	return elements;
}

jQuery.extend( {

	// Add in style property hooks for overriding the default
	// behavior of getting and setting a style property
	cssHooks: {
		opacity: {
			get: function( elem, computed ) {
				if ( computed ) {

					// We should always get a number back from opacity
					var ret = curCSS( elem, "opacity" );
					return ret === "" ? "1" : ret;
				}
			}
		}
	},

	// Don't automatically add "px" to these possibly-unitless properties
	cssNumber: {
		"animationIterationCount": true,
		"columnCount": true,
		"fillOpacity": true,
		"flexGrow": true,
		"flexShrink": true,
		"fontWeight": true,
		"lineHeight": true,
		"opacity": true,
		"order": true,
		"orphans": true,
		"widows": true,
		"zIndex": true,
		"zoom": true
	},

	// Add in properties whose names you wish to fix before
	// setting or getting the value
	cssProps: {
		"float": "cssFloat"
	},

	// Get and set the style property on a DOM Node
	style: function( elem, name, value, extra ) {

		// Don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
			return;
		}

		// Make sure that we're working with the right name
		var ret, type, hooks,
			origName = jQuery.camelCase( name ),
			style = elem.style;

		name = jQuery.cssProps[ origName ] ||
			( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );

		// Gets hook for the prefixed version, then unprefixed version
		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

		// Check if we're setting a value
		if ( value !== undefined ) {
			type = typeof value;

			// Convert "+=" or "-=" to relative numbers (#7345)
			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
				value = adjustCSS( elem, name, ret );

				// Fixes bug #9237
				type = "number";
			}

			// Make sure that null and NaN values aren't set (#7116)
			if ( value == null || value !== value ) {
				return;
			}

			// If a number was passed in, add the unit (except for certain CSS properties)
			if ( type === "number" ) {
				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
			}

			// Support: IE9-11+
			// background-* props affect original clone's values
			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
				style[ name ] = "inherit";
			}

			// If a hook was provided, use that value, otherwise just set the specified value
			if ( !hooks || !( "set" in hooks ) ||
				( value = hooks.set( elem, value, extra ) ) !== undefined ) {

				style[ name ] = value;
			}

		} else {

			// If a hook was provided get the non-computed value from there
			if ( hooks && "get" in hooks &&
				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {

				return ret;
			}

			// Otherwise just get the value from the style object
			return style[ name ];
		}
	},

	css: function( elem, name, extra, styles ) {
		var val, num, hooks,
			origName = jQuery.camelCase( name );

		// Make sure that we're working with the right name
		name = jQuery.cssProps[ origName ] ||
			( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );

		// Try prefixed name followed by the unprefixed name
		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

		// If a hook was provided get the computed value from there
		if ( hooks && "get" in hooks ) {
			val = hooks.get( elem, true, extra );
		}

		// Otherwise, if a way to get the computed value exists, use that
		if ( val === undefined ) {
			val = curCSS( elem, name, styles );
		}

		// Convert "normal" to computed value
		if ( val === "normal" && name in cssNormalTransform ) {
			val = cssNormalTransform[ name ];
		}

		// Make numeric if forced or a qualifier was provided and val looks numeric
		if ( extra === "" || extra ) {
			num = parseFloat( val );
			return extra === true || isFinite( num ) ? num || 0 : val;
		}
		return val;
	}
} );

jQuery.each( [ "height", "width" ], function( i, name ) {
	jQuery.cssHooks[ name ] = {
		get: function( elem, computed, extra ) {
			if ( computed ) {

				// Certain elements can have dimension info if we invisibly show them
				// but it must have a current display style that would benefit
				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
					elem.offsetWidth === 0 ?
						swap( elem, cssShow, function() {
							return getWidthOrHeight( elem, name, extra );
						} ) :
						getWidthOrHeight( elem, name, extra );
			}
		},

		set: function( elem, value, extra ) {
			var matches,
				styles = extra && getStyles( elem ),
				subtract = extra && augmentWidthOrHeight(
					elem,
					name,
					extra,
					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
					styles
				);

			// Convert to pixels if value adjustment is needed
			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
				( matches[ 3 ] || "px" ) !== "px" ) {

				elem.style[ name ] = value;
				value = jQuery.css( elem, name );
			}

			return setPositiveNumber( elem, value, subtract );
		}
	};
} );

jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
	function( elem, computed ) {
		if ( computed ) {
			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
				elem.getBoundingClientRect().left -
					swap( elem, { marginLeft: 0 }, function() {
						return elem.getBoundingClientRect().left;
					} )
				) + "px";
		}
	}
);

// Support: Android 2.3
jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
	function( elem, computed ) {
		if ( computed ) {
			return swap( elem, { "display": "inline-block" },
				curCSS, [ elem, "marginRight" ] );
		}
	}
);

// These hooks are used by animate to expand properties
jQuery.each( {
	margin: "",
	padding: "",
	border: "Width"
}, function( prefix, suffix ) {
	jQuery.cssHooks[ prefix + suffix ] = {
		expand: function( value ) {
			var i = 0,
				expanded = {},

				// Assumes a single number if not a string
				parts = typeof value === "string" ? value.split( " " ) : [ value ];

			for ( ; i < 4; i++ ) {
				expanded[ prefix + cssExpand[ i ] + suffix ] =
					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
			}

			return expanded;
		}
	};

	if ( !rmargin.test( prefix ) ) {
		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
	}
} );

jQuery.fn.extend( {
	css: function( name, value ) {
		return access( this, function( elem, name, value ) {
			var styles, len,
				map = {},
				i = 0;

			if ( jQuery.isArray( name ) ) {
				styles = getStyles( elem );
				len = name.length;

				for ( ; i < len; i++ ) {
					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
				}

				return map;
			}

			return value !== undefined ?
				jQuery.style( elem, name, value ) :
				jQuery.css( elem, name );
		}, name, value, arguments.length > 1 );
	},
	show: function() {
		return showHide( this, true );
	},
	hide: function() {
		return showHide( this );
	},
	toggle: function( state ) {
		if ( typeof state === "boolean" ) {
			return state ? this.show() : this.hide();
		}

		return this.each( function() {
			if ( isHidden( this ) ) {
				jQuery( this ).show();
			} else {
				jQuery( this ).hide();
			}
		} );
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return ( /^margin/ );
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(199)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( pnum ) {
	return new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return function( elem ) {

		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
		// IE throws on elements created in popups
		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
		var view = elem.ownerDocument.defaultView;

		if ( !view || !view.opener ) {
			view = window;
		}

		return view.getComputedStyle( elem );
	};
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

// A method for quickly swapping in/out CSS properties to get correct calculations.
return function( elem, options, callback, args ) {
	var ret, name,
		old = {};

	// Remember the old values, and insert the new ones
	for ( name in options ) {
		old[ name ] = elem.style[ name ];
		elem.style[ name ] = options[ name ];
	}

	ret = callback.apply( elem, args || [] );

	// Revert the old values
	for ( name in options ) {
		elem.style[ name ] = old[ name ];
	}

	return ret;
};

}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(200),
	__webpack_require__(291),
	__webpack_require__(292),
	__webpack_require__(201),
	__webpack_require__(42) // Get jQuery.contains
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, rnumnonpx, rmargin, getStyles, support ) {

function curCSS( elem, name, computed ) {
	var width, minWidth, maxWidth, ret,
		style = elem.style;

	computed = computed || getStyles( elem );
	ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;

	// Support: Opera 12.1x only
	// Fall back to style even without computed
	// computed is undefined for elems on document fragments
	if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {
		ret = jQuery.style( elem, name );
	}

	// Support: IE9
	// getPropertyValue is only needed for .css('filter') (#12537)
	if ( computed ) {

		// A tribute to the "awesome hack by Dean Edwards"
		// Android Browser returns percentage for some values,
		// but width seems to be reliably pixels.
		// This is against the CSSOM draft spec:
		// http://dev.w3.org/csswg/cssom/#resolved-values
		if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {

			// Remember the original values
			width = style.width;
			minWidth = style.minWidth;
			maxWidth = style.maxWidth;

			// Put in the new values to get a computed value out
			style.minWidth = style.maxWidth = style.width = ret;
			ret = computed.width;

			// Revert the changed values
			style.width = width;
			style.minWidth = minWidth;
			style.maxWidth = maxWidth;
		}
	}

	return ret !== undefined ?

		// Support: IE9-11+
		// IE returns zIndex value as an integer.
		ret + "" :
		ret;
}

return curCSS;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(294),
	__webpack_require__(96)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document, documentElement, support ) {

( function() {
	var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
		container = document.createElement( "div" ),
		div = document.createElement( "div" );

	// Finish early in limited (non-browser) environments
	if ( !div.style ) {
		return;
	}

	// Support: IE9-11+
	// Style of cloned element affects source element cloned (#8908)
	div.style.backgroundClip = "content-box";
	div.cloneNode( true ).style.backgroundClip = "";
	support.clearCloneStyle = div.style.backgroundClip === "content-box";

	container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
		"padding:0;margin-top:1px;position:absolute";
	container.appendChild( div );

	// Executing both pixelPosition & boxSizingReliable tests require only one layout
	// so they're executed at the same time to save the second computation.
	function computeStyleTests() {
		div.style.cssText =

			// Support: Firefox<29, Android 2.3
			// Vendor-prefix box-sizing
			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" +
			"position:relative;display:block;" +
			"margin:auto;border:1px;padding:1px;" +
			"top:1%;width:50%";
		div.innerHTML = "";
		documentElement.appendChild( container );

		var divStyle = window.getComputedStyle( div );
		pixelPositionVal = divStyle.top !== "1%";
		reliableMarginLeftVal = divStyle.marginLeft === "2px";
		boxSizingReliableVal = divStyle.width === "4px";

		// Support: Android 4.0 - 4.3 only
		// Some styles come back with percentage values, even though they shouldn't
		div.style.marginRight = "50%";
		pixelMarginRightVal = divStyle.marginRight === "4px";

		documentElement.removeChild( container );
	}

	jQuery.extend( support, {
		pixelPosition: function() {

			// This test is executed only once but we still do memoizing
			// since we can use the boxSizingReliable pre-computing.
			// No need to check if the test was already performed, though.
			computeStyleTests();
			return pixelPositionVal;
		},
		boxSizingReliable: function() {
			if ( boxSizingReliableVal == null ) {
				computeStyleTests();
			}
			return boxSizingReliableVal;
		},
		pixelMarginRight: function() {

			// Support: Android 4.0-4.3
			// We're checking for boxSizingReliableVal here instead of pixelMarginRightVal
			// since that compresses better and they're computed together anyway.
			if ( boxSizingReliableVal == null ) {
				computeStyleTests();
			}
			return pixelMarginRightVal;
		},
		reliableMarginLeft: function() {

			// Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37
			if ( boxSizingReliableVal == null ) {
				computeStyleTests();
			}
			return reliableMarginLeftVal;
		},
		reliableMarginRight: function() {

			// Support: Android 2.3
			// Check if div with explicit width and no margin-right incorrectly
			// gets computed margin-right based on width of container. (#3333)
			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
			// This support function is only executed once so no memoizing is needed.
			var ret,
				marginDiv = div.appendChild( document.createElement( "div" ) );

			// Reset CSS: box-sizing; display; margin; border; padding
			marginDiv.style.cssText = div.style.cssText =

				// Support: Android 2.3
				// Vendor-prefix box-sizing
				"-webkit-box-sizing:content-box;box-sizing:content-box;" +
				"display:block;margin:0;border:0;padding:0";
			marginDiv.style.marginRight = marginDiv.style.width = "0";
			div.style.width = "1px";
			documentElement.appendChild( container );

			ret = !parseFloat( window.getComputedStyle( marginDiv ).marginRight );

			documentElement.removeChild( container );
			div.removeChild( marginDiv );

			return ret;
		}
	} );
} )();

return support;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(37)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( document ) {
	return document.documentElement;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {

function addGetHookIf( conditionFn, hookFn ) {

	// Define the hook, we'll check on the first run if it's really needed.
	return {
		get: function() {
			if ( conditionFn() ) {

				// Hook not needed (or it's not possible to use it due
				// to missing dependency), remove it.
				delete this.get;
				return;
			}

			// Hook needed; redefine it so that the support test is not executed again.
			return ( this.get = hookFn ).apply( this, arguments );
		}
	};
}

return addGetHookIf;

}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(580),
	__webpack_require__(296),
	__webpack_require__(581),
	__webpack_require__(582)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Return jQuery for attributes-only inclusion
return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(83),
	__webpack_require__(202),
	__webpack_require__(82),
	__webpack_require__(42)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, access, support, rnotwhite ) {

var boolHook,
	attrHandle = jQuery.expr.attrHandle;

jQuery.fn.extend( {
	attr: function( name, value ) {
		return access( this, jQuery.attr, name, value, arguments.length > 1 );
	},

	removeAttr: function( name ) {
		return this.each( function() {
			jQuery.removeAttr( this, name );
		} );
	}
} );

jQuery.extend( {
	attr: function( elem, name, value ) {
		var ret, hooks,
			nType = elem.nodeType;

		// Don't get/set attributes on text, comment and attribute nodes
		if ( nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		// Fallback to prop when attributes are not supported
		if ( typeof elem.getAttribute === "undefined" ) {
			return jQuery.prop( elem, name, value );
		}

		// All attributes are lowercase
		// Grab necessary hook if one is defined
		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
			name = name.toLowerCase();
			hooks = jQuery.attrHooks[ name ] ||
				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
		}

		if ( value !== undefined ) {
			if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return;
			}

			if ( hooks && "set" in hooks &&
				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
				return ret;
			}

			elem.setAttribute( name, value + "" );
			return value;
		}

		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
			return ret;
		}

		ret = jQuery.find.attr( elem, name );

		// Non-existent attributes return null, we normalize to undefined
		return ret == null ? undefined : ret;
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				if ( !support.radioValue && value === "radio" &&
					jQuery.nodeName( elem, "input" ) ) {
					var val = elem.value;
					elem.setAttribute( "type", value );
					if ( val ) {
						elem.value = val;
					}
					return value;
				}
			}
		}
	},

	removeAttr: function( elem, value ) {
		var name, propName,
			i = 0,
			attrNames = value && value.match( rnotwhite );

		if ( attrNames && elem.nodeType === 1 ) {
			while ( ( name = attrNames[ i++ ] ) ) {
				propName = jQuery.propFix[ name ] || name;

				// Boolean attributes get special treatment (#10870)
				if ( jQuery.expr.match.bool.test( name ) ) {

					// Set corresponding property to false
					elem[ propName ] = false;
				}

				elem.removeAttribute( name );
			}
		}
	}
} );

// Hooks for boolean attributes
boolHook = {
	set: function( elem, value, name ) {
		if ( value === false ) {

			// Remove boolean attributes when set to false
			jQuery.removeAttr( elem, name );
		} else {
			elem.setAttribute( name, name );
		}
		return name;
	}
};
jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
	var getter = attrHandle[ name ] || jQuery.find.attr;

	attrHandle[ name ] = function( elem, name, isXML ) {
		var ret, handle;
		if ( !isXML ) {

			// Avoid an infinite loop by temporarily removing this function from the getter
			handle = attrHandle[ name ];
			attrHandle[ name ] = ret;
			ret = getter( elem, name, isXML ) != null ?
				name.toLowerCase() :
				null;
			attrHandle[ name ] = handle;
		}
		return ret;
	};
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(37),
	__webpack_require__(96)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( document, support ) {

( function() {
	var input = document.createElement( "input" ),
		select = document.createElement( "select" ),
		opt = select.appendChild( document.createElement( "option" ) );

	input.type = "checkbox";

	// Support: iOS<=5.1, Android<=4.2+
	// Default value for a checkbox should be "on"
	support.checkOn = input.value !== "";

	// Support: IE<=11+
	// Must access selectedIndex to make default options select
	support.optSelected = opt.selected;

	// Support: Android<=2.3
	// Options inside disabled selects are incorrectly marked as disabled
	select.disabled = true;
	support.optDisabled = !opt.disabled;

	// Support: IE<=11+
	// An input loses its value after becoming a radio
	input = document.createElement( "input" );
	input.value = "t";
	input.type = "radio";
	support.radioValue = input.value === "t";
} )();

return support;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(83),
	__webpack_require__(202),
	__webpack_require__(42)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, access, support ) {

var rfocusable = /^(?:input|select|textarea|button)$/i,
	rclickable = /^(?:a|area)$/i;

jQuery.fn.extend( {
	prop: function( name, value ) {
		return access( this, jQuery.prop, name, value, arguments.length > 1 );
	},

	removeProp: function( name ) {
		return this.each( function() {
			delete this[ jQuery.propFix[ name ] || name ];
		} );
	}
} );

jQuery.extend( {
	prop: function( elem, name, value ) {
		var ret, hooks,
			nType = elem.nodeType;

		// Don't get/set properties on text, comment and attribute nodes
		if ( nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {

			// Fix name and attach hooks
			name = jQuery.propFix[ name ] || name;
			hooks = jQuery.propHooks[ name ];
		}

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks &&
				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
				return ret;
			}

			return ( elem[ name ] = value );
		}

		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
			return ret;
		}

		return elem[ name ];
	},

	propHooks: {
		tabIndex: {
			get: function( elem ) {

				// elem.tabIndex doesn't always return the
				// correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				// Use proper attribute retrieval(#12072)
				var tabindex = jQuery.find.attr( elem, "tabindex" );

				return tabindex ?
					parseInt( tabindex, 10 ) :
					rfocusable.test( elem.nodeName ) ||
						rclickable.test( elem.nodeName ) && elem.href ?
							0 :
							-1;
			}
		}
	},

	propFix: {
		"for": "htmlFor",
		"class": "className"
	}
} );

// Support: IE <=11 only
// Accessing the selectedIndex property
// forces the browser to respect setting selected
// on the option
// The getter ensures a default option is selected
// when in an optgroup
if ( !support.optSelected ) {
	jQuery.propHooks.selected = {
		get: function( elem ) {
			var parent = elem.parentNode;
			if ( parent && parent.parentNode ) {
				parent.parentNode.selectedIndex;
			}
			return null;
		},
		set: function( elem ) {
			var parent = elem.parentNode;
			if ( parent ) {
				parent.selectedIndex;

				if ( parent.parentNode ) {
					parent.parentNode.selectedIndex;
				}
			}
		}
	};
}

jQuery.each( [
	"tabIndex",
	"readOnly",
	"maxLength",
	"cellSpacing",
	"cellPadding",
	"rowSpan",
	"colSpan",
	"useMap",
	"frameBorder",
	"contentEditable"
], function() {
	jQuery.propFix[ this.toLowerCase() ] = this;
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(82),
	__webpack_require__(55),
	__webpack_require__(52)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, rnotwhite, dataPriv ) {

var rclass = /[\t\r\n\f]/g;

function getClass( elem ) {
	return elem.getAttribute && elem.getAttribute( "class" ) || "";
}

jQuery.fn.extend( {
	addClass: function( value ) {
		var classes, elem, cur, curValue, clazz, j, finalValue,
			i = 0;

		if ( jQuery.isFunction( value ) ) {
			return this.each( function( j ) {
				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
			} );
		}

		if ( typeof value === "string" && value ) {
			classes = value.match( rnotwhite ) || [];

			while ( ( elem = this[ i++ ] ) ) {
				curValue = getClass( elem );
				cur = elem.nodeType === 1 &&
					( " " + curValue + " " ).replace( rclass, " " );

				if ( cur ) {
					j = 0;
					while ( ( clazz = classes[ j++ ] ) ) {
						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
							cur += clazz + " ";
						}
					}

					// Only assign if different to avoid unneeded rendering.
					finalValue = jQuery.trim( cur );
					if ( curValue !== finalValue ) {
						elem.setAttribute( "class", finalValue );
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		var classes, elem, cur, curValue, clazz, j, finalValue,
			i = 0;

		if ( jQuery.isFunction( value ) ) {
			return this.each( function( j ) {
				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
			} );
		}

		if ( !arguments.length ) {
			return this.attr( "class", "" );
		}

		if ( typeof value === "string" && value ) {
			classes = value.match( rnotwhite ) || [];

			while ( ( elem = this[ i++ ] ) ) {
				curValue = getClass( elem );

				// This expression is here for better compressibility (see addClass)
				cur = elem.nodeType === 1 &&
					( " " + curValue + " " ).replace( rclass, " " );

				if ( cur ) {
					j = 0;
					while ( ( clazz = classes[ j++ ] ) ) {

						// Remove *all* instances
						while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
							cur = cur.replace( " " + clazz + " ", " " );
						}
					}

					// Only assign if different to avoid unneeded rendering.
					finalValue = jQuery.trim( cur );
					if ( curValue !== finalValue ) {
						elem.setAttribute( "class", finalValue );
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value;

		if ( typeof stateVal === "boolean" && type === "string" ) {
			return stateVal ? this.addClass( value ) : this.removeClass( value );
		}

		if ( jQuery.isFunction( value ) ) {
			return this.each( function( i ) {
				jQuery( this ).toggleClass(
					value.call( this, i, getClass( this ), stateVal ),
					stateVal
				);
			} );
		}

		return this.each( function() {
			var className, i, self, classNames;

			if ( type === "string" ) {

				// Toggle individual class names
				i = 0;
				self = jQuery( this );
				classNames = value.match( rnotwhite ) || [];

				while ( ( className = classNames[ i++ ] ) ) {

					// Check each className given, space separated list
					if ( self.hasClass( className ) ) {
						self.removeClass( className );
					} else {
						self.addClass( className );
					}
				}

			// Toggle whole class name
			} else if ( value === undefined || type === "boolean" ) {
				className = getClass( this );
				if ( className ) {

					// Store className if set
					dataPriv.set( this, "__className__", className );
				}

				// If the element has a class name or if we're passed `false`,
				// then remove the whole classname (if there was one, the above saved it).
				// Otherwise bring back whatever was previously saved (if anything),
				// falling back to the empty string if nothing was stored.
				if ( this.setAttribute ) {
					this.setAttribute( "class",
						className || value === false ?
						"" :
						dataPriv.get( this, "__className__" ) || ""
					);
				}
			}
		} );
	},

	hasClass: function( selector ) {
		var className, elem,
			i = 0;

		className = " " + selector + " ";
		while ( ( elem = this[ i++ ] ) ) {
			if ( elem.nodeType === 1 &&
				( " " + getClass( elem ) + " " ).replace( rclass, " " )
					.indexOf( className ) > -1
			) {
				return true;
			}
		}

		return false;
	}
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(202),
	__webpack_require__(52)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, support ) {

var rreturn = /\r/g,
	rspaces = /[\x20\t\r\n\f]+/g;

jQuery.fn.extend( {
	val: function( value ) {
		var hooks, ret, isFunction,
			elem = this[ 0 ];

		if ( !arguments.length ) {
			if ( elem ) {
				hooks = jQuery.valHooks[ elem.type ] ||
					jQuery.valHooks[ elem.nodeName.toLowerCase() ];

				if ( hooks &&
					"get" in hooks &&
					( ret = hooks.get( elem, "value" ) ) !== undefined
				) {
					return ret;
				}

				ret = elem.value;

				return typeof ret === "string" ?

					// Handle most common string cases
					ret.replace( rreturn, "" ) :

					// Handle cases where value is null/undef or number
					ret == null ? "" : ret;
			}

			return;
		}

		isFunction = jQuery.isFunction( value );

		return this.each( function( i ) {
			var val;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call( this, i, jQuery( this ).val() );
			} else {
				val = value;
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";

			} else if ( typeof val === "number" ) {
				val += "";

			} else if ( jQuery.isArray( val ) ) {
				val = jQuery.map( val, function( value ) {
					return value == null ? "" : value + "";
				} );
			}

			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		} );
	}
} );

jQuery.extend( {
	valHooks: {
		option: {
			get: function( elem ) {

				var val = jQuery.find.attr( elem, "value" );
				return val != null ?
					val :

					// Support: IE10-11+
					// option.text throws exceptions (#14686, #14858)
					// Strip and collapse whitespace
					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
					jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
			}
		},
		select: {
			get: function( elem ) {
				var value, option,
					options = elem.options,
					index = elem.selectedIndex,
					one = elem.type === "select-one" || index < 0,
					values = one ? null : [],
					max = one ? index + 1 : options.length,
					i = index < 0 ?
						max :
						one ? index : 0;

				// Loop through all the selected options
				for ( ; i < max; i++ ) {
					option = options[ i ];

					// IE8-9 doesn't update selected after form reset (#2551)
					if ( ( option.selected || i === index ) &&

							// Don't return options that are disabled or in a disabled optgroup
							( support.optDisabled ?
								!option.disabled : option.getAttribute( "disabled" ) === null ) &&
							( !option.parentNode.disabled ||
								!jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {

						// Get the specific value for the option
						value = jQuery( option ).val();

						// We don't need an array for one selects
						if ( one ) {
							return value;
						}

						// Multi-Selects return an array
						values.push( value );
					}
				}

				return values;
			},

			set: function( elem, value ) {
				var optionSet, option,
					options = elem.options,
					values = jQuery.makeArray( value ),
					i = options.length;

				while ( i-- ) {
					option = options[ i ];
					if ( option.selected =
						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
					) {
						optionSet = true;
					}
				}

				// Force browsers to behave consistently when non-matching value is set
				if ( !optionSet ) {
					elem.selectedIndex = -1;
				}
				return values;
			}
		}
	}
} );

// Radios and checkboxes getter/setter
jQuery.each( [ "radio", "checkbox" ], function() {
	jQuery.valHooks[ this ] = {
		set: function( elem, value ) {
			if ( jQuery.isArray( value ) ) {
				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
			}
		}
	};
	if ( !support.checkOn ) {
		jQuery.valHooks[ this ].get = function( elem ) {
			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
		};
	}
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),

	__webpack_require__(98),
	__webpack_require__(203)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup error contextmenu" ).split( " " ),
	function( i, name ) {

	// Handle event binding
	jQuery.fn[ name ] = function( data, fn ) {
		return arguments.length > 0 ?
			this.on( name, null, data, fn ) :
			this.trigger( name );
	};
} );

jQuery.fn.extend( {
	hover: function( fnOver, fnOut ) {
		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
	}
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(55),
	__webpack_require__(195),
	__webpack_require__(273),

	__webpack_require__(98)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document, dataPriv, acceptData, hasOwn ) {

var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;

jQuery.extend( jQuery.event, {

	trigger: function( event, data, elem, onlyHandlers ) {

		var i, cur, tmp, bubbleType, ontype, handle, special,
			eventPath = [ elem || document ],
			type = hasOwn.call( event, "type" ) ? event.type : event,
			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];

		cur = tmp = elem = elem || document;

		// Don't do events on text and comment nodes
		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
			return;
		}

		// focus/blur morphs to focusin/out; ensure we're not firing them right now
		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
			return;
		}

		if ( type.indexOf( "." ) > -1 ) {

			// Namespaced trigger; create a regexp to match event type in handle()
			namespaces = type.split( "." );
			type = namespaces.shift();
			namespaces.sort();
		}
		ontype = type.indexOf( ":" ) < 0 && "on" + type;

		// Caller can pass in a jQuery.Event object, Object, or just an event type string
		event = event[ jQuery.expando ] ?
			event :
			new jQuery.Event( type, typeof event === "object" && event );

		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
		event.isTrigger = onlyHandlers ? 2 : 3;
		event.namespace = namespaces.join( "." );
		event.rnamespace = event.namespace ?
			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
			null;

		// Clean up the event in case it is being reused
		event.result = undefined;
		if ( !event.target ) {
			event.target = elem;
		}

		// Clone any incoming data and prepend the event, creating the handler arg list
		data = data == null ?
			[ event ] :
			jQuery.makeArray( data, [ event ] );

		// Allow special events to draw outside the lines
		special = jQuery.event.special[ type ] || {};
		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
			return;
		}

		// Determine event propagation path in advance, per W3C events spec (#9951)
		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

			bubbleType = special.delegateType || type;
			if ( !rfocusMorph.test( bubbleType + type ) ) {
				cur = cur.parentNode;
			}
			for ( ; cur; cur = cur.parentNode ) {
				eventPath.push( cur );
				tmp = cur;
			}

			// Only add window if we got to document (e.g., not plain obj or detached DOM)
			if ( tmp === ( elem.ownerDocument || document ) ) {
				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
			}
		}

		// Fire handlers on the event path
		i = 0;
		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {

			event.type = i > 1 ?
				bubbleType :
				special.bindType || type;

			// jQuery handler
			handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
				dataPriv.get( cur, "handle" );
			if ( handle ) {
				handle.apply( cur, data );
			}

			// Native handler
			handle = ontype && cur[ ontype ];
			if ( handle && handle.apply && acceptData( cur ) ) {
				event.result = handle.apply( cur, data );
				if ( event.result === false ) {
					event.preventDefault();
				}
			}
		}
		event.type = type;

		// If nobody prevented the default action, do it now
		if ( !onlyHandlers && !event.isDefaultPrevented() ) {

			if ( ( !special._default ||
				special._default.apply( eventPath.pop(), data ) === false ) &&
				acceptData( elem ) ) {

				// Call a native DOM method on the target with the same name name as the event.
				// Don't do default actions on window, that's where global variables be (#6170)
				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {

					// Don't re-trigger an onFOO event when we call its FOO() method
					tmp = elem[ ontype ];

					if ( tmp ) {
						elem[ ontype ] = null;
					}

					// Prevent re-triggering of the same event, since we already bubbled it above
					jQuery.event.triggered = type;
					elem[ type ]();
					jQuery.event.triggered = undefined;

					if ( tmp ) {
						elem[ ontype ] = tmp;
					}
				}
			}
		}

		return event.result;
	},

	// Piggyback on a donor event to simulate a different one
	// Used only for `focus(in | out)` events
	simulate: function( type, elem, event ) {
		var e = jQuery.extend(
			new jQuery.Event(),
			event,
			{
				type: type,
				isSimulated: true
			}
		);

		jQuery.event.trigger( e, null, elem );
	}

} );

jQuery.fn.extend( {

	trigger: function( type, data ) {
		return this.each( function() {
			jQuery.event.trigger( type, data, this );
		} );
	},
	triggerHandler: function( type, data ) {
		var elem = this[ 0 ];
		if ( elem ) {
			return jQuery.event.trigger( type, data, elem, true );
		}
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(55),
	__webpack_require__(584),

	__webpack_require__(98),
	__webpack_require__(203)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, dataPriv, support ) {

// Support: Firefox
// Firefox doesn't have focus(in | out) events
// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
//
// Support: Chrome, Safari
// focus(in | out) events fire after focus & blur events,
// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857
if ( !support.focusin ) {
	jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {

		// Attach a single capturing handler on the document while someone wants focusin/focusout
		var handler = function( event ) {
			jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
		};

		jQuery.event.special[ fix ] = {
			setup: function() {
				var doc = this.ownerDocument || this,
					attaches = dataPriv.access( doc, fix );

				if ( !attaches ) {
					doc.addEventListener( orig, handler, true );
				}
				dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
			},
			teardown: function() {
				var doc = this.ownerDocument || this,
					attaches = dataPriv.access( doc, fix ) - 1;

				if ( !attaches ) {
					doc.removeEventListener( orig, handler, true );
					dataPriv.remove( doc, fix );

				} else {
					dataPriv.access( doc, fix, attaches );
				}
			}
		};
	} );
}

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(96)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( support ) {

support.focusin = "onfocusin" in window;

return support;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(99)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

jQuery._evalUrl = function( url ) {
	return jQuery.ajax( {
		url: url,

		// Make this explicit, since user can override this through ajaxSetup (#11264)
		type: "GET",
		dataType: "script",
		async: false,
		global: false,
		"throws": true
	} );
};

return jQuery._evalUrl;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(82),
	__webpack_require__(586),
	__webpack_require__(298),
	__webpack_require__(299),

	__webpack_require__(52),
	__webpack_require__(587),
	__webpack_require__(588),
	__webpack_require__(203),
	__webpack_require__(123)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document, rnotwhite, location, nonce, rquery ) {

var
	rhash = /#.*$/,
	rts = /([?&])_=[^&]*/,
	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,

	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
	prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
	transports = {},

	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
	allTypes = "*/".concat( "*" ),

	// Anchor tag for parsing the document origin
	originAnchor = document.createElement( "a" );
	originAnchor.href = location.href;

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

	// dataTypeExpression is optional and defaults to "*"
	return function( dataTypeExpression, func ) {

		if ( typeof dataTypeExpression !== "string" ) {
			func = dataTypeExpression;
			dataTypeExpression = "*";
		}

		var dataType,
			i = 0,
			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];

		if ( jQuery.isFunction( func ) ) {

			// For each dataType in the dataTypeExpression
			while ( ( dataType = dataTypes[ i++ ] ) ) {

				// Prepend if requested
				if ( dataType[ 0 ] === "+" ) {
					dataType = dataType.slice( 1 ) || "*";
					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );

				// Otherwise append
				} else {
					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
				}
			}
		}
	};
}

// Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {

	var inspected = {},
		seekingTransport = ( structure === transports );

	function inspect( dataType ) {
		var selected;
		inspected[ dataType ] = true;
		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
			if ( typeof dataTypeOrTransport === "string" &&
				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {

				options.dataTypes.unshift( dataTypeOrTransport );
				inspect( dataTypeOrTransport );
				return false;
			} else if ( seekingTransport ) {
				return !( selected = dataTypeOrTransport );
			}
		} );
		return selected;
	}

	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
	var key, deep,
		flatOptions = jQuery.ajaxSettings.flatOptions || {};

	for ( key in src ) {
		if ( src[ key ] !== undefined ) {
			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
		}
	}
	if ( deep ) {
		jQuery.extend( true, target, deep );
	}

	return target;
}

/* Handles responses to an ajax request:
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

	var ct, type, finalDataType, firstDataType,
		contents = s.contents,
		dataTypes = s.dataTypes;

	// Remove auto dataType and get content-type in the process
	while ( dataTypes[ 0 ] === "*" ) {
		dataTypes.shift();
		if ( ct === undefined ) {
			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
		}
	}

	// Check if we're dealing with a known content-type
	if ( ct ) {
		for ( type in contents ) {
			if ( contents[ type ] && contents[ type ].test( ct ) ) {
				dataTypes.unshift( type );
				break;
			}
		}
	}

	// Check to see if we have a response for the expected dataType
	if ( dataTypes[ 0 ] in responses ) {
		finalDataType = dataTypes[ 0 ];
	} else {

		// Try convertible dataTypes
		for ( type in responses ) {
			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
				finalDataType = type;
				break;
			}
			if ( !firstDataType ) {
				firstDataType = type;
			}
		}

		// Or just use first one
		finalDataType = finalDataType || firstDataType;
	}

	// If we found a dataType
	// We add the dataType to the list if needed
	// and return the corresponding response
	if ( finalDataType ) {
		if ( finalDataType !== dataTypes[ 0 ] ) {
			dataTypes.unshift( finalDataType );
		}
		return responses[ finalDataType ];
	}
}

/* Chain conversions given the request and the original response
 * Also sets the responseXXX fields on the jqXHR instance
 */
function ajaxConvert( s, response, jqXHR, isSuccess ) {
	var conv2, current, conv, tmp, prev,
		converters = {},

		// Work with a copy of dataTypes in case we need to modify it for conversion
		dataTypes = s.dataTypes.slice();

	// Create converters map with lowercased keys
	if ( dataTypes[ 1 ] ) {
		for ( conv in s.converters ) {
			converters[ conv.toLowerCase() ] = s.converters[ conv ];
		}
	}

	current = dataTypes.shift();

	// Convert to each sequential dataType
	while ( current ) {

		if ( s.responseFields[ current ] ) {
			jqXHR[ s.responseFields[ current ] ] = response;
		}

		// Apply the dataFilter if provided
		if ( !prev && isSuccess && s.dataFilter ) {
			response = s.dataFilter( response, s.dataType );
		}

		prev = current;
		current = dataTypes.shift();

		if ( current ) {

		// There's only work to do if current dataType is non-auto
			if ( current === "*" ) {

				current = prev;

			// Convert response if prev dataType is non-auto and differs from current
			} else if ( prev !== "*" && prev !== current ) {

				// Seek a direct converter
				conv = converters[ prev + " " + current ] || converters[ "* " + current ];

				// If none found, seek a pair
				if ( !conv ) {
					for ( conv2 in converters ) {

						// If conv2 outputs current
						tmp = conv2.split( " " );
						if ( tmp[ 1 ] === current ) {

							// If prev can be converted to accepted input
							conv = converters[ prev + " " + tmp[ 0 ] ] ||
								converters[ "* " + tmp[ 0 ] ];
							if ( conv ) {

								// Condense equivalence converters
								if ( conv === true ) {
									conv = converters[ conv2 ];

								// Otherwise, insert the intermediate dataType
								} else if ( converters[ conv2 ] !== true ) {
									current = tmp[ 0 ];
									dataTypes.unshift( tmp[ 1 ] );
								}
								break;
							}
						}
					}
				}

				// Apply converter (if not an equivalence)
				if ( conv !== true ) {

					// Unless errors are allowed to bubble, catch and return them
					if ( conv && s.throws ) {
						response = conv( response );
					} else {
						try {
							response = conv( response );
						} catch ( e ) {
							return {
								state: "parsererror",
								error: conv ? e : "No conversion from " + prev + " to " + current
							};
						}
					}
				}
			}
		}
	}

	return { state: "success", data: response };
}

jQuery.extend( {

	// Counter for holding the number of active queries
	active: 0,

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {},

	ajaxSettings: {
		url: location.href,
		type: "GET",
		isLocal: rlocalProtocol.test( location.protocol ),
		global: true,
		processData: true,
		async: true,
		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
		/*
		timeout: 0,
		data: null,
		dataType: null,
		username: null,
		password: null,
		cache: null,
		throws: false,
		traditional: false,
		headers: {},
		*/

		accepts: {
			"*": allTypes,
			text: "text/plain",
			html: "text/html",
			xml: "application/xml, text/xml",
			json: "application/json, text/javascript"
		},

		contents: {
			xml: /\bxml\b/,
			html: /\bhtml/,
			json: /\bjson\b/
		},

		responseFields: {
			xml: "responseXML",
			text: "responseText",
			json: "responseJSON"
		},

		// Data converters
		// Keys separate source (or catchall "*") and destination types with a single space
		converters: {

			// Convert anything to text
			"* text": String,

			// Text to html (true = no transformation)
			"text html": true,

			// Evaluate text as a json expression
			"text json": jQuery.parseJSON,

			// Parse text as xml
			"text xml": jQuery.parseXML
		},

		// For options that shouldn't be deep extended:
		// you can add your own custom options here if
		// and when you create one that shouldn't be
		// deep extended (see ajaxExtend)
		flatOptions: {
			url: true,
			context: true
		}
	},

	// Creates a full fledged settings object into target
	// with both ajaxSettings and settings fields.
	// If target is omitted, writes into ajaxSettings.
	ajaxSetup: function( target, settings ) {
		return settings ?

			// Building a settings object
			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :

			// Extending ajaxSettings
			ajaxExtend( jQuery.ajaxSettings, target );
	},

	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
	ajaxTransport: addToPrefiltersOrTransports( transports ),

	// Main method
	ajax: function( url, options ) {

		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}

		// Force options to be an object
		options = options || {};

		var transport,

			// URL without anti-cache param
			cacheURL,

			// Response headers
			responseHeadersString,
			responseHeaders,

			// timeout handle
			timeoutTimer,

			// Url cleanup var
			urlAnchor,

			// To know if global events are to be dispatched
			fireGlobals,

			// Loop variable
			i,

			// Create the final options object
			s = jQuery.ajaxSetup( {}, options ),

			// Callbacks context
			callbackContext = s.context || s,

			// Context for global events is callbackContext if it is a DOM node or jQuery collection
			globalEventContext = s.context &&
				( callbackContext.nodeType || callbackContext.jquery ) ?
					jQuery( callbackContext ) :
					jQuery.event,

			// Deferreds
			deferred = jQuery.Deferred(),
			completeDeferred = jQuery.Callbacks( "once memory" ),

			// Status-dependent callbacks
			statusCode = s.statusCode || {},

			// Headers (they are sent all at once)
			requestHeaders = {},
			requestHeadersNames = {},

			// The jqXHR state
			state = 0,

			// Default abort message
			strAbort = "canceled",

			// Fake xhr
			jqXHR = {
				readyState: 0,

				// Builds headers hashtable if needed
				getResponseHeader: function( key ) {
					var match;
					if ( state === 2 ) {
						if ( !responseHeaders ) {
							responseHeaders = {};
							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
								responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
							}
						}
						match = responseHeaders[ key.toLowerCase() ];
					}
					return match == null ? null : match;
				},

				// Raw string
				getAllResponseHeaders: function() {
					return state === 2 ? responseHeadersString : null;
				},

				// Caches the header
				setRequestHeader: function( name, value ) {
					var lname = name.toLowerCase();
					if ( !state ) {
						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
						requestHeaders[ name ] = value;
					}
					return this;
				},

				// Overrides response content-type header
				overrideMimeType: function( type ) {
					if ( !state ) {
						s.mimeType = type;
					}
					return this;
				},

				// Status-dependent callbacks
				statusCode: function( map ) {
					var code;
					if ( map ) {
						if ( state < 2 ) {
							for ( code in map ) {

								// Lazy-add the new callback in a way that preserves old ones
								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
							}
						} else {

							// Execute the appropriate callbacks
							jqXHR.always( map[ jqXHR.status ] );
						}
					}
					return this;
				},

				// Cancel the request
				abort: function( statusText ) {
					var finalText = statusText || strAbort;
					if ( transport ) {
						transport.abort( finalText );
					}
					done( 0, finalText );
					return this;
				}
			};

		// Attach deferreds
		deferred.promise( jqXHR ).complete = completeDeferred.add;
		jqXHR.success = jqXHR.done;
		jqXHR.error = jqXHR.fail;

		// Remove hash character (#7531: and string promotion)
		// Add protocol if not provided (prefilters might expect it)
		// Handle falsy url in the settings object (#10093: consistency with old signature)
		// We also use the url parameter if available
		s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" )
			.replace( rprotocol, location.protocol + "//" );

		// Alias method option to type as per ticket #12004
		s.type = options.method || options.type || s.method || s.type;

		// Extract dataTypes list
		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];

		// A cross-domain request is in order when the origin doesn't match the current origin.
		if ( s.crossDomain == null ) {
			urlAnchor = document.createElement( "a" );

			// Support: IE8-11+
			// IE throws exception if url is malformed, e.g. http://example.com:80x/
			try {
				urlAnchor.href = s.url;

				// Support: IE8-11+
				// Anchor's host property isn't correctly set when s.url is relative
				urlAnchor.href = urlAnchor.href;
				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
					urlAnchor.protocol + "//" + urlAnchor.host;
			} catch ( e ) {

				// If there is an error parsing the URL, assume it is crossDomain,
				// it can be rejected by the transport if it is invalid
				s.crossDomain = true;
			}
		}

		// Convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Apply prefilters
		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

		// If request was aborted inside a prefilter, stop there
		if ( state === 2 ) {
			return jqXHR;
		}

		// We can fire global events as of now if asked to
		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
		fireGlobals = jQuery.event && s.global;

		// Watch for a new set of requests
		if ( fireGlobals && jQuery.active++ === 0 ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// Uppercase the type
		s.type = s.type.toUpperCase();

		// Determine if request has content
		s.hasContent = !rnoContent.test( s.type );

		// Save the URL in case we're toying with the If-Modified-Since
		// and/or If-None-Match header later on
		cacheURL = s.url;

		// More options handling for requests with no content
		if ( !s.hasContent ) {

			// If data is available, append data to url
			if ( s.data ) {
				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );

				// #9682: remove data so that it's not used in an eventual retry
				delete s.data;
			}

			// Add anti-cache in url if needed
			if ( s.cache === false ) {
				s.url = rts.test( cacheURL ) ?

					// If there is already a '_' parameter, set its value
					cacheURL.replace( rts, "$1_=" + nonce++ ) :

					// Otherwise add one to the end
					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
			}
		}

		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
		if ( s.ifModified ) {
			if ( jQuery.lastModified[ cacheURL ] ) {
				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
			}
			if ( jQuery.etag[ cacheURL ] ) {
				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
			}
		}

		// Set the correct header, if data is being sent
		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
			jqXHR.setRequestHeader( "Content-Type", s.contentType );
		}

		// Set the Accepts header for the server, depending on the dataType
		jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
				s.accepts[ s.dataTypes[ 0 ] ] +
					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
				s.accepts[ "*" ]
		);

		// Check for headers option
		for ( i in s.headers ) {
			jqXHR.setRequestHeader( i, s.headers[ i ] );
		}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend &&
			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {

			// Abort if not done already and return
			return jqXHR.abort();
		}

		// Aborting is no longer a cancellation
		strAbort = "abort";

		// Install callbacks on deferreds
		for ( i in { success: 1, error: 1, complete: 1 } ) {
			jqXHR[ i ]( s[ i ] );
		}

		// Get transport
		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

		// If no transport, we auto-abort
		if ( !transport ) {
			done( -1, "No Transport" );
		} else {
			jqXHR.readyState = 1;

			// Send global event
			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
			}

			// If request was aborted inside ajaxSend, stop there
			if ( state === 2 ) {
				return jqXHR;
			}

			// Timeout
			if ( s.async && s.timeout > 0 ) {
				timeoutTimer = window.setTimeout( function() {
					jqXHR.abort( "timeout" );
				}, s.timeout );
			}

			try {
				state = 1;
				transport.send( requestHeaders, done );
			} catch ( e ) {

				// Propagate exception as error if not done
				if ( state < 2 ) {
					done( -1, e );

				// Simply rethrow otherwise
				} else {
					throw e;
				}
			}
		}

		// Callback for when everything is done
		function done( status, nativeStatusText, responses, headers ) {
			var isSuccess, success, error, response, modified,
				statusText = nativeStatusText;

			// Called once
			if ( state === 2 ) {
				return;
			}

			// State is "done" now
			state = 2;

			// Clear timeout if it exists
			if ( timeoutTimer ) {
				window.clearTimeout( timeoutTimer );
			}

			// Dereference transport for early garbage collection
			// (no matter how long the jqXHR object will be used)
			transport = undefined;

			// Cache response headers
			responseHeadersString = headers || "";

			// Set readyState
			jqXHR.readyState = status > 0 ? 4 : 0;

			// Determine if successful
			isSuccess = status >= 200 && status < 300 || status === 304;

			// Get response data
			if ( responses ) {
				response = ajaxHandleResponses( s, jqXHR, responses );
			}

			// Convert no matter what (that way responseXXX fields are always set)
			response = ajaxConvert( s, response, jqXHR, isSuccess );

			// If successful, handle type chaining
			if ( isSuccess ) {

				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
				if ( s.ifModified ) {
					modified = jqXHR.getResponseHeader( "Last-Modified" );
					if ( modified ) {
						jQuery.lastModified[ cacheURL ] = modified;
					}
					modified = jqXHR.getResponseHeader( "etag" );
					if ( modified ) {
						jQuery.etag[ cacheURL ] = modified;
					}
				}

				// if no content
				if ( status === 204 || s.type === "HEAD" ) {
					statusText = "nocontent";

				// if not modified
				} else if ( status === 304 ) {
					statusText = "notmodified";

				// If we have data, let's convert it
				} else {
					statusText = response.state;
					success = response.data;
					error = response.error;
					isSuccess = !error;
				}
			} else {

				// Extract error from statusText and normalize for non-aborts
				error = statusText;
				if ( status || !statusText ) {
					statusText = "error";
					if ( status < 0 ) {
						status = 0;
					}
				}
			}

			// Set data for the fake xhr object
			jqXHR.status = status;
			jqXHR.statusText = ( nativeStatusText || statusText ) + "";

			// Success/Error
			if ( isSuccess ) {
				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
			} else {
				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
			}

			// Status-dependent callbacks
			jqXHR.statusCode( statusCode );
			statusCode = undefined;

			if ( fireGlobals ) {
				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
					[ jqXHR, s, isSuccess ? success : error ] );
			}

			// Complete
			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );

				// Handle the global AJAX counter
				if ( !( --jQuery.active ) ) {
					jQuery.event.trigger( "ajaxStop" );
				}
			}
		}

		return jqXHR;
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get( url, data, callback, "json" );
	},

	getScript: function( url, callback ) {
		return jQuery.get( url, undefined, callback, "script" );
	}
} );

jQuery.each( [ "get", "post" ], function( i, method ) {
	jQuery[ method ] = function( url, data, callback, type ) {

		// Shift arguments if data argument was omitted
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}

		// The url can be an options object (which then must have .url)
		return jQuery.ajax( jQuery.extend( {
			url: url,
			type: method,
			dataType: type,
			data: data,
			success: callback
		}, jQuery.isPlainObject( url ) && url ) );
	};
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return window.location;
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {
	return jQuery.now();
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
	return ( /\?/ );
}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Support: Android 2.3
// Workaround failure to string-cast null input
jQuery.parseJSON = function( data ) {
	return JSON.parse( data + "" );
};

return jQuery.parseJSON;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Cross-browser xml parsing
jQuery.parseXML = function( data ) {
	var xml;
	if ( !data || typeof data !== "string" ) {
		return null;
	}

	// Support: IE9
	try {
		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
	} catch ( e ) {
		xml = undefined;
	}

	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
		jQuery.error( "Invalid XML: " + data );
	}
	return xml;
};

return jQuery.parseXML;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(52),
	__webpack_require__(149), // clone
	__webpack_require__(97) // parent, contents
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

jQuery.fn.extend( {
	wrapAll: function( html ) {
		var wrap;

		if ( jQuery.isFunction( html ) ) {
			return this.each( function( i ) {
				jQuery( this ).wrapAll( html.call( this, i ) );
			} );
		}

		if ( this[ 0 ] ) {

			// The elements to wrap the target around
			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );

			if ( this[ 0 ].parentNode ) {
				wrap.insertBefore( this[ 0 ] );
			}

			wrap.map( function() {
				var elem = this;

				while ( elem.firstElementChild ) {
					elem = elem.firstElementChild;
				}

				return elem;
			} ).append( this );
		}

		return this;
	},

	wrapInner: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each( function( i ) {
				jQuery( this ).wrapInner( html.call( this, i ) );
			} );
		}

		return this.each( function() {
			var self = jQuery( this ),
				contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		} );
	},

	wrap: function( html ) {
		var isFunction = jQuery.isFunction( html );

		return this.each( function( i ) {
			jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
		} );
	},

	unwrap: function() {
		return this.parent().each( function() {
			if ( !jQuery.nodeName( this, "body" ) ) {
				jQuery( this ).replaceWith( this.childNodes );
			}
		} ).end();
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(42)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

jQuery.expr.filters.hidden = function( elem ) {
	return !jQuery.expr.filters.visible( elem );
};
jQuery.expr.filters.visible = function( elem ) {

	// Support: Opera <= 12.12
	// Opera reports offsetWidths and offsetHeights less than zero on some elements
	// Use OR instead of AND as the element is not visible if either is true
	// See tickets #10406 and #13132
	return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0;
};

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(284),
	__webpack_require__(52),
	__webpack_require__(97), // filter
	__webpack_require__(296)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, rcheckableType ) {

var r20 = /%20/g,
	rbracket = /\[\]$/,
	rCRLF = /\r?\n/g,
	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
	rsubmittable = /^(?:input|select|textarea|keygen)/i;

function buildParams( prefix, obj, traditional, add ) {
	var name;

	if ( jQuery.isArray( obj ) ) {

		// Serialize array item.
		jQuery.each( obj, function( i, v ) {
			if ( traditional || rbracket.test( prefix ) ) {

				// Treat each array item as a scalar.
				add( prefix, v );

			} else {

				// Item is non-scalar (array or object), encode its numeric index.
				buildParams(
					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
					v,
					traditional,
					add
				);
			}
		} );

	} else if ( !traditional && jQuery.type( obj ) === "object" ) {

		// Serialize object item.
		for ( name in obj ) {
			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
		}

	} else {

		// Serialize scalar item.
		add( prefix, obj );
	}
}

// Serialize an array of form elements or a set of
// key/values into a query string
jQuery.param = function( a, traditional ) {
	var prefix,
		s = [],
		add = function( key, value ) {

			// If value is a function, invoke it and return its value
			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
		};

	// Set traditional to true for jQuery <= 1.3.2 behavior.
	if ( traditional === undefined ) {
		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
	}

	// If an array was passed in, assume that it is an array of form elements.
	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {

		// Serialize the form elements
		jQuery.each( a, function() {
			add( this.name, this.value );
		} );

	} else {

		// If traditional, encode the "old" way (the way 1.3.2 or older
		// did it), otherwise encode params recursively.
		for ( prefix in a ) {
			buildParams( prefix, a[ prefix ], traditional, add );
		}
	}

	// Return the resulting serialization
	return s.join( "&" ).replace( r20, "+" );
};

jQuery.fn.extend( {
	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},
	serializeArray: function() {
		return this.map( function() {

			// Can add propHook for "elements" to filter or add form elements
			var elements = jQuery.prop( this, "elements" );
			return elements ? jQuery.makeArray( elements ) : this;
		} )
		.filter( function() {
			var type = this.type;

			// Use .is( ":disabled" ) so that fieldset[disabled] works
			return this.name && !jQuery( this ).is( ":disabled" ) &&
				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
				( this.checked || !rcheckableType.test( type ) );
		} )
		.map( function( i, elem ) {
			var val = jQuery( this ).val();

			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val ) {
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					} ) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		} ).get();
	}
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(96),
	__webpack_require__(99)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, support ) {

jQuery.ajaxSettings.xhr = function() {
	try {
		return new window.XMLHttpRequest();
	} catch ( e ) {}
};

var xhrSuccessStatus = {

		// File protocol always yields status code 0, assume 200
		0: 200,

		// Support: IE9
		// #1450: sometimes IE returns 1223 when it should be 204
		1223: 204
	},
	xhrSupported = jQuery.ajaxSettings.xhr();

support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
support.ajax = xhrSupported = !!xhrSupported;

jQuery.ajaxTransport( function( options ) {
	var callback, errorCallback;

	// Cross domain only allowed if supported through XMLHttpRequest
	if ( support.cors || xhrSupported && !options.crossDomain ) {
		return {
			send: function( headers, complete ) {
				var i,
					xhr = options.xhr();

				xhr.open(
					options.type,
					options.url,
					options.async,
					options.username,
					options.password
				);

				// Apply custom fields if provided
				if ( options.xhrFields ) {
					for ( i in options.xhrFields ) {
						xhr[ i ] = options.xhrFields[ i ];
					}
				}

				// Override mime type if needed
				if ( options.mimeType && xhr.overrideMimeType ) {
					xhr.overrideMimeType( options.mimeType );
				}

				// X-Requested-With header
				// For cross-domain requests, seeing as conditions for a preflight are
				// akin to a jigsaw puzzle, we simply never set it to be sure.
				// (it can always be set on a per-request basis or even using ajaxSetup)
				// For same-domain requests, won't change header if already provided.
				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
					headers[ "X-Requested-With" ] = "XMLHttpRequest";
				}

				// Set headers
				for ( i in headers ) {
					xhr.setRequestHeader( i, headers[ i ] );
				}

				// Callback
				callback = function( type ) {
					return function() {
						if ( callback ) {
							callback = errorCallback = xhr.onload =
								xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;

							if ( type === "abort" ) {
								xhr.abort();
							} else if ( type === "error" ) {

								// Support: IE9
								// On a manual native abort, IE9 throws
								// errors on any property access that is not readyState
								if ( typeof xhr.status !== "number" ) {
									complete( 0, "error" );
								} else {
									complete(

										// File: protocol always yields status 0; see #8605, #14207
										xhr.status,
										xhr.statusText
									);
								}
							} else {
								complete(
									xhrSuccessStatus[ xhr.status ] || xhr.status,
									xhr.statusText,

									// Support: IE9 only
									// IE9 has no XHR2 but throws on binary (trac-11426)
									// For XHR2 non-text, let the caller handle it (gh-2498)
									( xhr.responseType || "text" ) !== "text"  ||
									typeof xhr.responseText !== "string" ?
										{ binary: xhr.response } :
										{ text: xhr.responseText },
									xhr.getAllResponseHeaders()
								);
							}
						}
					};
				};

				// Listen to events
				xhr.onload = callback();
				errorCallback = xhr.onerror = callback( "error" );

				// Support: IE9
				// Use onreadystatechange to replace onabort
				// to handle uncaught aborts
				if ( xhr.onabort !== undefined ) {
					xhr.onabort = errorCallback;
				} else {
					xhr.onreadystatechange = function() {

						// Check readyState before timeout as it changes
						if ( xhr.readyState === 4 ) {

							// Allow onerror to be called first,
							// but that will not handle a native abort
							// Also, save errorCallback to a variable
							// as xhr.onerror cannot be accessed
							window.setTimeout( function() {
								if ( callback ) {
									errorCallback();
								}
							} );
						}
					};
				}

				// Create the abort callback
				callback = callback( "abort" );

				try {

					// Do send the request (this may raise an exception)
					xhr.send( options.hasContent && options.data || null );
				} catch ( e ) {

					// #14683: Only rethrow if this hasn't been notified as an error yet
					if ( callback ) {
						throw e;
					}
				}
			},

			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(99)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document ) {

// Install script dataType
jQuery.ajaxSetup( {
	accepts: {
		script: "text/javascript, application/javascript, " +
			"application/ecmascript, application/x-ecmascript"
	},
	contents: {
		script: /\b(?:java|ecma)script\b/
	},
	converters: {
		"text script": function( text ) {
			jQuery.globalEval( text );
			return text;
		}
	}
} );

// Handle cache's special case and crossDomain
jQuery.ajaxPrefilter( "script", function( s ) {
	if ( s.cache === undefined ) {
		s.cache = false;
	}
	if ( s.crossDomain ) {
		s.type = "GET";
	}
} );

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function( s ) {

	// This transport only deals with cross domain requests
	if ( s.crossDomain ) {
		var script, callback;
		return {
			send: function( _, complete ) {
				script = jQuery( "<script>" ).prop( {
					charset: s.scriptCharset,
					src: s.url
				} ).on(
					"load error",
					callback = function( evt ) {
						script.remove();
						callback = null;
						if ( evt ) {
							complete( evt.type === "error" ? 404 : 200, evt.type );
						}
					}
				);

				// Use native DOM manipulation to avoid our domManip AJAX trickery
				document.head.appendChild( script[ 0 ] );
			},
			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(298),
	__webpack_require__(299),
	__webpack_require__(99)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, nonce, rquery ) {

var oldCallbacks = [],
	rjsonp = /(=)\?(?=&|$)|\?\?/;

// Default jsonp settings
jQuery.ajaxSetup( {
	jsonp: "callback",
	jsonpCallback: function() {
		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
		this[ callback ] = true;
		return callback;
	}
} );

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var callbackName, overwritten, responseContainer,
		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
			"url" :
			typeof s.data === "string" &&
				( s.contentType || "" )
					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
				rjsonp.test( s.data ) && "data"
		);

	// Handle iff the expected data type is "jsonp" or we have a parameter to set
	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {

		// Get callback name, remembering preexisting value associated with it
		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
			s.jsonpCallback() :
			s.jsonpCallback;

		// Insert callback into url or form data
		if ( jsonProp ) {
			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
		} else if ( s.jsonp !== false ) {
			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
		}

		// Use data converter to retrieve json after script execution
		s.converters[ "script json" ] = function() {
			if ( !responseContainer ) {
				jQuery.error( callbackName + " was not called" );
			}
			return responseContainer[ 0 ];
		};

		// Force json dataType
		s.dataTypes[ 0 ] = "json";

		// Install callback
		overwritten = window[ callbackName ];
		window[ callbackName ] = function() {
			responseContainer = arguments;
		};

		// Clean-up function (fires after converters)
		jqXHR.always( function() {

			// If previous value didn't exist - remove it
			if ( overwritten === undefined ) {
				jQuery( window ).removeProp( callbackName );

			// Otherwise restore preexisting value
			} else {
				window[ callbackName ] = overwritten;
			}

			// Save back as free
			if ( s[ callbackName ] ) {

				// Make sure that re-using the options doesn't screw things around
				s.jsonpCallback = originalSettings.jsonpCallback;

				// Save the callback name for future use
				oldCallbacks.push( callbackName );
			}

			// Call if it was a function and we have a response
			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
				overwritten( responseContainer[ 0 ] );
			}

			responseContainer = overwritten = undefined;
		} );

		// Delegate to script
		return "script";
	}
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(596),
	__webpack_require__(99),
	__webpack_require__(97),
	__webpack_require__(149),
	__webpack_require__(42),

	// Optional event/alias dependency
	__webpack_require__(297)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Keep a copy of the old load method
var _load = jQuery.fn.load;

/**
 * Load a url into a page
 */
jQuery.fn.load = function( url, params, callback ) {
	if ( typeof url !== "string" && _load ) {
		return _load.apply( this, arguments );
	}

	var selector, type, response,
		self = this,
		off = url.indexOf( " " );

	if ( off > -1 ) {
		selector = jQuery.trim( url.slice( off ) );
		url = url.slice( 0, off );
	}

	// If it's a function
	if ( jQuery.isFunction( params ) ) {

		// We assume that it's the callback
		callback = params;
		params = undefined;

	// Otherwise, build a param string
	} else if ( params && typeof params === "object" ) {
		type = "POST";
	}

	// If we have elements to modify, make the request
	if ( self.length > 0 ) {
		jQuery.ajax( {
			url: url,

			// If "type" variable is undefined, then "GET" method will be used.
			// Make value of this field explicit since
			// user can override it through ajaxSetup method
			type: type || "GET",
			dataType: "html",
			data: params
		} ).done( function( responseText ) {

			// Save response for use in complete callback
			response = arguments;

			self.html( selector ?

				// If a selector was specified, locate the right elements in a dummy div
				// Exclude scripts to avoid IE 'Permission Denied' errors
				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :

				// Otherwise use the full result
				responseText );

		// If the request succeeds, this function gets "data", "status", "jqXHR"
		// but they are ignored because response was set above.
		// If it fails, this function gets "jqXHR", "status", "error"
		} ).always( callback && function( jqXHR, status ) {
			self.each( function() {
				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
			} );
		} );
	}

	return this;
};

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(37),
	__webpack_require__(275),
	__webpack_require__(290)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, document, rsingleTag, buildFragment ) {

// Argument "data" should be string of html
// context (optional): If specified, the fragment will be created in this context,
// defaults to document
// keepScripts (optional): If true, will include scripts passed in the html string
jQuery.parseHTML = function( data, context, keepScripts ) {
	if ( !data || typeof data !== "string" ) {
		return null;
	}
	if ( typeof context === "boolean" ) {
		keepScripts = context;
		context = false;
	}
	context = context || document;

	var parsed = rsingleTag.exec( data ),
		scripts = !keepScripts && [];

	// Single tag
	if ( parsed ) {
		return [ context.createElement( parsed[ 1 ] ) ];
	}

	parsed = buildFragment( [ data ], context, scripts );

	if ( scripts && scripts.length ) {
		jQuery( scripts ).remove();
	}

	return jQuery.merge( [], parsed.childNodes );
};

return jQuery.parseHTML;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(98)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Attach a bunch of functions for handling common AJAX events
jQuery.each( [
	"ajaxStart",
	"ajaxStop",
	"ajaxComplete",
	"ajaxError",
	"ajaxSuccess",
	"ajaxSend"
], function( i, type ) {
	jQuery.fn[ type ] = function( fn ) {
		return this.on( type, fn );
	};
} );

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(42),
	__webpack_require__(197)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

jQuery.expr.filters.animated = function( elem ) {
	return jQuery.grep( jQuery.timers, function( fn ) {
		return elem === fn.elem;
	} ).length;
};

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(83),
	__webpack_require__(37),
	__webpack_require__(294),
	__webpack_require__(200),
	__webpack_require__(293),
	__webpack_require__(295),
	__webpack_require__(201),

	__webpack_require__(52),
	__webpack_require__(124),
	__webpack_require__(42) // contains
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, access, document, documentElement, rnumnonpx, curCSS, addGetHookIf, support ) {

/**
 * Gets a window from an element
 */
function getWindow( elem ) {
	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
}

jQuery.offset = {
	setOffset: function( elem, options, i ) {
		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
			position = jQuery.css( elem, "position" ),
			curElem = jQuery( elem ),
			props = {};

		// Set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		curOffset = curElem.offset();
		curCSSTop = jQuery.css( elem, "top" );
		curCSSLeft = jQuery.css( elem, "left" );
		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;

		// Need to be able to calculate position if either
		// top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;

		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( jQuery.isFunction( options ) ) {

			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );

		} else {
			curElem.css( props );
		}
	}
};

jQuery.fn.extend( {
	offset: function( options ) {
		if ( arguments.length ) {
			return options === undefined ?
				this :
				this.each( function( i ) {
					jQuery.offset.setOffset( this, options, i );
				} );
		}

		var docElem, win,
			elem = this[ 0 ],
			box = { top: 0, left: 0 },
			doc = elem && elem.ownerDocument;

		if ( !doc ) {
			return;
		}

		docElem = doc.documentElement;

		// Make sure it's not a disconnected DOM node
		if ( !jQuery.contains( docElem, elem ) ) {
			return box;
		}

		box = elem.getBoundingClientRect();
		win = getWindow( doc );
		return {
			top: box.top + win.pageYOffset - docElem.clientTop,
			left: box.left + win.pageXOffset - docElem.clientLeft
		};
	},

	position: function() {
		if ( !this[ 0 ] ) {
			return;
		}

		var offsetParent, offset,
			elem = this[ 0 ],
			parentOffset = { top: 0, left: 0 };

		// Fixed elements are offset from window (parentOffset = {top:0, left: 0},
		// because it is its only offset parent
		if ( jQuery.css( elem, "position" ) === "fixed" ) {

			// Assume getBoundingClientRect is there when computed position is fixed
			offset = elem.getBoundingClientRect();

		} else {

			// Get *real* offsetParent
			offsetParent = this.offsetParent();

			// Get correct offsets
			offset = this.offset();
			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
				parentOffset = offsetParent.offset();
			}

			// Add offsetParent borders
			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
		}

		// Subtract parent offsets and element margins
		return {
			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
		};
	},

	// This method will return documentElement in the following cases:
	// 1) For the element inside the iframe without offsetParent, this method will return
	//    documentElement of the parent window
	// 2) For the hidden or detached element
	// 3) For body or html element, i.e. in case of the html node - it will return itself
	//
	// but those exceptions were never presented as a real life use-cases
	// and might be considered as more preferable results.
	//
	// This logic, however, is not guaranteed and can change at any point in the future
	offsetParent: function() {
		return this.map( function() {
			var offsetParent = this.offsetParent;

			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
				offsetParent = offsetParent.offsetParent;
			}

			return offsetParent || documentElement;
		} );
	}
} );

// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
	var top = "pageYOffset" === prop;

	jQuery.fn[ method ] = function( val ) {
		return access( this, function( elem, method, val ) {
			var win = getWindow( elem );

			if ( val === undefined ) {
				return win ? win[ prop ] : elem[ method ];
			}

			if ( win ) {
				win.scrollTo(
					!top ? val : win.pageXOffset,
					top ? val : win.pageYOffset
				);

			} else {
				elem[ method ] = val;
			}
		}, method, val, arguments.length );
	};
} );

// Support: Safari<7-8+, Chrome<37-44+
// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
// getComputedStyle returns percent when specified for top/left/bottom/right;
// rather than make the css module depend on the offset module, just check for it here
jQuery.each( [ "top", "left" ], function( i, prop ) {
	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
		function( elem, computed ) {
			if ( computed ) {
				computed = curCSS( elem, prop );

				// If curCSS returns percentage, fallback to offset
				return rnumnonpx.test( computed ) ?
					jQuery( elem ).position()[ prop ] + "px" :
					computed;
			}
		}
	);
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10),
	__webpack_require__(83),
	__webpack_require__(124)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery, access ) {

// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
		function( defaultExtra, funcName ) {

		// Margin is only for outerHeight, outerWidth
		jQuery.fn[ funcName ] = function( margin, value ) {
			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );

			return access( this, function( elem, type, value ) {
				var doc;

				if ( jQuery.isWindow( elem ) ) {

					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
					// isn't a whole lot we can do. See pull request at this URL for discussion:
					// https://github.com/jquery/jquery/pull/764
					return elem.document.documentElement[ "client" + name ];
				}

				// Get document width or height
				if ( elem.nodeType === 9 ) {
					doc = elem.documentElement;

					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
					// whichever is greatest
					return Math.max(
						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
						elem.body[ "offset" + name ], doc[ "offset" + name ],
						doc[ "client" + name ]
					);
				}

				return value === undefined ?

					// Get width or height on the element, requesting but not forcing parseFloat
					jQuery.css( elem, type, extra ) :

					// Set width or height on the element
					jQuery.style( elem, type, value, extra );
			}, type, chainable ? margin : undefined, chainable, null );
		};
	} );
} );

return jQuery;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

jQuery.fn.extend( {

	bind: function( types, data, fn ) {
		return this.on( types, null, data, fn );
	},
	unbind: function( types, fn ) {
		return this.off( types, null, fn );
	},

	delegate: function( selector, types, data, fn ) {
		return this.on( types, selector, data, fn );
	},
	undelegate: function( selector, types, fn ) {

		// ( namespace ) or ( selector, types [, fn] )
		return arguments.length === 1 ?
			this.off( selector, "**" ) :
			this.off( types, selector || "**", fn );
	},
	size: function() {
		return this.length;
	}
} );

jQuery.fn.andSelf = jQuery.fn.addBack;

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
	__webpack_require__(10)
], __WEBPACK_AMD_DEFINE_RESULT__ = (function( jQuery ) {

// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.

// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon

if ( true ) {
	!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {
		return jQuery;
	}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
}

}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;//     Backbone.js 1.4.0

//     (c) 2010-2019 Jeremy Ashkenas and DocumentCloud
//     Backbone may be freely distributed under the MIT license.
//     For all details and documentation:
//     http://backbonejs.org

(function(factory) {

  // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
  // We use `self` instead of `window` for `WebWorker` support.
  var root = typeof self == 'object' && self.self === self && self ||
            typeof global == 'object' && global.global === global && global;

  // Set up Backbone appropriately for the environment. Start with AMD.
  if (true) {
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(5), __webpack_require__(0), exports], __WEBPACK_AMD_DEFINE_RESULT__ = (function(_, $, exports) {
      // Export global even in AMD case in case this script is loaded with
      // others that may still expect a global Backbone.
      root.Backbone = factory(root, exports, _, $);
    }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

  // Next for Node.js or CommonJS. jQuery may not be needed as a module.
  } else { var _, $; }

})(function(root, Backbone, _, $) {

  // Initial Setup
  // -------------

  // Save the previous value of the `Backbone` variable, so that it can be
  // restored later on, if `noConflict` is used.
  var previousBackbone = root.Backbone;

  // Create a local reference to a common array method we'll want to use later.
  var slice = Array.prototype.slice;

  // Current version of the library. Keep in sync with `package.json`.
  Backbone.VERSION = '1.4.0';

  // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
  // the `$` variable.
  Backbone.$ = $;

  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
  // to its previous owner. Returns a reference to this Backbone object.
  Backbone.noConflict = function() {
    root.Backbone = previousBackbone;
    return this;
  };

  // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
  // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
  // set a `X-Http-Method-Override` header.
  Backbone.emulateHTTP = false;

  // Turn on `emulateJSON` to support legacy servers that can't deal with direct
  // `application/json` requests ... this will encode the body as
  // `application/x-www-form-urlencoded` instead and will send the model in a
  // form param named `model`.
  Backbone.emulateJSON = false;

  // Backbone.Events
  // ---------------

  // A module that can be mixed in to *any object* in order to provide it with
  // a custom event channel. You may bind a callback to an event with `on` or
  // remove with `off`; `trigger`-ing an event fires all callbacks in
  // succession.
  //
  //     var object = {};
  //     _.extend(object, Backbone.Events);
  //     object.on('expand', function(){ alert('expanded'); });
  //     object.trigger('expand');
  //
  var Events = Backbone.Events = {};

  // Regular expression used to split event strings.
  var eventSplitter = /\s+/;

  // A private global variable to share between listeners and listenees.
  var _listening;

  // Iterates over the standard `event, callback` (as well as the fancy multiple
  // space-separated events `"change blur", callback` and jQuery-style event
  // maps `{event: callback}`).
  var eventsApi = function(iteratee, events, name, callback, opts) {
    var i = 0, names;
    if (name && typeof name === 'object') {
      // Handle event maps.
      if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
      for (names = _.keys(name); i < names.length ; i++) {
        events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
      }
    } else if (name && eventSplitter.test(name)) {
      // Handle space-separated event names by delegating them individually.
      for (names = name.split(eventSplitter); i < names.length; i++) {
        events = iteratee(events, names[i], callback, opts);
      }
    } else {
      // Finally, standard events.
      events = iteratee(events, name, callback, opts);
    }
    return events;
  };

  // Bind an event to a `callback` function. Passing `"all"` will bind
  // the callback to all events fired.
  Events.on = function(name, callback, context) {
    this._events = eventsApi(onApi, this._events || {}, name, callback, {
      context: context,
      ctx: this,
      listening: _listening
    });

    if (_listening) {
      var listeners = this._listeners || (this._listeners = {});
      listeners[_listening.id] = _listening;
      // Allow the listening to use a counter, instead of tracking
      // callbacks for library interop
      _listening.interop = false;
    }

    return this;
  };

  // Inversion-of-control versions of `on`. Tell *this* object to listen to
  // an event in another object... keeping track of what it's listening to
  // for easier unbinding later.
  Events.listenTo = function(obj, name, callback) {
    if (!obj) return this;
    var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
    var listeningTo = this._listeningTo || (this._listeningTo = {});
    var listening = _listening = listeningTo[id];

    // This object is not listening to any other events on `obj` yet.
    // Setup the necessary references to track the listening callbacks.
    if (!listening) {
      this._listenId || (this._listenId = _.uniqueId('l'));
      listening = _listening = listeningTo[id] = new Listening(this, obj);
    }

    // Bind callbacks on obj.
    var error = tryCatchOn(obj, name, callback, this);
    _listening = void 0;

    if (error) throw error;
    // If the target obj is not Backbone.Events, track events manually.
    if (listening.interop) listening.on(name, callback);

    return this;
  };

  // The reducing API that adds a callback to the `events` object.
  var onApi = function(events, name, callback, options) {
    if (callback) {
      var handlers = events[name] || (events[name] = []);
      var context = options.context, ctx = options.ctx, listening = options.listening;
      if (listening) listening.count++;

      handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening});
    }
    return events;
  };

  // An try-catch guarded #on function, to prevent poisoning the global
  // `_listening` variable.
  var tryCatchOn = function(obj, name, callback, context) {
    try {
      obj.on(name, callback, context);
    } catch (e) {
      return e;
    }
  };

  // Remove one or many callbacks. If `context` is null, removes all
  // callbacks with that function. If `callback` is null, removes all
  // callbacks for the event. If `name` is null, removes all bound
  // callbacks for all events.
  Events.off = function(name, callback, context) {
    if (!this._events) return this;
    this._events = eventsApi(offApi, this._events, name, callback, {
      context: context,
      listeners: this._listeners
    });

    return this;
  };

  // Tell this object to stop listening to either specific events ... or
  // to every object it's currently listening to.
  Events.stopListening = function(obj, name, callback) {
    var listeningTo = this._listeningTo;
    if (!listeningTo) return this;

    var ids = obj ? [obj._listenId] : _.keys(listeningTo);
    for (var i = 0; i < ids.length; i++) {
      var listening = listeningTo[ids[i]];

      // If listening doesn't exist, this object is not currently
      // listening to obj. Break out early.
      if (!listening) break;

      listening.obj.off(name, callback, this);
      if (listening.interop) listening.off(name, callback);
    }
    if (_.isEmpty(listeningTo)) this._listeningTo = void 0;

    return this;
  };

  // The reducing API that removes a callback from the `events` object.
  var offApi = function(events, name, callback, options) {
    if (!events) return;

    var context = options.context, listeners = options.listeners;
    var i = 0, names;

    // Delete all event listeners and "drop" events.
    if (!name && !context && !callback) {
      for (names = _.keys(listeners); i < names.length; i++) {
        listeners[names[i]].cleanup();
      }
      return;
    }

    names = name ? [name] : _.keys(events);
    for (; i < names.length; i++) {
      name = names[i];
      var handlers = events[name];

      // Bail out if there are no events stored.
      if (!handlers) break;

      // Find any remaining events.
      var remaining = [];
      for (var j = 0; j < handlers.length; j++) {
        var handler = handlers[j];
        if (
          callback && callback !== handler.callback &&
            callback !== handler.callback._callback ||
              context && context !== handler.context
        ) {
          remaining.push(handler);
        } else {
          var listening = handler.listening;
          if (listening) listening.off(name, callback);
        }
      }

      // Replace events if there are any remaining.  Otherwise, clean up.
      if (remaining.length) {
        events[name] = remaining;
      } else {
        delete events[name];
      }
    }

    return events;
  };

  // Bind an event to only be triggered a single time. After the first time
  // the callback is invoked, its listener will be removed. If multiple events
  // are passed in using the space-separated syntax, the handler will fire
  // once for each event, not once for a combination of all events.
  Events.once = function(name, callback, context) {
    // Map the event into a `{event: once}` object.
    var events = eventsApi(onceMap, {}, name, callback, this.off.bind(this));
    if (typeof name === 'string' && context == null) callback = void 0;
    return this.on(events, callback, context);
  };

  // Inversion-of-control versions of `once`.
  Events.listenToOnce = function(obj, name, callback) {
    // Map the event into a `{event: once}` object.
    var events = eventsApi(onceMap, {}, name, callback, this.stopListening.bind(this, obj));
    return this.listenTo(obj, events);
  };

  // Reduces the event callbacks into a map of `{event: onceWrapper}`.
  // `offer` unbinds the `onceWrapper` after it has been called.
  var onceMap = function(map, name, callback, offer) {
    if (callback) {
      var once = map[name] = _.once(function() {
        offer(name, once);
        callback.apply(this, arguments);
      });
      once._callback = callback;
    }
    return map;
  };

  // Trigger one or many events, firing all bound callbacks. Callbacks are
  // passed the same arguments as `trigger` is, apart from the event name
  // (unless you're listening on `"all"`, which will cause your callback to
  // receive the true name of the event as the first argument).
  Events.trigger = function(name) {
    if (!this._events) return this;

    var length = Math.max(0, arguments.length - 1);
    var args = Array(length);
    for (var i = 0; i < length; i++) args[i] = arguments[i + 1];

    eventsApi(triggerApi, this._events, name, void 0, args);
    return this;
  };

  // Handles triggering the appropriate event callbacks.
  var triggerApi = function(objEvents, name, callback, args) {
    if (objEvents) {
      var events = objEvents[name];
      var allEvents = objEvents.all;
      if (events && allEvents) allEvents = allEvents.slice();
      if (events) triggerEvents(events, args);
      if (allEvents) triggerEvents(allEvents, [name].concat(args));
    }
    return objEvents;
  };

  // A difficult-to-believe, but optimized internal dispatch function for
  // triggering events. Tries to keep the usual cases speedy (most internal
  // Backbone events have 3 arguments).
  var triggerEvents = function(events, args) {
    var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
    switch (args.length) {
      case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
      case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
      case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
      case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
      default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
    }
  };

  // A listening class that tracks and cleans up memory bindings
  // when all callbacks have been offed.
  var Listening = function(listener, obj) {
    this.id = listener._listenId;
    this.listener = listener;
    this.obj = obj;
    this.interop = true;
    this.count = 0;
    this._events = void 0;
  };

  Listening.prototype.on = Events.on;

  // Offs a callback (or several).
  // Uses an optimized counter if the listenee uses Backbone.Events.
  // Otherwise, falls back to manual tracking to support events
  // library interop.
  Listening.prototype.off = function(name, callback) {
    var cleanup;
    if (this.interop) {
      this._events = eventsApi(offApi, this._events, name, callback, {
        context: void 0,
        listeners: void 0
      });
      cleanup = !this._events;
    } else {
      this.count--;
      cleanup = this.count === 0;
    }
    if (cleanup) this.cleanup();
  };

  // Cleans up memory bindings between the listener and the listenee.
  Listening.prototype.cleanup = function() {
    delete this.listener._listeningTo[this.obj._listenId];
    if (!this.interop) delete this.obj._listeners[this.id];
  };

  // Aliases for backwards compatibility.
  Events.bind   = Events.on;
  Events.unbind = Events.off;

  // Allow the `Backbone` object to serve as a global event bus, for folks who
  // want global "pubsub" in a convenient place.
  _.extend(Backbone, Events);

  // Backbone.Model
  // --------------

  // Backbone **Models** are the basic data object in the framework --
  // frequently representing a row in a table in a database on your server.
  // A discrete chunk of data and a bunch of useful, related methods for
  // performing computations and transformations on that data.

  // Create a new model with the specified attributes. A client id (`cid`)
  // is automatically generated and assigned for you.
  var Model = Backbone.Model = function(attributes, options) {
    var attrs = attributes || {};
    options || (options = {});
    this.preinitialize.apply(this, arguments);
    this.cid = _.uniqueId(this.cidPrefix);
    this.attributes = {};
    if (options.collection) this.collection = options.collection;
    if (options.parse) attrs = this.parse(attrs, options) || {};
    var defaults = _.result(this, 'defaults');
    attrs = _.defaults(_.extend({}, defaults, attrs), defaults);
    this.set(attrs, options);
    this.changed = {};
    this.initialize.apply(this, arguments);
  };

  // Attach all inheritable methods to the Model prototype.
  _.extend(Model.prototype, Events, {

    // A hash of attributes whose current and previous value differ.
    changed: null,

    // The value returned during the last failed validation.
    validationError: null,

    // The default name for the JSON `id` attribute is `"id"`. MongoDB and
    // CouchDB users may want to set this to `"_id"`.
    idAttribute: 'id',

    // The prefix is used to create the client id which is used to identify models locally.
    // You may want to override this if you're experiencing name clashes with model ids.
    cidPrefix: 'c',

    // preinitialize is an empty function by default. You can override it with a function
    // or object.  preinitialize will run before any instantiation logic is run in the Model.
    preinitialize: function(){},

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize: function(){},

    // Return a copy of the model's `attributes` object.
    toJSON: function(options) {
      return _.clone(this.attributes);
    },

    // Proxy `Backbone.sync` by default -- but override this if you need
    // custom syncing semantics for *this* particular model.
    sync: function() {
      return Backbone.sync.apply(this, arguments);
    },

    // Get the value of an attribute.
    get: function(attr) {
      return this.attributes[attr];
    },

    // Get the HTML-escaped value of an attribute.
    escape: function(attr) {
      return _.escape(this.get(attr));
    },

    // Returns `true` if the attribute contains a value that is not null
    // or undefined.
    has: function(attr) {
      return this.get(attr) != null;
    },

    // Special-cased proxy to underscore's `_.matches` method.
    matches: function(attrs) {
      return !!_.iteratee(attrs, this)(this.attributes);
    },

    // Set a hash of model attributes on the object, firing `"change"`. This is
    // the core primitive operation of a model, updating the data and notifying
    // anyone who needs to know about the change in state. The heart of the beast.
    set: function(key, val, options) {
      if (key == null) return this;

      // Handle both `"key", value` and `{key: value}` -style arguments.
      var attrs;
      if (typeof key === 'object') {
        attrs = key;
        options = val;
      } else {
        (attrs = {})[key] = val;
      }

      options || (options = {});

      // Run validation.
      if (!this._validate(attrs, options)) return false;

      // Extract attributes and options.
      var unset      = options.unset;
      var silent     = options.silent;
      var changes    = [];
      var changing   = this._changing;
      this._changing = true;

      if (!changing) {
        this._previousAttributes = _.clone(this.attributes);
        this.changed = {};
      }

      var current = this.attributes;
      var changed = this.changed;
      var prev    = this._previousAttributes;

      // For each `set` attribute, update or delete the current value.
      for (var attr in attrs) {
        val = attrs[attr];
        if (!_.isEqual(current[attr], val)) changes.push(attr);
        if (!_.isEqual(prev[attr], val)) {
          changed[attr] = val;
        } else {
          delete changed[attr];
        }
        unset ? delete current[attr] : current[attr] = val;
      }

      // Update the `id`.
      if (this.idAttribute in attrs) this.id = this.get(this.idAttribute);

      // Trigger all relevant attribute changes.
      if (!silent) {
        if (changes.length) this._pending = options;
        for (var i = 0; i < changes.length; i++) {
          this.trigger('change:' + changes[i], this, current[changes[i]], options);
        }
      }

      // You might be wondering why there's a `while` loop here. Changes can
      // be recursively nested within `"change"` events.
      if (changing) return this;
      if (!silent) {
        while (this._pending) {
          options = this._pending;
          this._pending = false;
          this.trigger('change', this, options);
        }
      }
      this._pending = false;
      this._changing = false;
      return this;
    },

    // Remove an attribute from the model, firing `"change"`. `unset` is a noop
    // if the attribute doesn't exist.
    unset: function(attr, options) {
      return this.set(attr, void 0, _.extend({}, options, {unset: true}));
    },

    // Clear all attributes on the model, firing `"change"`.
    clear: function(options) {
      var attrs = {};
      for (var key in this.attributes) attrs[key] = void 0;
      return this.set(attrs, _.extend({}, options, {unset: true}));
    },

    // Determine if the model has changed since the last `"change"` event.
    // If you specify an attribute name, determine if that attribute has changed.
    hasChanged: function(attr) {
      if (attr == null) return !_.isEmpty(this.changed);
      return _.has(this.changed, attr);
    },

    // Return an object containing all the attributes that have changed, or
    // false if there are no changed attributes. Useful for determining what
    // parts of a view need to be updated and/or what attributes need to be
    // persisted to the server. Unset attributes will be set to undefined.
    // You can also pass an attributes object to diff against the model,
    // determining if there *would be* a change.
    changedAttributes: function(diff) {
      if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
      var old = this._changing ? this._previousAttributes : this.attributes;
      var changed = {};
      var hasChanged;
      for (var attr in diff) {
        var val = diff[attr];
        if (_.isEqual(old[attr], val)) continue;
        changed[attr] = val;
        hasChanged = true;
      }
      return hasChanged ? changed : false;
    },

    // Get the previous value of an attribute, recorded at the time the last
    // `"change"` event was fired.
    previous: function(attr) {
      if (attr == null || !this._previousAttributes) return null;
      return this._previousAttributes[attr];
    },

    // Get all of the attributes of the model at the time of the previous
    // `"change"` event.
    previousAttributes: function() {
      return _.clone(this._previousAttributes);
    },

    // Fetch the model from the server, merging the response with the model's
    // local attributes. Any changed attributes will trigger a "change" event.
    fetch: function(options) {
      options = _.extend({parse: true}, options);
      var model = this;
      var success = options.success;
      options.success = function(resp) {
        var serverAttrs = options.parse ? model.parse(resp, options) : resp;
        if (!model.set(serverAttrs, options)) return false;
        if (success) success.call(options.context, model, resp, options);
        model.trigger('sync', model, resp, options);
      };
      wrapError(this, options);
      return this.sync('read', this, options);
    },

    // Set a hash of model attributes, and sync the model to the server.
    // If the server returns an attributes hash that differs, the model's
    // state will be `set` again.
    save: function(key, val, options) {
      // Handle both `"key", value` and `{key: value}` -style arguments.
      var attrs;
      if (key == null || typeof key === 'object') {
        attrs = key;
        options = val;
      } else {
        (attrs = {})[key] = val;
      }

      options = _.extend({validate: true, parse: true}, options);
      var wait = options.wait;

      // If we're not waiting and attributes exist, save acts as
      // `set(attr).save(null, opts)` with validation. Otherwise, check if
      // the model will be valid when the attributes, if any, are set.
      if (attrs && !wait) {
        if (!this.set(attrs, options)) return false;
      } else if (!this._validate(attrs, options)) {
        return false;
      }

      // After a successful server-side save, the client is (optionally)
      // updated with the server-side state.
      var model = this;
      var success = options.success;
      var attributes = this.attributes;
      options.success = function(resp) {
        // Ensure attributes are restored during synchronous saves.
        model.attributes = attributes;
        var serverAttrs = options.parse ? model.parse(resp, options) : resp;
        if (wait) serverAttrs = _.extend({}, attrs, serverAttrs);
        if (serverAttrs && !model.set(serverAttrs, options)) return false;
        if (success) success.call(options.context, model, resp, options);
        model.trigger('sync', model, resp, options);
      };
      wrapError(this, options);

      // Set temporary attributes if `{wait: true}` to properly find new ids.
      if (attrs && wait) this.attributes = _.extend({}, attributes, attrs);

      var method = this.isNew() ? 'create' : options.patch ? 'patch' : 'update';
      if (method === 'patch' && !options.attrs) options.attrs = attrs;
      var xhr = this.sync(method, this, options);

      // Restore attributes.
      this.attributes = attributes;

      return xhr;
    },

    // Destroy this model on the server if it was already persisted.
    // Optimistically removes the model from its collection, if it has one.
    // If `wait: true` is passed, waits for the server to respond before removal.
    destroy: function(options) {
      options = options ? _.clone(options) : {};
      var model = this;
      var success = options.success;
      var wait = options.wait;

      var destroy = function() {
        model.stopListening();
        model.trigger('destroy', model, model.collection, options);
      };

      options.success = function(resp) {
        if (wait) destroy();
        if (success) success.call(options.context, model, resp, options);
        if (!model.isNew()) model.trigger('sync', model, resp, options);
      };

      var xhr = false;
      if (this.isNew()) {
        _.defer(options.success);
      } else {
        wrapError(this, options);
        xhr = this.sync('delete', this, options);
      }
      if (!wait) destroy();
      return xhr;
    },

    // Default URL for the model's representation on the server -- if you're
    // using Backbone's restful methods, override this to change the endpoint
    // that will be called.
    url: function() {
      var base =
        _.result(this, 'urlRoot') ||
        _.result(this.collection, 'url') ||
        urlError();
      if (this.isNew()) return base;
      var id = this.get(this.idAttribute);
      return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id);
    },

    // **parse** converts a response into the hash of attributes to be `set` on
    // the model. The default implementation is just to pass the response along.
    parse: function(resp, options) {
      return resp;
    },

    // Create a new model with identical attributes to this one.
    clone: function() {
      return new this.constructor(this.attributes);
    },

    // A model is new if it has never been saved to the server, and lacks an id.
    isNew: function() {
      return !this.has(this.idAttribute);
    },

    // Check if the model is currently in a valid state.
    isValid: function(options) {
      return this._validate({}, _.extend({}, options, {validate: true}));
    },

    // Run validation against the next complete set of model attributes,
    // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
    _validate: function(attrs, options) {
      if (!options.validate || !this.validate) return true;
      attrs = _.extend({}, this.attributes, attrs);
      var error = this.validationError = this.validate(attrs, options) || null;
      if (!error) return true;
      this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
      return false;
    }

  });

  // Backbone.Collection
  // -------------------

  // If models tend to represent a single row of data, a Backbone Collection is
  // more analogous to a table full of data ... or a small slice or page of that
  // table, or a collection of rows that belong together for a particular reason
  // -- all of the messages in this particular folder, all of the documents
  // belonging to this particular author, and so on. Collections maintain
  // indexes of their models, both in order, and for lookup by `id`.

  // Create a new **Collection**, perhaps to contain a specific type of `model`.
  // If a `comparator` is specified, the Collection will maintain
  // its models in sort order, as they're added and removed.
  var Collection = Backbone.Collection = function(models, options) {
    options || (options = {});
    this.preinitialize.apply(this, arguments);
    if (options.model) this.model = options.model;
    if (options.comparator !== void 0) this.comparator = options.comparator;
    this._reset();
    this.initialize.apply(this, arguments);
    if (models) this.reset(models, _.extend({silent: true}, options));
  };

  // Default options for `Collection#set`.
  var setOptions = {add: true, remove: true, merge: true};
  var addOptions = {add: true, remove: false};

  // Splices `insert` into `array` at index `at`.
  var splice = function(array, insert, at) {
    at = Math.min(Math.max(at, 0), array.length);
    var tail = Array(array.length - at);
    var length = insert.length;
    var i;
    for (i = 0; i < tail.length; i++) tail[i] = array[i + at];
    for (i = 0; i < length; i++) array[i + at] = insert[i];
    for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];
  };

  // Define the Collection's inheritable methods.
  _.extend(Collection.prototype, Events, {

    // The default model for a collection is just a **Backbone.Model**.
    // This should be overridden in most cases.
    model: Model,


    // preinitialize is an empty function by default. You can override it with a function
    // or object.  preinitialize will run before any instantiation logic is run in the Collection.
    preinitialize: function(){},

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize: function(){},

    // The JSON representation of a Collection is an array of the
    // models' attributes.
    toJSON: function(options) {
      return this.map(function(model) { return model.toJSON(options); });
    },

    // Proxy `Backbone.sync` by default.
    sync: function() {
      return Backbone.sync.apply(this, arguments);
    },

    // Add a model, or list of models to the set. `models` may be Backbone
    // Models or raw JavaScript objects to be converted to Models, or any
    // combination of the two.
    add: function(models, options) {
      return this.set(models, _.extend({merge: false}, options, addOptions));
    },

    // Remove a model, or a list of models from the set.
    remove: function(models, options) {
      options = _.extend({}, options);
      var singular = !_.isArray(models);
      models = singular ? [models] : models.slice();
      var removed = this._removeModels(models, options);
      if (!options.silent && removed.length) {
        options.changes = {added: [], merged: [], removed: removed};
        this.trigger('update', this, options);
      }
      return singular ? removed[0] : removed;
    },

    // Update a collection by `set`-ing a new list of models, adding new ones,
    // removing models that are no longer present, and merging models that
    // already exist in the collection, as necessary. Similar to **Model#set**,
    // the core operation for updating the data contained by the collection.
    set: function(models, options) {
      if (models == null) return;

      options = _.extend({}, setOptions, options);
      if (options.parse && !this._isModel(models)) {
        models = this.parse(models, options) || [];
      }

      var singular = !_.isArray(models);
      models = singular ? [models] : models.slice();

      var at = options.at;
      if (at != null) at = +at;
      if (at > this.length) at = this.length;
      if (at < 0) at += this.length + 1;

      var set = [];
      var toAdd = [];
      var toMerge = [];
      var toRemove = [];
      var modelMap = {};

      var add = options.add;
      var merge = options.merge;
      var remove = options.remove;

      var sort = false;
      var sortable = this.comparator && at == null && options.sort !== false;
      var sortAttr = _.isString(this.comparator) ? this.comparator : null;

      // Turn bare objects into model references, and prevent invalid models
      // from being added.
      var model, i;
      for (i = 0; i < models.length; i++) {
        model = models[i];

        // If a duplicate is found, prevent it from being added and
        // optionally merge it into the existing model.
        var existing = this.get(model);
        if (existing) {
          if (merge && model !== existing) {
            var attrs = this._isModel(model) ? model.attributes : model;
            if (options.parse) attrs = existing.parse(attrs, options);
            existing.set(attrs, options);
            toMerge.push(existing);
            if (sortable && !sort) sort = existing.hasChanged(sortAttr);
          }
          if (!modelMap[existing.cid]) {
            modelMap[existing.cid] = true;
            set.push(existing);
          }
          models[i] = existing;

        // If this is a new, valid model, push it to the `toAdd` list.
        } else if (add) {
          model = models[i] = this._prepareModel(model, options);
          if (model) {
            toAdd.push(model);
            this._addReference(model, options);
            modelMap[model.cid] = true;
            set.push(model);
          }
        }
      }

      // Remove stale models.
      if (remove) {
        for (i = 0; i < this.length; i++) {
          model = this.models[i];
          if (!modelMap[model.cid]) toRemove.push(model);
        }
        if (toRemove.length) this._removeModels(toRemove, options);
      }

      // See if sorting is needed, update `length` and splice in new models.
      var orderChanged = false;
      var replace = !sortable && add && remove;
      if (set.length && replace) {
        orderChanged = this.length !== set.length || _.some(this.models, function(m, index) {
          return m !== set[index];
        });
        this.models.length = 0;
        splice(this.models, set, 0);
        this.length = this.models.length;
      } else if (toAdd.length) {
        if (sortable) sort = true;
        splice(this.models, toAdd, at == null ? this.length : at);
        this.length = this.models.length;
      }

      // Silently sort the collection if appropriate.
      if (sort) this.sort({silent: true});

      // Unless silenced, it's time to fire all appropriate add/sort/update events.
      if (!options.silent) {
        for (i = 0; i < toAdd.length; i++) {
          if (at != null) options.index = at + i;
          model = toAdd[i];
          model.trigger('add', model, this, options);
        }
        if (sort || orderChanged) this.trigger('sort', this, options);
        if (toAdd.length || toRemove.length || toMerge.length) {
          options.changes = {
            added: toAdd,
            removed: toRemove,
            merged: toMerge
          };
          this.trigger('update', this, options);
        }
      }

      // Return the added (or merged) model (or models).
      return singular ? models[0] : models;
    },

    // When you have more items than you want to add or remove individually,
    // you can reset the entire set with a new list of models, without firing
    // any granular `add` or `remove` events. Fires `reset` when finished.
    // Useful for bulk operations and optimizations.
    reset: function(models, options) {
      options = options ? _.clone(options) : {};
      for (var i = 0; i < this.models.length; i++) {
        this._removeReference(this.models[i], options);
      }
      options.previousModels = this.models;
      this._reset();
      models = this.add(models, _.extend({silent: true}, options));
      if (!options.silent) this.trigger('reset', this, options);
      return models;
    },

    // Add a model to the end of the collection.
    push: function(model, options) {
      return this.add(model, _.extend({at: this.length}, options));
    },

    // Remove a model from the end of the collection.
    pop: function(options) {
      var model = this.at(this.length - 1);
      return this.remove(model, options);
    },

    // Add a model to the beginning of the collection.
    unshift: function(model, options) {
      return this.add(model, _.extend({at: 0}, options));
    },

    // Remove a model from the beginning of the collection.
    shift: function(options) {
      var model = this.at(0);
      return this.remove(model, options);
    },

    // Slice out a sub-array of models from the collection.
    slice: function() {
      return slice.apply(this.models, arguments);
    },

    // Get a model from the set by id, cid, model object with id or cid
    // properties, or an attributes object that is transformed through modelId.
    get: function(obj) {
      if (obj == null) return void 0;
      return this._byId[obj] ||
        this._byId[this.modelId(this._isModel(obj) ? obj.attributes : obj)] ||
        obj.cid && this._byId[obj.cid];
    },

    // Returns `true` if the model is in the collection.
    has: function(obj) {
      return this.get(obj) != null;
    },

    // Get the model at the given index.
    at: function(index) {
      if (index < 0) index += this.length;
      return this.models[index];
    },

    // Return models with matching attributes. Useful for simple cases of
    // `filter`.
    where: function(attrs, first) {
      return this[first ? 'find' : 'filter'](attrs);
    },

    // Return the first model with matching attributes. Useful for simple cases
    // of `find`.
    findWhere: function(attrs) {
      return this.where(attrs, true);
    },

    // Force the collection to re-sort itself. You don't need to call this under
    // normal circumstances, as the set will maintain sort order as each item
    // is added.
    sort: function(options) {
      var comparator = this.comparator;
      if (!comparator) throw new Error('Cannot sort a set without a comparator');
      options || (options = {});

      var length = comparator.length;
      if (_.isFunction(comparator)) comparator = comparator.bind(this);

      // Run sort based on type of `comparator`.
      if (length === 1 || _.isString(comparator)) {
        this.models = this.sortBy(comparator);
      } else {
        this.models.sort(comparator);
      }
      if (!options.silent) this.trigger('sort', this, options);
      return this;
    },

    // Pluck an attribute from each model in the collection.
    pluck: function(attr) {
      return this.map(attr + '');
    },

    // Fetch the default set of models for this collection, resetting the
    // collection when they arrive. If `reset: true` is passed, the response
    // data will be passed through the `reset` method instead of `set`.
    fetch: function(options) {
      options = _.extend({parse: true}, options);
      var success = options.success;
      var collection = this;
      options.success = function(resp) {
        var method = options.reset ? 'reset' : 'set';
        collection[method](resp, options);
        if (success) success.call(options.context, collection, resp, options);
        collection.trigger('sync', collection, resp, options);
      };
      wrapError(this, options);
      return this.sync('read', this, options);
    },

    // Create a new instance of a model in this collection. Add the model to the
    // collection immediately, unless `wait: true` is passed, in which case we
    // wait for the server to agree.
    create: function(model, options) {
      options = options ? _.clone(options) : {};
      var wait = options.wait;
      model = this._prepareModel(model, options);
      if (!model) return false;
      if (!wait) this.add(model, options);
      var collection = this;
      var success = options.success;
      options.success = function(m, resp, callbackOpts) {
        if (wait) collection.add(m, callbackOpts);
        if (success) success.call(callbackOpts.context, m, resp, callbackOpts);
      };
      model.save(null, options);
      return model;
    },

    // **parse** converts a response into a list of models to be added to the
    // collection. The default implementation is just to pass it through.
    parse: function(resp, options) {
      return resp;
    },

    // Create a new collection with an identical list of models as this one.
    clone: function() {
      return new this.constructor(this.models, {
        model: this.model,
        comparator: this.comparator
      });
    },

    // Define how to uniquely identify models in the collection.
    modelId: function(attrs) {
      return attrs[this.model.prototype.idAttribute || 'id'];
    },

    // Get an iterator of all models in this collection.
    values: function() {
      return new CollectionIterator(this, ITERATOR_VALUES);
    },

    // Get an iterator of all model IDs in this collection.
    keys: function() {
      return new CollectionIterator(this, ITERATOR_KEYS);
    },

    // Get an iterator of all [ID, model] tuples in this collection.
    entries: function() {
      return new CollectionIterator(this, ITERATOR_KEYSVALUES);
    },

    // Private method to reset all internal state. Called when the collection
    // is first initialized or reset.
    _reset: function() {
      this.length = 0;
      this.models = [];
      this._byId  = {};
    },

    // Prepare a hash of attributes (or other model) to be added to this
    // collection.
    _prepareModel: function(attrs, options) {
      if (this._isModel(attrs)) {
        if (!attrs.collection) attrs.collection = this;
        return attrs;
      }
      options = options ? _.clone(options) : {};
      options.collection = this;
      var model = new this.model(attrs, options);
      if (!model.validationError) return model;
      this.trigger('invalid', this, model.validationError, options);
      return false;
    },

    // Internal method called by both remove and set.
    _removeModels: function(models, options) {
      var removed = [];
      for (var i = 0; i < models.length; i++) {
        var model = this.get(models[i]);
        if (!model) continue;

        var index = this.indexOf(model);
        this.models.splice(index, 1);
        this.length--;

        // Remove references before triggering 'remove' event to prevent an
        // infinite loop. #3693
        delete this._byId[model.cid];
        var id = this.modelId(model.attributes);
        if (id != null) delete this._byId[id];

        if (!options.silent) {
          options.index = index;
          model.trigger('remove', model, this, options);
        }

        removed.push(model);
        this._removeReference(model, options);
      }
      return removed;
    },

    // Method for checking whether an object should be considered a model for
    // the purposes of adding to the collection.
    _isModel: function(model) {
      return model instanceof Model;
    },

    // Internal method to create a model's ties to a collection.
    _addReference: function(model, options) {
      this._byId[model.cid] = model;
      var id = this.modelId(model.attributes);
      if (id != null) this._byId[id] = model;
      model.on('all', this._onModelEvent, this);
    },

    // Internal method to sever a model's ties to a collection.
    _removeReference: function(model, options) {
      delete this._byId[model.cid];
      var id = this.modelId(model.attributes);
      if (id != null) delete this._byId[id];
      if (this === model.collection) delete model.collection;
      model.off('all', this._onModelEvent, this);
    },

    // Internal method called every time a model in the set fires an event.
    // Sets need to update their indexes when models change ids. All other
    // events simply proxy through. "add" and "remove" events that originate
    // in other collections are ignored.
    _onModelEvent: function(event, model, collection, options) {
      if (model) {
        if ((event === 'add' || event === 'remove') && collection !== this) return;
        if (event === 'destroy') this.remove(model, options);
        if (event === 'change') {
          var prevId = this.modelId(model.previousAttributes());
          var id = this.modelId(model.attributes);
          if (prevId !== id) {
            if (prevId != null) delete this._byId[prevId];
            if (id != null) this._byId[id] = model;
          }
        }
      }
      this.trigger.apply(this, arguments);
    }

  });

  // Defining an @@iterator method implements JavaScript's Iterable protocol.
  // In modern ES2015 browsers, this value is found at Symbol.iterator.
  /* global Symbol */
  var $$iterator = typeof Symbol === 'function' && Symbol.iterator;
  if ($$iterator) {
    Collection.prototype[$$iterator] = Collection.prototype.values;
  }

  // CollectionIterator
  // ------------------

  // A CollectionIterator implements JavaScript's Iterator protocol, allowing the
  // use of `for of` loops in modern browsers and interoperation between
  // Backbone.Collection and other JavaScript functions and third-party libraries
  // which can operate on Iterables.
  var CollectionIterator = function(collection, kind) {
    this._collection = collection;
    this._kind = kind;
    this._index = 0;
  };

  // This "enum" defines the three possible kinds of values which can be emitted
  // by a CollectionIterator that correspond to the values(), keys() and entries()
  // methods on Collection, respectively.
  var ITERATOR_VALUES = 1;
  var ITERATOR_KEYS = 2;
  var ITERATOR_KEYSVALUES = 3;

  // All Iterators should themselves be Iterable.
  if ($$iterator) {
    CollectionIterator.prototype[$$iterator] = function() {
      return this;
    };
  }

  CollectionIterator.prototype.next = function() {
    if (this._collection) {

      // Only continue iterating if the iterated collection is long enough.
      if (this._index < this._collection.length) {
        var model = this._collection.at(this._index);
        this._index++;

        // Construct a value depending on what kind of values should be iterated.
        var value;
        if (this._kind === ITERATOR_VALUES) {
          value = model;
        } else {
          var id = this._collection.modelId(model.attributes);
          if (this._kind === ITERATOR_KEYS) {
            value = id;
          } else { // ITERATOR_KEYSVALUES
            value = [id, model];
          }
        }
        return {value: value, done: false};
      }

      // Once exhausted, remove the reference to the collection so future
      // calls to the next method always return done.
      this._collection = void 0;
    }

    return {value: void 0, done: true};
  };

  // Backbone.View
  // -------------

  // Backbone Views are almost more convention than they are actual code. A View
  // is simply a JavaScript object that represents a logical chunk of UI in the
  // DOM. This might be a single item, an entire list, a sidebar or panel, or
  // even the surrounding frame which wraps your whole app. Defining a chunk of
  // UI as a **View** allows you to define your DOM events declaratively, without
  // having to worry about render order ... and makes it easy for the view to
  // react to specific changes in the state of your models.

  // Creating a Backbone.View creates its initial element outside of the DOM,
  // if an existing element is not provided...
  var View = Backbone.View = function(options) {
    this.cid = _.uniqueId('view');
    this.preinitialize.apply(this, arguments);
    _.extend(this, _.pick(options, viewOptions));
    this._ensureElement();
    this.initialize.apply(this, arguments);
  };

  // Cached regex to split keys for `delegate`.
  var delegateEventSplitter = /^(\S+)\s*(.*)$/;

  // List of view options to be set as properties.
  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];

  // Set up all inheritable **Backbone.View** properties and methods.
  _.extend(View.prototype, Events, {

    // The default `tagName` of a View's element is `"div"`.
    tagName: 'div',

    // jQuery delegate for element lookup, scoped to DOM elements within the
    // current view. This should be preferred to global lookups where possible.
    $: function(selector) {
      return this.$el.find(selector);
    },

    // preinitialize is an empty function by default. You can override it with a function
    // or object.  preinitialize will run before any instantiation logic is run in the View
    preinitialize: function(){},

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize: function(){},

    // **render** is the core function that your view should override, in order
    // to populate its element (`this.el`), with the appropriate HTML. The
    // convention is for **render** to always return `this`.
    render: function() {
      return this;
    },

    // Remove this view by taking the element out of the DOM, and removing any
    // applicable Backbone.Events listeners.
    remove: function() {
      this._removeElement();
      this.stopListening();
      return this;
    },

    // Remove this view's element from the document and all event listeners
    // attached to it. Exposed for subclasses using an alternative DOM
    // manipulation API.
    _removeElement: function() {
      this.$el.remove();
    },

    // Change the view's element (`this.el` property) and re-delegate the
    // view's events on the new element.
    setElement: function(element) {
      this.undelegateEvents();
      this._setElement(element);
      this.delegateEvents();
      return this;
    },

    // Creates the `this.el` and `this.$el` references for this view using the
    // given `el`. `el` can be a CSS selector or an HTML string, a jQuery
    // context or an element. Subclasses can override this to utilize an
    // alternative DOM manipulation API and are only required to set the
    // `this.el` property.
    _setElement: function(el) {
      this.$el = el instanceof Backbone.$ ? el : Backbone.$(el);
      this.el = this.$el[0];
    },

    // Set callbacks, where `this.events` is a hash of
    //
    // *{"event selector": "callback"}*
    //
    //     {
    //       'mousedown .title':  'edit',
    //       'click .button':     'save',
    //       'click .open':       function(e) { ... }
    //     }
    //
    // pairs. Callbacks will be bound to the view, with `this` set properly.
    // Uses event delegation for efficiency.
    // Omitting the selector binds the event to `this.el`.
    delegateEvents: function(events) {
      events || (events = _.result(this, 'events'));
      if (!events) return this;
      this.undelegateEvents();
      for (var key in events) {
        var method = events[key];
        if (!_.isFunction(method)) method = this[method];
        if (!method) continue;
        var match = key.match(delegateEventSplitter);
        this.delegate(match[1], match[2], method.bind(this));
      }
      return this;
    },

    // Add a single event listener to the view's element (or a child element
    // using `selector`). This only works for delegate-able events: not `focus`,
    // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.
    delegate: function(eventName, selector, listener) {
      this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
      return this;
    },

    // Clears all callbacks previously bound to the view by `delegateEvents`.
    // You usually don't need to use this, but may wish to if you have multiple
    // Backbone views attached to the same DOM element.
    undelegateEvents: function() {
      if (this.$el) this.$el.off('.delegateEvents' + this.cid);
      return this;
    },

    // A finer-grained `undelegateEvents` for removing a single delegated event.
    // `selector` and `listener` are both optional.
    undelegate: function(eventName, selector, listener) {
      this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener);
      return this;
    },

    // Produces a DOM element to be assigned to your view. Exposed for
    // subclasses using an alternative DOM manipulation API.
    _createElement: function(tagName) {
      return document.createElement(tagName);
    },

    // Ensure that the View has a DOM element to render into.
    // If `this.el` is a string, pass it through `$()`, take the first
    // matching element, and re-assign it to `el`. Otherwise, create
    // an element from the `id`, `className` and `tagName` properties.
    _ensureElement: function() {
      if (!this.el) {
        var attrs = _.extend({}, _.result(this, 'attributes'));
        if (this.id) attrs.id = _.result(this, 'id');
        if (this.className) attrs['class'] = _.result(this, 'className');
        this.setElement(this._createElement(_.result(this, 'tagName')));
        this._setAttributes(attrs);
      } else {
        this.setElement(_.result(this, 'el'));
      }
    },

    // Set attributes from a hash on this view's element.  Exposed for
    // subclasses using an alternative DOM manipulation API.
    _setAttributes: function(attributes) {
      this.$el.attr(attributes);
    }

  });

  // Proxy Backbone class methods to Underscore functions, wrapping the model's
  // `attributes` object or collection's `models` array behind the scenes.
  //
  // collection.filter(function(model) { return model.get('age') > 10 });
  // collection.each(this.addView);
  //
  // `Function#apply` can be slow so we use the method's arg count, if we know it.
  var addMethod = function(base, length, method, attribute) {
    switch (length) {
      case 1: return function() {
        return base[method](this[attribute]);
      };
      case 2: return function(value) {
        return base[method](this[attribute], value);
      };
      case 3: return function(iteratee, context) {
        return base[method](this[attribute], cb(iteratee, this), context);
      };
      case 4: return function(iteratee, defaultVal, context) {
        return base[method](this[attribute], cb(iteratee, this), defaultVal, context);
      };
      default: return function() {
        var args = slice.call(arguments);
        args.unshift(this[attribute]);
        return base[method].apply(base, args);
      };
    }
  };

  var addUnderscoreMethods = function(Class, base, methods, attribute) {
    _.each(methods, function(length, method) {
      if (base[method]) Class.prototype[method] = addMethod(base, length, method, attribute);
    });
  };

  // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`.
  var cb = function(iteratee, instance) {
    if (_.isFunction(iteratee)) return iteratee;
    if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
    if (_.isString(iteratee)) return function(model) { return model.get(iteratee); };
    return iteratee;
  };
  var modelMatcher = function(attrs) {
    var matcher = _.matches(attrs);
    return function(model) {
      return matcher(model.attributes);
    };
  };

  // Underscore methods that we want to implement on the Collection.
  // 90% of the core usefulness of Backbone Collections is actually implemented
  // right here:
  var collectionMethods = {forEach: 3, each: 3, map: 3, collect: 3, reduce: 0,
    foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3,
    select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3,
    contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
    head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
    without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3,
    isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3,
    sortBy: 3, indexBy: 3, findIndex: 3, findLastIndex: 3};


  // Underscore methods that we want to implement on the Model, mapped to the
  // number of arguments they take.
  var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
    omit: 0, chain: 1, isEmpty: 1};

  // Mix in each Underscore method as a proxy to `Collection#models`.

  _.each([
    [Collection, collectionMethods, 'models'],
    [Model, modelMethods, 'attributes']
  ], function(config) {
    var Base = config[0],
        methods = config[1],
        attribute = config[2];

    Base.mixin = function(obj) {
      var mappings = _.reduce(_.functions(obj), function(memo, name) {
        memo[name] = 0;
        return memo;
      }, {});
      addUnderscoreMethods(Base, obj, mappings, attribute);
    };

    addUnderscoreMethods(Base, _, methods, attribute);
  });

  // Backbone.sync
  // -------------

  // Override this function to change the manner in which Backbone persists
  // models to the server. You will be passed the type of request, and the
  // model in question. By default, makes a RESTful Ajax request
  // to the model's `url()`. Some possible customizations could be:
  //
  // * Use `setTimeout` to batch rapid-fire updates into a single request.
  // * Send up the models as XML instead of JSON.
  // * Persist models via WebSockets instead of Ajax.
  //
  // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
  // as `POST`, with a `_method` parameter containing the true HTTP method,
  // as well as all requests with the body as `application/x-www-form-urlencoded`
  // instead of `application/json` with the model in a param named `model`.
  // Useful when interfacing with server-side languages like **PHP** that make
  // it difficult to read the body of `PUT` requests.
  Backbone.sync = function(method, model, options) {
    var type = methodMap[method];

    // Default options, unless specified.
    _.defaults(options || (options = {}), {
      emulateHTTP: Backbone.emulateHTTP,
      emulateJSON: Backbone.emulateJSON
    });

    // Default JSON-request options.
    var params = {type: type, dataType: 'json'};

    // Ensure that we have a URL.
    if (!options.url) {
      params.url = _.result(model, 'url') || urlError();
    }

    // Ensure that we have the appropriate request data.
    if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
      params.contentType = 'application/json';
      params.data = JSON.stringify(options.attrs || model.toJSON(options));
    }

    // For older servers, emulate JSON by encoding the request into an HTML-form.
    if (options.emulateJSON) {
      params.contentType = 'application/x-www-form-urlencoded';
      params.data = params.data ? {model: params.data} : {};
    }

    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
    // And an `X-HTTP-Method-Override` header.
    if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
      params.type = 'POST';
      if (options.emulateJSON) params.data._method = type;
      var beforeSend = options.beforeSend;
      options.beforeSend = function(xhr) {
        xhr.setRequestHeader('X-HTTP-Method-Override', type);
        if (beforeSend) return beforeSend.apply(this, arguments);
      };
    }

    // Don't process data on a non-GET request.
    if (params.type !== 'GET' && !options.emulateJSON) {
      params.processData = false;
    }

    // Pass along `textStatus` and `errorThrown` from jQuery.
    var error = options.error;
    options.error = function(xhr, textStatus, errorThrown) {
      options.textStatus = textStatus;
      options.errorThrown = errorThrown;
      if (error) error.call(options.context, xhr, textStatus, errorThrown);
    };

    // Make the request, allowing the user to override any Ajax options.
    var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
    model.trigger('request', model, xhr, options);
    return xhr;
  };

  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
  var methodMap = {
    create: 'POST',
    update: 'PUT',
    patch: 'PATCH',
    delete: 'DELETE',
    read: 'GET'
  };

  // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
  // Override this if you'd like to use a different library.
  Backbone.ajax = function() {
    return Backbone.$.ajax.apply(Backbone.$, arguments);
  };

  // Backbone.Router
  // ---------------

  // Routers map faux-URLs to actions, and fire events when routes are
  // matched. Creating a new one sets its `routes` hash, if not set statically.
  var Router = Backbone.Router = function(options) {
    options || (options = {});
    this.preinitialize.apply(this, arguments);
    if (options.routes) this.routes = options.routes;
    this._bindRoutes();
    this.initialize.apply(this, arguments);
  };

  // Cached regular expressions for matching named param parts and splatted
  // parts of route strings.
  var optionalParam = /\((.*?)\)/g;
  var namedParam    = /(\(\?)?:\w+/g;
  var splatParam    = /\*\w+/g;
  var escapeRegExp  = /[\-{}\[\]+?.,\\\^$|#\s]/g;

  // Set up all inheritable **Backbone.Router** properties and methods.
  _.extend(Router.prototype, Events, {

    // preinitialize is an empty function by default. You can override it with a function
    // or object.  preinitialize will run before any instantiation logic is run in the Router.
    preinitialize: function(){},

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize: function(){},

    // Manually bind a single named route to a callback. For example:
    //
    //     this.route('search/:query/p:num', 'search', function(query, num) {
    //       ...
    //     });
    //
    route: function(route, name, callback) {
      if (!_.isRegExp(route)) route = this._routeToRegExp(route);
      if (_.isFunction(name)) {
        callback = name;
        name = '';
      }
      if (!callback) callback = this[name];
      var router = this;
      Backbone.history.route(route, function(fragment) {
        var args = router._extractParameters(route, fragment);
        if (router.execute(callback, args, name) !== false) {
          router.trigger.apply(router, ['route:' + name].concat(args));
          router.trigger('route', name, args);
          Backbone.history.trigger('route', router, name, args);
        }
      });
      return this;
    },

    // Execute a route handler with the provided parameters.  This is an
    // excellent place to do pre-route setup or post-route cleanup.
    execute: function(callback, args, name) {
      if (callback) callback.apply(this, args);
    },

    // Simple proxy to `Backbone.history` to save a fragment into the history.
    navigate: function(fragment, options) {
      Backbone.history.navigate(fragment, options);
      return this;
    },

    // Bind all defined routes to `Backbone.history`. We have to reverse the
    // order of the routes here to support behavior where the most general
    // routes can be defined at the bottom of the route map.
    _bindRoutes: function() {
      if (!this.routes) return;
      this.routes = _.result(this, 'routes');
      var route, routes = _.keys(this.routes);
      while ((route = routes.pop()) != null) {
        this.route(route, this.routes[route]);
      }
    },

    // Convert a route string into a regular expression, suitable for matching
    // against the current location hash.
    _routeToRegExp: function(route) {
      route = route.replace(escapeRegExp, '\\$&')
        .replace(optionalParam, '(?:$1)?')
        .replace(namedParam, function(match, optional) {
          return optional ? match : '([^/?]+)';
        })
        .replace(splatParam, '([^?]*?)');
      return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
    },

    // Given a route, and a URL fragment that it matches, return the array of
    // extracted decoded parameters. Empty or unmatched parameters will be
    // treated as `null` to normalize cross-browser behavior.
    _extractParameters: function(route, fragment) {
      var params = route.exec(fragment).slice(1);
      return _.map(params, function(param, i) {
        // Don't decode the search params.
        if (i === params.length - 1) return param || null;
        return param ? decodeURIComponent(param) : null;
      });
    }

  });

  // Backbone.History
  // ----------------

  // Handles cross-browser history management, based on either
  // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
  // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
  // and URL fragments. If the browser supports neither (old IE, natch),
  // falls back to polling.
  var History = Backbone.History = function() {
    this.handlers = [];
    this.checkUrl = this.checkUrl.bind(this);

    // Ensure that `History` can be used outside of the browser.
    if (typeof window !== 'undefined') {
      this.location = window.location;
      this.history = window.history;
    }
  };

  // Cached regex for stripping a leading hash/slash and trailing space.
  var routeStripper = /^[#\/]|\s+$/g;

  // Cached regex for stripping leading and trailing slashes.
  var rootStripper = /^\/+|\/+$/g;

  // Cached regex for stripping urls of hash.
  var pathStripper = /#.*$/;

  // Has the history handling already been started?
  History.started = false;

  // Set up all inheritable **Backbone.History** properties and methods.
  _.extend(History.prototype, Events, {

    // The default interval to poll for hash changes, if necessary, is
    // twenty times a second.
    interval: 50,

    // Are we at the app root?
    atRoot: function() {
      var path = this.location.pathname.replace(/[^\/]$/, '$&/');
      return path === this.root && !this.getSearch();
    },

    // Does the pathname match the root?
    matchRoot: function() {
      var path = this.decodeFragment(this.location.pathname);
      var rootPath = path.slice(0, this.root.length - 1) + '/';
      return rootPath === this.root;
    },

    // Unicode characters in `location.pathname` are percent encoded so they're
    // decoded for comparison. `%25` should not be decoded since it may be part
    // of an encoded parameter.
    decodeFragment: function(fragment) {
      return decodeURI(fragment.replace(/%25/g, '%2525'));
    },

    // In IE6, the hash fragment and search params are incorrect if the
    // fragment contains `?`.
    getSearch: function() {
      var match = this.location.href.replace(/#.*/, '').match(/\?.+/);
      return match ? match[0] : '';
    },

    // Gets the true hash value. Cannot use location.hash directly due to bug
    // in Firefox where location.hash will always be decoded.
    getHash: function(window) {
      var match = (window || this).location.href.match(/#(.*)$/);
      return match ? match[1] : '';
    },

    // Get the pathname and search params, without the root.
    getPath: function() {
      var path = this.decodeFragment(
        this.location.pathname + this.getSearch()
      ).slice(this.root.length - 1);
      return path.charAt(0) === '/' ? path.slice(1) : path;
    },

    // Get the cross-browser normalized URL fragment from the path or hash.
    getFragment: function(fragment) {
      if (fragment == null) {
        if (this._usePushState || !this._wantsHashChange) {
          fragment = this.getPath();
        } else {
          fragment = this.getHash();
        }
      }
      return fragment.replace(routeStripper, '');
    },

    // Start the hash change handling, returning `true` if the current URL matches
    // an existing route, and `false` otherwise.
    start: function(options) {
      if (History.started) throw new Error('Backbone.history has already been started');
      History.started = true;

      // Figure out the initial configuration. Do we need an iframe?
      // Is pushState desired ... is it available?
      this.options          = _.extend({root: '/'}, this.options, options);
      this.root             = this.options.root;
      this._wantsHashChange = this.options.hashChange !== false;
      this._hasHashChange   = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7);
      this._useHashChange   = this._wantsHashChange && this._hasHashChange;
      this._wantsPushState  = !!this.options.pushState;
      this._hasPushState    = !!(this.history && this.history.pushState);
      this._usePushState    = this._wantsPushState && this._hasPushState;
      this.fragment         = this.getFragment();

      // Normalize root to always include a leading and trailing slash.
      this.root = ('/' + this.root + '/').replace(rootStripper, '/');

      // Transition from hashChange to pushState or vice versa if both are
      // requested.
      if (this._wantsHashChange && this._wantsPushState) {

        // If we've started off with a route from a `pushState`-enabled
        // browser, but we're currently in a browser that doesn't support it...
        if (!this._hasPushState && !this.atRoot()) {
          var rootPath = this.root.slice(0, -1) || '/';
          this.location.replace(rootPath + '#' + this.getPath());
          // Return immediately as browser will do redirect to new url
          return true;

        // Or if we've started out with a hash-based route, but we're currently
        // in a browser where it could be `pushState`-based instead...
        } else if (this._hasPushState && this.atRoot()) {
          this.navigate(this.getHash(), {replace: true});
        }

      }

      // Proxy an iframe to handle location events if the browser doesn't
      // support the `hashchange` event, HTML5 history, or the user wants
      // `hashChange` but not `pushState`.
      if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) {
        this.iframe = document.createElement('iframe');
        this.iframe.src = 'javascript:0';
        this.iframe.style.display = 'none';
        this.iframe.tabIndex = -1;
        var body = document.body;
        // Using `appendChild` will throw on IE < 9 if the document is not ready.
        var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow;
        iWindow.document.open();
        iWindow.document.close();
        iWindow.location.hash = '#' + this.fragment;
      }

      // Add a cross-platform `addEventListener` shim for older browsers.
      var addEventListener = window.addEventListener || function(eventName, listener) {
        return attachEvent('on' + eventName, listener);
      };

      // Depending on whether we're using pushState or hashes, and whether
      // 'onhashchange' is supported, determine how we check the URL state.
      if (this._usePushState) {
        addEventListener('popstate', this.checkUrl, false);
      } else if (this._useHashChange && !this.iframe) {
        addEventListener('hashchange', this.checkUrl, false);
      } else if (this._wantsHashChange) {
        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
      }

      if (!this.options.silent) return this.loadUrl();
    },

    // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
    // but possibly useful for unit testing Routers.
    stop: function() {
      // Add a cross-platform `removeEventListener` shim for older browsers.
      var removeEventListener = window.removeEventListener || function(eventName, listener) {
        return detachEvent('on' + eventName, listener);
      };

      // Remove window listeners.
      if (this._usePushState) {
        removeEventListener('popstate', this.checkUrl, false);
      } else if (this._useHashChange && !this.iframe) {
        removeEventListener('hashchange', this.checkUrl, false);
      }

      // Clean up the iframe if necessary.
      if (this.iframe) {
        document.body.removeChild(this.iframe);
        this.iframe = null;
      }

      // Some environments will throw when clearing an undefined interval.
      if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
      History.started = false;
    },

    // Add a route to be tested when the fragment changes. Routes added later
    // may override previous routes.
    route: function(route, callback) {
      this.handlers.unshift({route: route, callback: callback});
    },

    // Checks the current URL to see if it has changed, and if it has,
    // calls `loadUrl`, normalizing across the hidden iframe.
    checkUrl: function(e) {
      var current = this.getFragment();

      // If the user pressed the back button, the iframe's hash will have
      // changed and we should use that for comparison.
      if (current === this.fragment && this.iframe) {
        current = this.getHash(this.iframe.contentWindow);
      }

      if (current === this.fragment) return false;
      if (this.iframe) this.navigate(current);
      this.loadUrl();
    },

    // Attempt to load the current URL fragment. If a route succeeds with a
    // match, returns `true`. If no defined routes matches the fragment,
    // returns `false`.
    loadUrl: function(fragment) {
      // If the root doesn't match, no routes can match either.
      if (!this.matchRoot()) return false;
      fragment = this.fragment = this.getFragment(fragment);
      return _.some(this.handlers, function(handler) {
        if (handler.route.test(fragment)) {
          handler.callback(fragment);
          return true;
        }
      });
    },

    // Save a fragment into the hash history, or replace the URL state if the
    // 'replace' option is passed. You are responsible for properly URL-encoding
    // the fragment in advance.
    //
    // The options object can contain `trigger: true` if you wish to have the
    // route callback be fired (not usually desirable), or `replace: true`, if
    // you wish to modify the current URL without adding an entry to the history.
    navigate: function(fragment, options) {
      if (!History.started) return false;
      if (!options || options === true) options = {trigger: !!options};

      // Normalize the fragment.
      fragment = this.getFragment(fragment || '');

      // Don't include a trailing slash on the root.
      var rootPath = this.root;
      if (fragment === '' || fragment.charAt(0) === '?') {
        rootPath = rootPath.slice(0, -1) || '/';
      }
      var url = rootPath + fragment;

      // Strip the fragment of the query and hash for matching.
      fragment = fragment.replace(pathStripper, '');

      // Decode for matching.
      var decodedFragment = this.decodeFragment(fragment);

      if (this.fragment === decodedFragment) return;
      this.fragment = decodedFragment;

      // If pushState is available, we use it to set the fragment as a real URL.
      if (this._usePushState) {
        this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);

      // If hash changes haven't been explicitly disabled, update the hash
      // fragment to store history.
      } else if (this._wantsHashChange) {
        this._updateHash(this.location, fragment, options.replace);
        if (this.iframe && fragment !== this.getHash(this.iframe.contentWindow)) {
          var iWindow = this.iframe.contentWindow;

          // Opening and closing the iframe tricks IE7 and earlier to push a
          // history entry on hash-tag change.  When replace is true, we don't
          // want this.
          if (!options.replace) {
            iWindow.document.open();
            iWindow.document.close();
          }

          this._updateHash(iWindow.location, fragment, options.replace);
        }

      // If you've told us that you explicitly don't want fallback hashchange-
      // based history, then `navigate` becomes a page refresh.
      } else {
        return this.location.assign(url);
      }
      if (options.trigger) return this.loadUrl(fragment);
    },

    // Update the hash location, either replacing the current entry, or adding
    // a new one to the browser history.
    _updateHash: function(location, fragment, replace) {
      if (replace) {
        var href = location.href.replace(/(javascript:|#).*$/, '');
        location.replace(href + '#' + fragment);
      } else {
        // Some browsers require that `hash` contains a leading #.
        location.hash = '#' + fragment;
      }
    }

  });

  // Create the default Backbone.history.
  Backbone.history = new History;

  // Helpers
  // -------

  // Helper function to correctly set up the prototype chain for subclasses.
  // Similar to `goog.inherits`, but uses a hash of prototype properties and
  // class properties to be extended.
  var extend = function(protoProps, staticProps) {
    var parent = this;
    var child;

    // The constructor function for the new subclass is either defined by you
    // (the "constructor" property in your `extend` definition), or defaulted
    // by us to simply call the parent constructor.
    if (protoProps && _.has(protoProps, 'constructor')) {
      child = protoProps.constructor;
    } else {
      child = function(){ return parent.apply(this, arguments); };
    }

    // Add static properties to the constructor function, if supplied.
    _.extend(child, parent, staticProps);

    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function and add the prototype properties.
    child.prototype = _.create(parent.prototype, protoProps);
    child.prototype.constructor = child;

    // Set a convenience property in case the parent's prototype is needed
    // later.
    child.__super__ = parent.prototype;

    return child;
  };

  // Set up inheritance for the model, collection, router, view and history.
  Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;

  // Throw an error when a URL is needed, and none is supplied.
  var urlError = function() {
    throw new Error('A "url" property or function must be specified');
  };

  // Wrap an optional error callback with a fallback error event.
  var wrapError = function(model, options) {
    var error = options.error;
    options.error = function(resp) {
      if (error) error.call(options.context, model, resp, options);
      model.trigger('error', model, resp, options);
    };
  };

  return Backbone;
});

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(48)))/* WEBPACK VAR INJECTION */(function(global, module) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;//     Underscore.js 1.9.1
//     http://underscorejs.org
//     (c) 2009-2018 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
//     Underscore may be freely distributed under the MIT license.

(function() {

  // Baseline setup
  // --------------

  // Establish the root object, `window` (`self`) in the browser, `global`
  // on the server, or `this` in some virtual machines. We use `self`
  // instead of `window` for `WebWorker` support.
  var root = typeof self == 'object' && self.self === self && self ||
            typeof global == 'object' && global.global === global && global ||
            this ||
            {};

  // Save the previous value of the `_` variable.
  var previousUnderscore = root._;

  // Save bytes in the minified (but not gzipped) version:
  var ArrayProto = Array.prototype, ObjProto = Object.prototype;
  var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;

  // Create quick reference variables for speed access to core prototypes.
  var push = ArrayProto.push,
      slice = ArrayProto.slice,
      toString = ObjProto.toString,
      hasOwnProperty = ObjProto.hasOwnProperty;

  // All **ECMAScript 5** native function implementations that we hope to use
  // are declared here.
  var nativeIsArray = Array.isArray,
      nativeKeys = Object.keys,
      nativeCreate = Object.create;

  // Naked function reference for surrogate-prototype-swapping.
  var Ctor = function(){};

  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

  // Export the Underscore object for **Node.js**, with
  // backwards-compatibility for their old module API. If we're in
  // the browser, add `_` as a global object.
  // (`nodeType` is checked to ensure that `module`
  // and `exports` are not HTML elements.)
  if ( true && !exports.nodeType) {
    if ( true && !module.nodeType && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else {
    root._ = _;
  }

  // Current version.
  _.VERSION = '1.9.1';

  // Internal function that returns an efficient (for current engines) version
  // of the passed-in callback, to be repeatedly applied in other Underscore
  // functions.
  var optimizeCb = function(func, context, argCount) {
    if (context === void 0) return func;
    switch (argCount == null ? 3 : argCount) {
      case 1: return function(value) {
        return func.call(context, value);
      };
      // The 2-argument case is omitted because we’re not using it.
      case 3: return function(value, index, collection) {
        return func.call(context, value, index, collection);
      };
      case 4: return function(accumulator, value, index, collection) {
        return func.call(context, accumulator, value, index, collection);
      };
    }
    return function() {
      return func.apply(context, arguments);
    };
  };

  var builtinIteratee;

  // An internal function to generate callbacks that can be applied to each
  // element in a collection, returning the desired result — either `identity`,
  // an arbitrary callback, a property matcher, or a property accessor.
  var cb = function(value, context, argCount) {
    if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
    if (value == null) return _.identity;
    if (_.isFunction(value)) return optimizeCb(value, context, argCount);
    if (_.isObject(value) && !_.isArray(value)) return _.matcher(value);
    return _.property(value);
  };

  // External wrapper for our callback generator. Users may customize
  // `_.iteratee` if they want additional predicate/iteratee shorthand styles.
  // This abstraction hides the internal-only argCount argument.
  _.iteratee = builtinIteratee = function(value, context) {
    return cb(value, context, Infinity);
  };

  // Some functions take a variable number of arguments, or a few expected
  // arguments at the beginning and then a variable number of values to operate
  // on. This helper accumulates all remaining arguments past the function’s
  // argument length (or an explicit `startIndex`), into an array that becomes
  // the last argument. Similar to ES6’s "rest parameter".
  var restArguments = function(func, startIndex) {
    startIndex = startIndex == null ? func.length - 1 : +startIndex;
    return function() {
      var length = Math.max(arguments.length - startIndex, 0),
          rest = Array(length),
          index = 0;
      for (; index < length; index++) {
        rest[index] = arguments[index + startIndex];
      }
      switch (startIndex) {
        case 0: return func.call(this, rest);
        case 1: return func.call(this, arguments[0], rest);
        case 2: return func.call(this, arguments[0], arguments[1], rest);
      }
      var args = Array(startIndex + 1);
      for (index = 0; index < startIndex; index++) {
        args[index] = arguments[index];
      }
      args[startIndex] = rest;
      return func.apply(this, args);
    };
  };

  // An internal function for creating a new object that inherits from another.
  var baseCreate = function(prototype) {
    if (!_.isObject(prototype)) return {};
    if (nativeCreate) return nativeCreate(prototype);
    Ctor.prototype = prototype;
    var result = new Ctor;
    Ctor.prototype = null;
    return result;
  };

  var shallowProperty = function(key) {
    return function(obj) {
      return obj == null ? void 0 : obj[key];
    };
  };

  var has = function(obj, path) {
    return obj != null && hasOwnProperty.call(obj, path);
  }

  var deepGet = function(obj, path) {
    var length = path.length;
    for (var i = 0; i < length; i++) {
      if (obj == null) return void 0;
      obj = obj[path[i]];
    }
    return length ? obj : void 0;
  };

  // Helper for collection methods to determine whether a collection
  // should be iterated as an array or as an object.
  // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
  // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
  var getLength = shallowProperty('length');
  var isArrayLike = function(collection) {
    var length = getLength(collection);
    return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
  };

  // Collection Functions
  // --------------------

  // The cornerstone, an `each` implementation, aka `forEach`.
  // Handles raw objects in addition to array-likes. Treats all
  // sparse array-likes as if they were dense.
  _.each = _.forEach = function(obj, iteratee, context) {
    iteratee = optimizeCb(iteratee, context);
    var i, length;
    if (isArrayLike(obj)) {
      for (i = 0, length = obj.length; i < length; i++) {
        iteratee(obj[i], i, obj);
      }
    } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i < length; i++) {
        iteratee(obj[keys[i]], keys[i], obj);
      }
    }
    return obj;
  };

  // Return the results of applying the iteratee to each element.
  _.map = _.collect = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length,
        results = Array(length);
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      results[index] = iteratee(obj[currentKey], currentKey, obj);
    }
    return results;
  };

  // Create a reducing function iterating left or right.
  var createReduce = function(dir) {
    // Wrap code that reassigns argument variables in a separate function than
    // the one that accesses `arguments.length` to avoid a perf hit. (#1991)
    var reducer = function(obj, iteratee, memo, initial) {
      var keys = !isArrayLike(obj) && _.keys(obj),
          length = (keys || obj).length,
          index = dir > 0 ? 0 : length - 1;
      if (!initial) {
        memo = obj[keys ? keys[index] : index];
        index += dir;
      }
      for (; index >= 0 && index < length; index += dir) {
        var currentKey = keys ? keys[index] : index;
        memo = iteratee(memo, obj[currentKey], currentKey, obj);
      }
      return memo;
    };

    return function(obj, iteratee, memo, context) {
      var initial = arguments.length >= 3;
      return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial);
    };
  };

  // **Reduce** builds up a single result from a list of values, aka `inject`,
  // or `foldl`.
  _.reduce = _.foldl = _.inject = createReduce(1);

  // The right-associative version of reduce, also known as `foldr`.
  _.reduceRight = _.foldr = createReduce(-1);

  // Return the first value which passes a truth test. Aliased as `detect`.
  _.find = _.detect = function(obj, predicate, context) {
    var keyFinder = isArrayLike(obj) ? _.findIndex : _.findKey;
    var key = keyFinder(obj, predicate, context);
    if (key !== void 0 && key !== -1) return obj[key];
  };

  // Return all the elements that pass a truth test.
  // Aliased as `select`.
  _.filter = _.select = function(obj, predicate, context) {
    var results = [];
    predicate = cb(predicate, context);
    _.each(obj, function(value, index, list) {
      if (predicate(value, index, list)) results.push(value);
    });
    return results;
  };

  // Return all the elements for which a truth test fails.
  _.reject = function(obj, predicate, context) {
    return _.filter(obj, _.negate(cb(predicate)), context);
  };

  // Determine whether all of the elements match a truth test.
  // Aliased as `all`.
  _.every = _.all = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length;
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      if (!predicate(obj[currentKey], currentKey, obj)) return false;
    }
    return true;
  };

  // Determine if at least one element in the object matches a truth test.
  // Aliased as `any`.
  _.some = _.any = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length;
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      if (predicate(obj[currentKey], currentKey, obj)) return true;
    }
    return false;
  };

  // Determine if the array or object contains a given item (using `===`).
  // Aliased as `includes` and `include`.
  _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
    if (!isArrayLike(obj)) obj = _.values(obj);
    if (typeof fromIndex != 'number' || guard) fromIndex = 0;
    return _.indexOf(obj, item, fromIndex) >= 0;
  };

  // Invoke a method (with arguments) on every item in a collection.
  _.invoke = restArguments(function(obj, path, args) {
    var contextPath, func;
    if (_.isFunction(path)) {
      func = path;
    } else if (_.isArray(path)) {
      contextPath = path.slice(0, -1);
      path = path[path.length - 1];
    }
    return _.map(obj, function(context) {
      var method = func;
      if (!method) {
        if (contextPath && contextPath.length) {
          context = deepGet(context, contextPath);
        }
        if (context == null) return void 0;
        method = context[path];
      }
      return method == null ? method : method.apply(context, args);
    });
  });

  // Convenience version of a common use case of `map`: fetching a property.
  _.pluck = function(obj, key) {
    return _.map(obj, _.property(key));
  };

  // Convenience version of a common use case of `filter`: selecting only objects
  // containing specific `key:value` pairs.
  _.where = function(obj, attrs) {
    return _.filter(obj, _.matcher(attrs));
  };

  // Convenience version of a common use case of `find`: getting the first object
  // containing specific `key:value` pairs.
  _.findWhere = function(obj, attrs) {
    return _.find(obj, _.matcher(attrs));
  };

  // Return the maximum element (or element-based computation).
  _.max = function(obj, iteratee, context) {
    var result = -Infinity, lastComputed = -Infinity,
        value, computed;
    if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value != null && value > result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(v, index, list) {
        computed = iteratee(v, index, list);
        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
          result = v;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

  // Return the minimum element (or element-based computation).
  _.min = function(obj, iteratee, context) {
    var result = Infinity, lastComputed = Infinity,
        value, computed;
    if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value != null && value < result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(v, index, list) {
        computed = iteratee(v, index, list);
        if (computed < lastComputed || computed === Infinity && result === Infinity) {
          result = v;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

  // Shuffle a collection.
  _.shuffle = function(obj) {
    return _.sample(obj, Infinity);
  };

  // Sample **n** random values from a collection using the modern version of the
  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
  // If **n** is not specified, returns a single random element.
  // The internal `guard` argument allows it to work with `map`.
  _.sample = function(obj, n, guard) {
    if (n == null || guard) {
      if (!isArrayLike(obj)) obj = _.values(obj);
      return obj[_.random(obj.length - 1)];
    }
    var sample = isArrayLike(obj) ? _.clone(obj) : _.values(obj);
    var length = getLength(sample);
    n = Math.max(Math.min(n, length), 0);
    var last = length - 1;
    for (var index = 0; index < n; index++) {
      var rand = _.random(index, last);
      var temp = sample[index];
      sample[index] = sample[rand];
      sample[rand] = temp;
    }
    return sample.slice(0, n);
  };

  // Sort the object's values by a criterion produced by an iteratee.
  _.sortBy = function(obj, iteratee, context) {
    var index = 0;
    iteratee = cb(iteratee, context);
    return _.pluck(_.map(obj, function(value, key, list) {
      return {
        value: value,
        index: index++,
        criteria: iteratee(value, key, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria;
      var b = right.criteria;
      if (a !== b) {
        if (a > b || a === void 0) return 1;
        if (a < b || b === void 0) return -1;
      }
      return left.index - right.index;
    }), 'value');
  };

  // An internal function used for aggregate "group by" operations.
  var group = function(behavior, partition) {
    return function(obj, iteratee, context) {
      var result = partition ? [[], []] : {};
      iteratee = cb(iteratee, context);
      _.each(obj, function(value, index) {
        var key = iteratee(value, index, obj);
        behavior(result, value, key);
      });
      return result;
    };
  };

  // Groups the object's values by a criterion. Pass either a string attribute
  // to group by, or a function that returns the criterion.
  _.groupBy = group(function(result, value, key) {
    if (has(result, key)) result[key].push(value); else result[key] = [value];
  });

  // Indexes the object's values by a criterion, similar to `groupBy`, but for
  // when you know that your index values will be unique.
  _.indexBy = group(function(result, value, key) {
    result[key] = value;
  });

  // Counts instances of an object that group by a certain criterion. Pass
  // either a string attribute to count by, or a function that returns the
  // criterion.
  _.countBy = group(function(result, value, key) {
    if (has(result, key)) result[key]++; else result[key] = 1;
  });

  var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;
  // Safely create a real, live array from anything iterable.
  _.toArray = function(obj) {
    if (!obj) return [];
    if (_.isArray(obj)) return slice.call(obj);
    if (_.isString(obj)) {
      // Keep surrogate pair characters together
      return obj.match(reStrSymbol);
    }
    if (isArrayLike(obj)) return _.map(obj, _.identity);
    return _.values(obj);
  };

  // Return the number of elements in an object.
  _.size = function(obj) {
    if (obj == null) return 0;
    return isArrayLike(obj) ? obj.length : _.keys(obj).length;
  };

  // Split a collection into two arrays: one whose elements all satisfy the given
  // predicate, and one whose elements all do not satisfy the predicate.
  _.partition = group(function(result, value, pass) {
    result[pass ? 0 : 1].push(value);
  }, true);

  // Array Functions
  // ---------------

  // Get the first element of an array. Passing **n** will return the first N
  // values in the array. Aliased as `head` and `take`. The **guard** check
  // allows it to work with `_.map`.
  _.first = _.head = _.take = function(array, n, guard) {
    if (array == null || array.length < 1) return n == null ? void 0 : [];
    if (n == null || guard) return array[0];
    return _.initial(array, array.length - n);
  };

  // Returns everything but the last entry of the array. Especially useful on
  // the arguments object. Passing **n** will return all the values in
  // the array, excluding the last N.
  _.initial = function(array, n, guard) {
    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
  };

  // Get the last element of an array. Passing **n** will return the last N
  // values in the array.
  _.last = function(array, n, guard) {
    if (array == null || array.length < 1) return n == null ? void 0 : [];
    if (n == null || guard) return array[array.length - 1];
    return _.rest(array, Math.max(0, array.length - n));
  };

  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
  // Especially useful on the arguments object. Passing an **n** will return
  // the rest N values in the array.
  _.rest = _.tail = _.drop = function(array, n, guard) {
    return slice.call(array, n == null || guard ? 1 : n);
  };

  // Trim out all falsy values from an array.
  _.compact = function(array) {
    return _.filter(array, Boolean);
  };

  // Internal implementation of a recursive `flatten` function.
  var flatten = function(input, shallow, strict, output) {
    output = output || [];
    var idx = output.length;
    for (var i = 0, length = getLength(input); i < length; i++) {
      var value = input[i];
      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
        // Flatten current level of array or arguments object.
        if (shallow) {
          var j = 0, len = value.length;
          while (j < len) output[idx++] = value[j++];
        } else {
          flatten(value, shallow, strict, output);
          idx = output.length;
        }
      } else if (!strict) {
        output[idx++] = value;
      }
    }
    return output;
  };

  // Flatten out an array, either recursively (by default), or just one level.
  _.flatten = function(array, shallow) {
    return flatten(array, shallow, false);
  };

  // Return a version of the array that does not contain the specified value(s).
  _.without = restArguments(function(array, otherArrays) {
    return _.difference(array, otherArrays);
  });

  // Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  // The faster algorithm will not work with an iteratee if the iteratee
  // is not a one-to-one function, so providing an iteratee will disable
  // the faster algorithm.
  // Aliased as `unique`.
  _.uniq = _.unique = function(array, isSorted, iteratee, context) {
    if (!_.isBoolean(isSorted)) {
      context = iteratee;
      iteratee = isSorted;
      isSorted = false;
    }
    if (iteratee != null) iteratee = cb(iteratee, context);
    var result = [];
    var seen = [];
    for (var i = 0, length = getLength(array); i < length; i++) {
      var value = array[i],
          computed = iteratee ? iteratee(value, i, array) : value;
      if (isSorted && !iteratee) {
        if (!i || seen !== computed) result.push(value);
        seen = computed;
      } else if (iteratee) {
        if (!_.contains(seen, computed)) {
          seen.push(computed);
          result.push(value);
        }
      } else if (!_.contains(result, value)) {
        result.push(value);
      }
    }
    return result;
  };

  // Produce an array that contains the union: each distinct element from all of
  // the passed-in arrays.
  _.union = restArguments(function(arrays) {
    return _.uniq(flatten(arrays, true, true));
  });

  // Produce an array that contains every item shared between all the
  // passed-in arrays.
  _.intersection = function(array) {
    var result = [];
    var argsLength = arguments.length;
    for (var i = 0, length = getLength(array); i < length; i++) {
      var item = array[i];
      if (_.contains(result, item)) continue;
      var j;
      for (j = 1; j < argsLength; j++) {
        if (!_.contains(arguments[j], item)) break;
      }
      if (j === argsLength) result.push(item);
    }
    return result;
  };

  // Take the difference between one array and a number of other arrays.
  // Only the elements present in just the first array will remain.
  _.difference = restArguments(function(array, rest) {
    rest = flatten(rest, true, true);
    return _.filter(array, function(value){
      return !_.contains(rest, value);
    });
  });

  // Complement of _.zip. Unzip accepts an array of arrays and groups
  // each array's elements on shared indices.
  _.unzip = function(array) {
    var length = array && _.max(array, getLength).length || 0;
    var result = Array(length);

    for (var index = 0; index < length; index++) {
      result[index] = _.pluck(array, index);
    }
    return result;
  };

  // Zip together multiple lists into a single array -- elements that share
  // an index go together.
  _.zip = restArguments(_.unzip);

  // Converts lists into objects. Pass either a single array of `[key, value]`
  // pairs, or two parallel arrays of the same length -- one of keys, and one of
  // the corresponding values. Passing by pairs is the reverse of _.pairs.
  _.object = function(list, values) {
    var result = {};
    for (var i = 0, length = getLength(list); i < length; i++) {
      if (values) {
        result[list[i]] = values[i];
      } else {
        result[list[i][0]] = list[i][1];
      }
    }
    return result;
  };

  // Generator function to create the findIndex and findLastIndex functions.
  var createPredicateIndexFinder = function(dir) {
    return function(array, predicate, context) {
      predicate = cb(predicate, context);
      var length = getLength(array);
      var index = dir > 0 ? 0 : length - 1;
      for (; index >= 0 && index < length; index += dir) {
        if (predicate(array[index], index, array)) return index;
      }
      return -1;
    };
  };

  // Returns the first index on an array-like that passes a predicate test.
  _.findIndex = createPredicateIndexFinder(1);
  _.findLastIndex = createPredicateIndexFinder(-1);

  // Use a comparator function to figure out the smallest index at which
  // an object should be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iteratee, context) {
    iteratee = cb(iteratee, context, 1);
    var value = iteratee(obj);
    var low = 0, high = getLength(array);
    while (low < high) {
      var mid = Math.floor((low + high) / 2);
      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
    }
    return low;
  };

  // Generator function to create the indexOf and lastIndexOf functions.
  var createIndexFinder = function(dir, predicateFind, sortedIndex) {
    return function(array, item, idx) {
      var i = 0, length = getLength(array);
      if (typeof idx == 'number') {
        if (dir > 0) {
          i = idx >= 0 ? idx : Math.max(idx + length, i);
        } else {
          length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
        }
      } else if (sortedIndex && idx && length) {
        idx = sortedIndex(array, item);
        return array[idx] === item ? idx : -1;
      }
      if (item !== item) {
        idx = predicateFind(slice.call(array, i, length), _.isNaN);
        return idx >= 0 ? idx + i : -1;
      }
      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
        if (array[idx] === item) return idx;
      }
      return -1;
    };
  };

  // Return the position of the first occurrence of an item in an array,
  // or -1 if the item is not included in the array.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (stop == null) {
      stop = start || 0;
      start = 0;
    }
    if (!step) {
      step = stop < start ? -1 : 1;
    }

    var length = Math.max(Math.ceil((stop - start) / step), 0);
    var range = Array(length);

    for (var idx = 0; idx < length; idx++, start += step) {
      range[idx] = start;
    }

    return range;
  };

  // Chunk a single array into multiple arrays, each containing `count` or fewer
  // items.
  _.chunk = function(array, count) {
    if (count == null || count < 1) return [];
    var result = [];
    var i = 0, length = array.length;
    while (i < length) {
      result.push(slice.call(array, i, i += count));
    }
    return result;
  };

  // Function (ahem) Functions
  // ------------------

  // Determines whether to execute a function as a constructor
  // or a normal function with the provided arguments.
  var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
    if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
    var self = baseCreate(sourceFunc.prototype);
    var result = sourceFunc.apply(self, args);
    if (_.isObject(result)) return result;
    return self;
  };

  // Create a function bound to a given object (assigning `this`, and arguments,
  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
  // available.
  _.bind = restArguments(function(func, context, args) {
    if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
    var bound = restArguments(function(callArgs) {
      return executeBound(func, bound, context, this, args.concat(callArgs));
    });
    return bound;
  });

  // Partially apply a function by creating a version that has had some of its
  // arguments pre-filled, without changing its dynamic `this` context. _ acts
  // as a placeholder by default, allowing any combination of arguments to be
  // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument.
  _.partial = restArguments(function(func, boundArgs) {
    var placeholder = _.partial.placeholder;
    var bound = function() {
      var position = 0, length = boundArgs.length;
      var args = Array(length);
      for (var i = 0; i < length; i++) {
        args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i];
      }
      while (position < arguments.length) args.push(arguments[position++]);
      return executeBound(func, bound, this, this, args);
    };
    return bound;
  });

  _.partial.placeholder = _;

  // Bind a number of an object's methods to that object. Remaining arguments
  // are the method names to be bound. Useful for ensuring that all callbacks
  // defined on an object belong to it.
  _.bindAll = restArguments(function(obj, keys) {
    keys = flatten(keys, false, false);
    var index = keys.length;
    if (index < 1) throw new Error('bindAll must be passed function names');
    while (index--) {
      var key = keys[index];
      obj[key] = _.bind(obj[key], obj);
    }
  });

  // Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memoize = function(key) {
      var cache = memoize.cache;
      var address = '' + (hasher ? hasher.apply(this, arguments) : key);
      if (!has(cache, address)) cache[address] = func.apply(this, arguments);
      return cache[address];
    };
    memoize.cache = {};
    return memoize;
  };

  // Delays a function for the given number of milliseconds, and then calls
  // it with the arguments supplied.
  _.delay = restArguments(function(func, wait, args) {
    return setTimeout(function() {
      return func.apply(null, args);
    }, wait);
  });

  // Defers a function, scheduling it to run after the current call stack has
  // cleared.
  _.defer = _.partial(_.delay, _, 1);

  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time. Normally, the throttled function will run
  // as much as it can, without ever going more than once per `wait` duration;
  // but if you'd like to disable the execution on the leading edge, pass
  // `{leading: false}`. To disable execution on the trailing edge, ditto.
  _.throttle = function(func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};

    var later = function() {
      previous = options.leading === false ? 0 : _.now();
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    };

    var throttled = function() {
      var now = _.now();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };

    throttled.cancel = function() {
      clearTimeout(timeout);
      previous = 0;
      timeout = context = args = null;
    };

    return throttled;
  };

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  _.debounce = function(func, wait, immediate) {
    var timeout, result;

    var later = function(context, args) {
      timeout = null;
      if (args) result = func.apply(context, args);
    };

    var debounced = restArguments(function(args) {
      if (timeout) clearTimeout(timeout);
      if (immediate) {
        var callNow = !timeout;
        timeout = setTimeout(later, wait);
        if (callNow) result = func.apply(this, args);
      } else {
        timeout = _.delay(later, wait, this, args);
      }

      return result;
    });

    debounced.cancel = function() {
      clearTimeout(timeout);
      timeout = null;
    };

    return debounced;
  };

  // Returns the first function passed as an argument to the second,
  // allowing you to adjust arguments, run code before and after, and
  // conditionally execute the original function.
  _.wrap = function(func, wrapper) {
    return _.partial(wrapper, func);
  };

  // Returns a negated version of the passed-in predicate.
  _.negate = function(predicate) {
    return function() {
      return !predicate.apply(this, arguments);
    };
  };

  // Returns a function that is the composition of a list of functions, each
  // consuming the return value of the function that follows.
  _.compose = function() {
    var args = arguments;
    var start = args.length - 1;
    return function() {
      var i = start;
      var result = args[start].apply(this, arguments);
      while (i--) result = args[i].call(this, result);
      return result;
    };
  };

  // Returns a function that will only be executed on and after the Nth call.
  _.after = function(times, func) {
    return function() {
      if (--times < 1) {
        return func.apply(this, arguments);
      }
    };
  };

  // Returns a function that will only be executed up to (but not including) the Nth call.
  _.before = function(times, func) {
    var memo;
    return function() {
      if (--times > 0) {
        memo = func.apply(this, arguments);
      }
      if (times <= 1) func = null;
      return memo;
    };
  };

  // Returns a function that will be executed at most one time, no matter how
  // often you call it. Useful for lazy initialization.
  _.once = _.partial(_.before, 2);

  _.restArguments = restArguments;

  // Object Functions
  // ----------------

  // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
  var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
  var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
    'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];

  var collectNonEnumProps = function(obj, keys) {
    var nonEnumIdx = nonEnumerableProps.length;
    var constructor = obj.constructor;
    var proto = _.isFunction(constructor) && constructor.prototype || ObjProto;

    // Constructor is a special case.
    var prop = 'constructor';
    if (has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);

    while (nonEnumIdx--) {
      prop = nonEnumerableProps[nonEnumIdx];
      if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
        keys.push(prop);
      }
    }
  };

  // Retrieve the names of an object's own properties.
  // Delegates to **ECMAScript 5**'s native `Object.keys`.
  _.keys = function(obj) {
    if (!_.isObject(obj)) return [];
    if (nativeKeys) return nativeKeys(obj);
    var keys = [];
    for (var key in obj) if (has(obj, key)) keys.push(key);
    // Ahem, IE < 9.
    if (hasEnumBug) collectNonEnumProps(obj, keys);
    return keys;
  };

  // Retrieve all the property names of an object.
  _.allKeys = function(obj) {
    if (!_.isObject(obj)) return [];
    var keys = [];
    for (var key in obj) keys.push(key);
    // Ahem, IE < 9.
    if (hasEnumBug) collectNonEnumProps(obj, keys);
    return keys;
  };

  // Retrieve the values of an object's properties.
  _.values = function(obj) {
    var keys = _.keys(obj);
    var length = keys.length;
    var values = Array(length);
    for (var i = 0; i < length; i++) {
      values[i] = obj[keys[i]];
    }
    return values;
  };

  // Returns the results of applying the iteratee to each element of the object.
  // In contrast to _.map it returns an object.
  _.mapObject = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    var keys = _.keys(obj),
        length = keys.length,
        results = {};
    for (var index = 0; index < length; index++) {
      var currentKey = keys[index];
      results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
    }
    return results;
  };

  // Convert an object into a list of `[key, value]` pairs.
  // The opposite of _.object.
  _.pairs = function(obj) {
    var keys = _.keys(obj);
    var length = keys.length;
    var pairs = Array(length);
    for (var i = 0; i < length; i++) {
      pairs[i] = [keys[i], obj[keys[i]]];
    }
    return pairs;
  };

  // Invert the keys and values of an object. The values must be serializable.
  _.invert = function(obj) {
    var result = {};
    var keys = _.keys(obj);
    for (var i = 0, length = keys.length; i < length; i++) {
      result[obj[keys[i]]] = keys[i];
    }
    return result;
  };

  // Return a sorted list of the function names available on the object.
  // Aliased as `methods`.
  _.functions = _.methods = function(obj) {
    var names = [];
    for (var key in obj) {
      if (_.isFunction(obj[key])) names.push(key);
    }
    return names.sort();
  };

  // An internal function for creating assigner functions.
  var createAssigner = function(keysFunc, defaults) {
    return function(obj) {
      var length = arguments.length;
      if (defaults) obj = Object(obj);
      if (length < 2 || obj == null) return obj;
      for (var index = 1; index < length; index++) {
        var source = arguments[index],
            keys = keysFunc(source),
            l = keys.length;
        for (var i = 0; i < l; i++) {
          var key = keys[i];
          if (!defaults || obj[key] === void 0) obj[key] = source[key];
        }
      }
      return obj;
    };
  };

  // Extend a given object with all the properties in passed-in object(s).
  _.extend = createAssigner(_.allKeys);

  // Assigns a given object with all the own properties in the passed-in object(s).
  // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
  _.extendOwn = _.assign = createAssigner(_.keys);

  // Returns the first key on an object that passes a predicate test.
  _.findKey = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = _.keys(obj), key;
    for (var i = 0, length = keys.length; i < length; i++) {
      key = keys[i];
      if (predicate(obj[key], key, obj)) return key;
    }
  };

  // Internal pick helper function to determine if `obj` has key `key`.
  var keyInObj = function(value, key, obj) {
    return key in obj;
  };

  // Return a copy of the object only containing the whitelisted properties.
  _.pick = restArguments(function(obj, keys) {
    var result = {}, iteratee = keys[0];
    if (obj == null) return result;
    if (_.isFunction(iteratee)) {
      if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]);
      keys = _.allKeys(obj);
    } else {
      iteratee = keyInObj;
      keys = flatten(keys, false, false);
      obj = Object(obj);
    }
    for (var i = 0, length = keys.length; i < length; i++) {
      var key = keys[i];
      var value = obj[key];
      if (iteratee(value, key, obj)) result[key] = value;
    }
    return result;
  });

  // Return a copy of the object without the blacklisted properties.
  _.omit = restArguments(function(obj, keys) {
    var iteratee = keys[0], context;
    if (_.isFunction(iteratee)) {
      iteratee = _.negate(iteratee);
      if (keys.length > 1) context = keys[1];
    } else {
      keys = _.map(flatten(keys, false, false), String);
      iteratee = function(value, key) {
        return !_.contains(keys, key);
      };
    }
    return _.pick(obj, iteratee, context);
  });

  // Fill in a given object with default properties.
  _.defaults = createAssigner(_.allKeys, true);

  // Creates an object that inherits from the given prototype object.
  // If additional properties are provided then they will be added to the
  // created object.
  _.create = function(prototype, props) {
    var result = baseCreate(prototype);
    if (props) _.extendOwn(result, props);
    return result;
  };

  // Create a (shallow-cloned) duplicate of an object.
  _.clone = function(obj) {
    if (!_.isObject(obj)) return obj;
    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  };

  // Invokes interceptor with the obj, and then returns obj.
  // The primary purpose of this method is to "tap into" a method chain, in
  // order to perform operations on intermediate results within the chain.
  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

  // Returns whether an object has a given set of `key:value` pairs.
  _.isMatch = function(object, attrs) {
    var keys = _.keys(attrs), length = keys.length;
    if (object == null) return !length;
    var obj = Object(object);
    for (var i = 0; i < length; i++) {
      var key = keys[i];
      if (attrs[key] !== obj[key] || !(key in obj)) return false;
    }
    return true;
  };


  // Internal recursive comparison function for `isEqual`.
  var eq, deepEq;
  eq = function(a, b, aStack, bStack) {
    // Identical objects are equal. `0 === -0`, but they aren't identical.
    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
    if (a === b) return a !== 0 || 1 / a === 1 / b;
    // `null` or `undefined` only equal to itself (strict comparison).
    if (a == null || b == null) return false;
    // `NaN`s are equivalent, but non-reflexive.
    if (a !== a) return b !== b;
    // Exhaust primitive checks
    var type = typeof a;
    if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
    return deepEq(a, b, aStack, bStack);
  };

  // Internal recursive comparison function for `isEqual`.
  deepEq = function(a, b, aStack, bStack) {
    // Unwrap any wrapped objects.
    if (a instanceof _) a = a._wrapped;
    if (b instanceof _) b = b._wrapped;
    // Compare `[[Class]]` names.
    var className = toString.call(a);
    if (className !== toString.call(b)) return false;
    switch (className) {
      // Strings, numbers, regular expressions, dates, and booleans are compared by value.
      case '[object RegExp]':
      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
      case '[object String]':
        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
        // equivalent to `new String("5")`.
        return '' + a === '' + b;
      case '[object Number]':
        // `NaN`s are equivalent, but non-reflexive.
        // Object(NaN) is equivalent to NaN.
        if (+a !== +a) return +b !== +b;
        // An `egal` comparison is performed for other numeric values.
        return +a === 0 ? 1 / +a === 1 / b : +a === +b;
      case '[object Date]':
      case '[object Boolean]':
        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
        // millisecond representations. Note that invalid dates with millisecond representations
        // of `NaN` are not equivalent.
        return +a === +b;
      case '[object Symbol]':
        return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
    }

    var areArrays = className === '[object Array]';
    if (!areArrays) {
      if (typeof a != 'object' || typeof b != 'object') return false;

      // Objects with different constructors are not equivalent, but `Object`s or `Array`s
      // from different frames are.
      var aCtor = a.constructor, bCtor = b.constructor;
      if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
                               _.isFunction(bCtor) && bCtor instanceof bCtor)
                          && ('constructor' in a && 'constructor' in b)) {
        return false;
      }
    }
    // Assume equality for cyclic structures. The algorithm for detecting cyclic
    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.

    // Initializing stack of traversed objects.
    // It's done here since we only need them for objects and arrays comparison.
    aStack = aStack || [];
    bStack = bStack || [];
    var length = aStack.length;
    while (length--) {
      // Linear search. Performance is inversely proportional to the number of
      // unique nested structures.
      if (aStack[length] === a) return bStack[length] === b;
    }

    // Add the first object to the stack of traversed objects.
    aStack.push(a);
    bStack.push(b);

    // Recursively compare objects and arrays.
    if (areArrays) {
      // Compare array lengths to determine if a deep comparison is necessary.
      length = a.length;
      if (length !== b.length) return false;
      // Deep compare the contents, ignoring non-numeric properties.
      while (length--) {
        if (!eq(a[length], b[length], aStack, bStack)) return false;
      }
    } else {
      // Deep compare objects.
      var keys = _.keys(a), key;
      length = keys.length;
      // Ensure that both objects contain the same number of properties before comparing deep equality.
      if (_.keys(b).length !== length) return false;
      while (length--) {
        // Deep compare each member
        key = keys[length];
        if (!(has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
      }
    }
    // Remove the first object from the stack of traversed objects.
    aStack.pop();
    bStack.pop();
    return true;
  };

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    return eq(a, b);
  };

  // Is a given array, string, or object empty?
  // An "empty" object has no enumerable own-properties.
  _.isEmpty = function(obj) {
    if (obj == null) return true;
    if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
    return _.keys(obj).length === 0;
  };

  // Is a given value a DOM element?
  _.isElement = function(obj) {
    return !!(obj && obj.nodeType === 1);
  };

  // Is a given value an array?
  // Delegates to ECMA5's native Array.isArray
  _.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) === '[object Array]';
  };

  // Is a given variable an object?
  _.isObject = function(obj) {
    var type = typeof obj;
    return type === 'function' || type === 'object' && !!obj;
  };

  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError, isMap, isWeakMap, isSet, isWeakSet.
  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error', 'Symbol', 'Map', 'WeakMap', 'Set', 'WeakSet'], function(name) {
    _['is' + name] = function(obj) {
      return toString.call(obj) === '[object ' + name + ']';
    };
  });

  // Define a fallback version of the method in browsers (ahem, IE < 9), where
  // there isn't any inspectable "Arguments" type.
  if (!_.isArguments(arguments)) {
    _.isArguments = function(obj) {
      return has(obj, 'callee');
    };
  }

  // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
  // IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).
  var nodelist = root.document && root.document.childNodes;
  if ( true && typeof Int8Array != 'object' && typeof nodelist != 'function') {
    _.isFunction = function(obj) {
      return typeof obj == 'function' || false;
    };
  }

  // Is a given object a finite number?
  _.isFinite = function(obj) {
    return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj));
  };

  // Is the given value `NaN`?
  _.isNaN = function(obj) {
    return _.isNumber(obj) && isNaN(obj);
  };

  // Is a given value a boolean?
  _.isBoolean = function(obj) {
    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
  };

  // Is a given value equal to null?
  _.isNull = function(obj) {
    return obj === null;
  };

  // Is a given variable undefined?
  _.isUndefined = function(obj) {
    return obj === void 0;
  };

  // Shortcut function for checking if an object has a given property directly
  // on itself (in other words, not on a prototype).
  _.has = function(obj, path) {
    if (!_.isArray(path)) {
      return has(obj, path);
    }
    var length = path.length;
    for (var i = 0; i < length; i++) {
      var key = path[i];
      if (obj == null || !hasOwnProperty.call(obj, key)) {
        return false;
      }
      obj = obj[key];
    }
    return !!length;
  };

  // Utility Functions
  // -----------------

  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  // previous owner. Returns a reference to the Underscore object.
  _.noConflict = function() {
    root._ = previousUnderscore;
    return this;
  };

  // Keep the identity function around for default iteratees.
  _.identity = function(value) {
    return value;
  };

  // Predicate-generating functions. Often useful outside of Underscore.
  _.constant = function(value) {
    return function() {
      return value;
    };
  };

  _.noop = function(){};

  // Creates a function that, when passed an object, will traverse that object’s
  // properties down the given `path`, specified as an array of keys or indexes.
  _.property = function(path) {
    if (!_.isArray(path)) {
      return shallowProperty(path);
    }
    return function(obj) {
      return deepGet(obj, path);
    };
  };

  // Generates a function for a given object that returns a given property.
  _.propertyOf = function(obj) {
    if (obj == null) {
      return function(){};
    }
    return function(path) {
      return !_.isArray(path) ? obj[path] : deepGet(obj, path);
    };
  };

  // Returns a predicate for checking whether an object has a given set of
  // `key:value` pairs.
  _.matcher = _.matches = function(attrs) {
    attrs = _.extendOwn({}, attrs);
    return function(obj) {
      return _.isMatch(obj, attrs);
    };
  };

  // Run a function **n** times.
  _.times = function(n, iteratee, context) {
    var accum = Array(Math.max(0, n));
    iteratee = optimizeCb(iteratee, context, 1);
    for (var i = 0; i < n; i++) accum[i] = iteratee(i);
    return accum;
  };

  // Return a random integer between min and max (inclusive).
  _.random = function(min, max) {
    if (max == null) {
      max = min;
      min = 0;
    }
    return min + Math.floor(Math.random() * (max - min + 1));
  };

  // A (possibly faster) way to get the current timestamp as an integer.
  _.now = Date.now || function() {
    return new Date().getTime();
  };

  // List of HTML entities for escaping.
  var escapeMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
  };
  var unescapeMap = _.invert(escapeMap);

  // Functions for escaping and unescaping strings to/from HTML interpolation.
  var createEscaper = function(map) {
    var escaper = function(match) {
      return map[match];
    };
    // Regexes for identifying a key that needs to be escaped.
    var source = '(?:' + _.keys(map).join('|') + ')';
    var testRegexp = RegExp(source);
    var replaceRegexp = RegExp(source, 'g');
    return function(string) {
      string = string == null ? '' : '' + string;
      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
    };
  };
  _.escape = createEscaper(escapeMap);
  _.unescape = createEscaper(unescapeMap);

  // Traverses the children of `obj` along `path`. If a child is a function, it
  // is invoked with its parent as context. Returns the value of the final
  // child, or `fallback` if any child is undefined.
  _.result = function(obj, path, fallback) {
    if (!_.isArray(path)) path = [path];
    var length = path.length;
    if (!length) {
      return _.isFunction(fallback) ? fallback.call(obj) : fallback;
    }
    for (var i = 0; i < length; i++) {
      var prop = obj == null ? void 0 : obj[path[i]];
      if (prop === void 0) {
        prop = fallback;
        i = length; // Ensure we don't continue iterating.
      }
      obj = _.isFunction(prop) ? prop.call(obj) : prop;
    }
    return obj;
  };

  // Generate a unique integer id (unique within the entire client session).
  // Useful for temporary DOM ids.
  var idCounter = 0;
  _.uniqueId = function(prefix) {
    var id = ++idCounter + '';
    return prefix ? prefix + id : id;
  };

  // By default, Underscore uses ERB-style template delimiters, change the
  // following template settings to use alternative delimiters.
  _.templateSettings = {
    evaluate: /<%([\s\S]+?)%>/g,
    interpolate: /<%=([\s\S]+?)%>/g,
    escape: /<%-([\s\S]+?)%>/g
  };

  // When customizing `templateSettings`, if you don't want to define an
  // interpolation, evaluation or escaping regex, we need one that is
  // guaranteed not to match.
  var noMatch = /(.)^/;

  // Certain characters need to be escaped so that they can be put into a
  // string literal.
  var escapes = {
    "'": "'",
    '\\': '\\',
    '\r': 'r',
    '\n': 'n',
    '\u2028': 'u2028',
    '\u2029': 'u2029'
  };

  var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;

  var escapeChar = function(match) {
    return '\\' + escapes[match];
  };

  // JavaScript micro-templating, similar to John Resig's implementation.
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
  // and correctly escapes quotes within interpolated code.
  // NB: `oldSettings` only exists for backwards compatibility.
  _.template = function(text, settings, oldSettings) {
    if (!settings && oldSettings) settings = oldSettings;
    settings = _.defaults({}, settings, _.templateSettings);

    // Combine delimiters into one regular expression via alternation.
    var matcher = RegExp([
      (settings.escape || noMatch).source,
      (settings.interpolate || noMatch).source,
      (settings.evaluate || noMatch).source
    ].join('|') + '|$', 'g');

    // Compile the template source, escaping string literals appropriately.
    var index = 0;
    var source = "__p+='";
    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
      source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
      index = offset + match.length;

      if (escape) {
        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
      } else if (interpolate) {
        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
      } else if (evaluate) {
        source += "';\n" + evaluate + "\n__p+='";
      }

      // Adobe VMs need the match returned to produce the correct offset.
      return match;
    });
    source += "';\n";

    // If a variable is not specified, place data values in local scope.
    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

    source = "var __t,__p='',__j=Array.prototype.join," +
      "print=function(){__p+=__j.call(arguments,'');};\n" +
      source + 'return __p;\n';

    var render;
    try {
      render = new Function(settings.variable || 'obj', '_', source);
    } catch (e) {
      e.source = source;
      throw e;
    }

    var template = function(data) {
      return render.call(this, data, _);
    };

    // Provide the compiled source as a convenience for precompilation.
    var argument = settings.variable || 'obj';
    template.source = 'function(' + argument + '){\n' + source + '}';

    return template;
  };

  // Add a "chain" function. Start chaining a wrapped Underscore object.
  _.chain = function(obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
  };

  // OOP
  // ---------------
  // If Underscore is called as a function, it returns a wrapped object that
  // can be used OO-style. This wrapper holds altered versions of all the
  // underscore functions. Wrapped objects may be chained.

  // Helper function to continue chaining intermediate results.
  var chainResult = function(instance, obj) {
    return instance._chain ? _(obj).chain() : obj;
  };

  // Add your own custom functions to the Underscore object.
  _.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
      var func = _[name] = obj[name];
      _.prototype[name] = function() {
        var args = [this._wrapped];
        push.apply(args, arguments);
        return chainResult(this, func.apply(_, args));
      };
    });
    return _;
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

  // Add all mutator Array functions to the wrapper.
  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      var obj = this._wrapped;
      method.apply(obj, arguments);
      if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
      return chainResult(this, obj);
    };
  });

  // Add all accessor Array functions to the wrapper.
  _.each(['concat', 'join', 'slice'], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      return chainResult(this, method.apply(this._wrapped, arguments));
    };
  });

  // Extracts the result from a wrapped and chained object.
  _.prototype.value = function() {
    return this._wrapped;
  };

  // Provide unwrapping proxy for some methods used in engine operations
  // such as arithmetic and JSON stringification.
  _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;

  _.prototype.toString = function() {
    return String(this._wrapped);
  };

  // AMD registration happens at the end for compatibility with AMD loaders
  // that may not enforce next-turn semantics on modules. Even though general
  // practice for AMD registration is to be anonymous, underscore registers
  // as a named module because, like jQuery, it is a base library that is
  // popular enough to be bundled in a third party lib, but not be part of
  // an AMD load request. Those cases could generate an error when an
  // anonymous define() is called outside of a loader request.
  if (true) {
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {
      return _;
    }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  }
}());

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(48), __webpack_require__(212)(module)))module.exports = function(module) {
	if (!module.webpackPolyfill) {
		module.deprecate = function() {};
		module.paths = [];
		// module.parent = undefined by default
		if (!module.children) module.children = [];
		Object.defineProperty(module, "loaded", {
			enumerable: true,
			get: function() {
				return module.l;
			}
		});
		Object.defineProperty(module, "id", {
			enumerable: true,
			get: function() {
				return module.i;
			}
		});
		module.webpackPolyfill = 1;
	}
	return module;
};
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// MarionetteJS (Backbone.Marionette)
// ----------------------------------
// v2.4.7
//
// Copyright (c)2016 Derick Bailey, Muted Solutions, LLC.
// Distributed under MIT license
//
// http://marionettejs.com


/*!
 * Includes BabySitter
 * https://github.com/marionettejs/backbone.babysitter/
 *
 * Includes Wreqr
 * https://github.com/marionettejs/backbone.wreqr/
 */


(function(root, factory) {

  /* istanbul ignore next */
  if (true) {
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(6), __webpack_require__(5)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(Backbone, _) {
      return (root.Marionette = root.Mn = factory(root, Backbone, _));
    }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  } else { var _, Backbone; }

}(this, function(root, Backbone, _) {
  'use strict';

  /* istanbul ignore next */
  // Backbone.BabySitter
  // -------------------
  // v0.1.11
  //
  // Copyright (c)2016 Derick Bailey, Muted Solutions, LLC.
  // Distributed under MIT license
  //
  // http://github.com/marionettejs/backbone.babysitter
  (function(Backbone, _) {
    "use strict";
    var previousChildViewContainer = Backbone.ChildViewContainer;
    // BabySitter.ChildViewContainer
    // -----------------------------
    //
    // Provide a container to store, retrieve and
    // shut down child views.
    Backbone.ChildViewContainer = function(Backbone, _) {
      // Container Constructor
      // ---------------------
      var Container = function(views) {
        this._views = {};
        this._indexByModel = {};
        this._indexByCustom = {};
        this._updateLength();
        _.each(views, this.add, this);
      };
      // Container Methods
      // -----------------
      _.extend(Container.prototype, {
        // Add a view to this container. Stores the view
        // by `cid` and makes it searchable by the model
        // cid (and model itself). Optionally specify
        // a custom key to store an retrieve the view.
        add: function(view, customIndex) {
          var viewCid = view.cid;
          // store the view
          this._views[viewCid] = view;
          // index it by model
          if (view.model) {
            this._indexByModel[view.model.cid] = viewCid;
          }
          // index by custom
          if (customIndex) {
            this._indexByCustom[customIndex] = viewCid;
          }
          this._updateLength();
          return this;
        },
        // Find a view by the model that was attached to
        // it. Uses the model's `cid` to find it.
        findByModel: function(model) {
          return this.findByModelCid(model.cid);
        },
        // Find a view by the `cid` of the model that was attached to
        // it. Uses the model's `cid` to find the view `cid` and
        // retrieve the view using it.
        findByModelCid: function(modelCid) {
          var viewCid = this._indexByModel[modelCid];
          return this.findByCid(viewCid);
        },
        // Find a view by a custom indexer.
        findByCustom: function(index) {
          var viewCid = this._indexByCustom[index];
          return this.findByCid(viewCid);
        },
        // Find by index. This is not guaranteed to be a
        // stable index.
        findByIndex: function(index) {
          return _.values(this._views)[index];
        },
        // retrieve a view by its `cid` directly
        findByCid: function(cid) {
          return this._views[cid];
        },
        // Remove a view
        remove: function(view) {
          var viewCid = view.cid;
          // delete model index
          if (view.model) {
            delete this._indexByModel[view.model.cid];
          }
          // delete custom index
          _.any(this._indexByCustom, function(cid, key) {
            if (cid === viewCid) {
              delete this._indexByCustom[key];
              return true;
            }
          }, this);
          // remove the view from the container
          delete this._views[viewCid];
          // update the length
          this._updateLength();
          return this;
        },
        // Call a method on every view in the container,
        // passing parameters to the call method one at a
        // time, like `function.call`.
        call: function(method) {
          this.apply(method, _.tail(arguments));
        },
        // Apply a method on every view in the container,
        // passing parameters to the call method one at a
        // time, like `function.apply`.
        apply: function(method, args) {
          _.each(this._views, function(view) {
            if (_.isFunction(view[method])) {
              view[method].apply(view, args || []);
            }
          });
        },
        // Update the `.length` attribute on this container
        _updateLength: function() {
          this.length = _.size(this._views);
        }
      });
      // Borrowing this code from Backbone.Collection:
      // http://backbonejs.org/docs/backbone.html#section-106
      //
      // Mix in methods from Underscore, for iteration, and other
      // collection related features.
      var methods = [ "forEach", "each", "map", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "toArray", "first", "initial", "rest", "last", "without", "isEmpty", "pluck", "reduce" ];
      _.each(methods, function(method) {
        Container.prototype[method] = function() {
          var views = _.values(this._views);
          var args = [ views ].concat(_.toArray(arguments));
          return _[method].apply(_, args);
        };
      });
      // return the public API
      return Container;
    }(Backbone, _);
    Backbone.ChildViewContainer.VERSION = "0.1.11";
    Backbone.ChildViewContainer.noConflict = function() {
      Backbone.ChildViewContainer = previousChildViewContainer;
      return this;
    };
    return Backbone.ChildViewContainer;
  })(Backbone, _);

  /* istanbul ignore next */
  // Backbone.Wreqr (Backbone.Marionette)
  // ----------------------------------
  // v1.3.6
  //
  // Copyright (c)2016 Derick Bailey, Muted Solutions, LLC.
  // Distributed under MIT license
  //
  // http://github.com/marionettejs/backbone.wreqr
  (function(Backbone, _) {
    "use strict";
    var previousWreqr = Backbone.Wreqr;
    var Wreqr = Backbone.Wreqr = {};
    Backbone.Wreqr.VERSION = "1.3.6";
    Backbone.Wreqr.noConflict = function() {
      Backbone.Wreqr = previousWreqr;
      return this;
    };
    // Handlers
    // --------
    // A registry of functions to call, given a name
    Wreqr.Handlers = function(Backbone, _) {
      "use strict";
      // Constructor
      // -----------
      var Handlers = function(options) {
        this.options = options;
        this._wreqrHandlers = {};
        if (_.isFunction(this.initialize)) {
          this.initialize(options);
        }
      };
      Handlers.extend = Backbone.Model.extend;
      // Instance Members
      // ----------------
      _.extend(Handlers.prototype, Backbone.Events, {
        // Add multiple handlers using an object literal configuration
        setHandlers: function(handlers) {
          _.each(handlers, function(handler, name) {
            var context = null;
            if (_.isObject(handler) && !_.isFunction(handler)) {
              context = handler.context;
              handler = handler.callback;
            }
            this.setHandler(name, handler, context);
          }, this);
        },
        // Add a handler for the given name, with an
        // optional context to run the handler within
        setHandler: function(name, handler, context) {
          var config = {
            callback: handler,
            context: context
          };
          this._wreqrHandlers[name] = config;
          this.trigger("handler:add", name, handler, context);
        },
        // Determine whether or not a handler is registered
        hasHandler: function(name) {
          return !!this._wreqrHandlers[name];
        },
        // Get the currently registered handler for
        // the specified name. Throws an exception if
        // no handler is found.
        getHandler: function(name) {
          var config = this._wreqrHandlers[name];
          if (!config) {
            return;
          }
          return function() {
            return config.callback.apply(config.context, arguments);
          };
        },
        // Remove a handler for the specified name
        removeHandler: function(name) {
          delete this._wreqrHandlers[name];
        },
        // Remove all handlers from this registry
        removeAllHandlers: function() {
          this._wreqrHandlers = {};
        }
      });
      return Handlers;
    }(Backbone, _);
    // Wreqr.CommandStorage
    // --------------------
    //
    // Store and retrieve commands for execution.
    Wreqr.CommandStorage = function() {
      "use strict";
      // Constructor function
      var CommandStorage = function(options) {
        this.options = options;
        this._commands = {};
        if (_.isFunction(this.initialize)) {
          this.initialize(options);
        }
      };
      // Instance methods
      _.extend(CommandStorage.prototype, Backbone.Events, {
        // Get an object literal by command name, that contains
        // the `commandName` and the `instances` of all commands
        // represented as an array of arguments to process
        getCommands: function(commandName) {
          var commands = this._commands[commandName];
          // we don't have it, so add it
          if (!commands) {
            // build the configuration
            commands = {
              command: commandName,
              instances: []
            };
            // store it
            this._commands[commandName] = commands;
          }
          return commands;
        },
        // Add a command by name, to the storage and store the
        // args for the command
        addCommand: function(commandName, args) {
          var command = this.getCommands(commandName);
          command.instances.push(args);
        },
        // Clear all commands for the given `commandName`
        clearCommands: function(commandName) {
          var command = this.getCommands(commandName);
          command.instances = [];
        }
      });
      return CommandStorage;
    }();
    // Wreqr.Commands
    // --------------
    //
    // A simple command pattern implementation. Register a command
    // handler and execute it.
    Wreqr.Commands = function(Wreqr, _) {
      "use strict";
      return Wreqr.Handlers.extend({
        // default storage type
        storageType: Wreqr.CommandStorage,
        constructor: function(options) {
          this.options = options || {};
          this._initializeStorage(this.options);
          this.on("handler:add", this._executeCommands, this);
          Wreqr.Handlers.prototype.constructor.apply(this, arguments);
        },
        // Execute a named command with the supplied args
        execute: function(name) {
          name = arguments[0];
          var args = _.rest(arguments);
          if (this.hasHandler(name)) {
            this.getHandler(name).apply(this, args);
          } else {
            this.storage.addCommand(name, args);
          }
        },
        // Internal method to handle bulk execution of stored commands
        _executeCommands: function(name, handler, context) {
          var command = this.storage.getCommands(name);
          // loop through and execute all the stored command instances
          _.each(command.instances, function(args) {
            handler.apply(context, args);
          });
          this.storage.clearCommands(name);
        },
        // Internal method to initialize storage either from the type's
        // `storageType` or the instance `options.storageType`.
        _initializeStorage: function(options) {
          var storage;
          var StorageType = options.storageType || this.storageType;
          if (_.isFunction(StorageType)) {
            storage = new StorageType();
          } else {
            storage = StorageType;
          }
          this.storage = storage;
        }
      });
    }(Wreqr, _);
    // Wreqr.RequestResponse
    // ---------------------
    //
    // A simple request/response implementation. Register a
    // request handler, and return a response from it
    Wreqr.RequestResponse = function(Wreqr, _) {
      "use strict";
      return Wreqr.Handlers.extend({
        request: function(name) {
          if (this.hasHandler(name)) {
            return this.getHandler(name).apply(this, _.rest(arguments));
          }
        }
      });
    }(Wreqr, _);
    // Event Aggregator
    // ----------------
    // A pub-sub object that can be used to decouple various parts
    // of an application through event-driven architecture.
    Wreqr.EventAggregator = function(Backbone, _) {
      "use strict";
      var EA = function() {};
      // Copy the `extend` function used by Backbone's classes
      EA.extend = Backbone.Model.extend;
      // Copy the basic Backbone.Events on to the event aggregator
      _.extend(EA.prototype, Backbone.Events);
      return EA;
    }(Backbone, _);
    // Wreqr.Channel
    // --------------
    //
    // An object that wraps the three messaging systems:
    // EventAggregator, RequestResponse, Commands
    Wreqr.Channel = function(Wreqr) {
      "use strict";
      var Channel = function(channelName) {
        this.vent = new Backbone.Wreqr.EventAggregator();
        this.reqres = new Backbone.Wreqr.RequestResponse();
        this.commands = new Backbone.Wreqr.Commands();
        this.channelName = channelName;
      };
      _.extend(Channel.prototype, {
        // Remove all handlers from the messaging systems of this channel
        reset: function() {
          this.vent.off();
          this.vent.stopListening();
          this.reqres.removeAllHandlers();
          this.commands.removeAllHandlers();
          return this;
        },
        // Connect a hash of events; one for each messaging system
        connectEvents: function(hash, context) {
          this._connect("vent", hash, context);
          return this;
        },
        connectCommands: function(hash, context) {
          this._connect("commands", hash, context);
          return this;
        },
        connectRequests: function(hash, context) {
          this._connect("reqres", hash, context);
          return this;
        },
        // Attach the handlers to a given message system `type`
        _connect: function(type, hash, context) {
          if (!hash) {
            return;
          }
          context = context || this;
          var method = type === "vent" ? "on" : "setHandler";
          _.each(hash, function(fn, eventName) {
            this[type][method](eventName, _.bind(fn, context));
          }, this);
        }
      });
      return Channel;
    }(Wreqr);
    // Wreqr.Radio
    // --------------
    //
    // An object that lets you communicate with many channels.
    Wreqr.radio = function(Wreqr, _) {
      "use strict";
      var Radio = function() {
        this._channels = {};
        this.vent = {};
        this.commands = {};
        this.reqres = {};
        this._proxyMethods();
      };
      _.extend(Radio.prototype, {
        channel: function(channelName) {
          if (!channelName) {
            throw new Error("Channel must receive a name");
          }
          return this._getChannel(channelName);
        },
        _getChannel: function(channelName) {
          var channel = this._channels[channelName];
          if (!channel) {
            channel = new Wreqr.Channel(channelName);
            this._channels[channelName] = channel;
          }
          return channel;
        },
        _proxyMethods: function() {
          _.each([ "vent", "commands", "reqres" ], function(system) {
            _.each(messageSystems[system], function(method) {
              this[system][method] = proxyMethod(this, system, method);
            }, this);
          }, this);
        }
      });
      var messageSystems = {
        vent: [ "on", "off", "trigger", "once", "stopListening", "listenTo", "listenToOnce" ],
        commands: [ "execute", "setHandler", "setHandlers", "removeHandler", "removeAllHandlers" ],
        reqres: [ "request", "setHandler", "setHandlers", "removeHandler", "removeAllHandlers" ]
      };
      var proxyMethod = function(radio, system, method) {
        return function(channelName) {
          var messageSystem = radio._getChannel(channelName)[system];
          return messageSystem[method].apply(messageSystem, _.rest(arguments));
        };
      };
      return new Radio();
    }(Wreqr, _);
    return Backbone.Wreqr;
  })(Backbone, _);

  var previousMarionette = root.Marionette;
  var previousMn = root.Mn;

  var Marionette = Backbone.Marionette = {};

  Marionette.VERSION = '2.4.7';

  Marionette.noConflict = function() {
    root.Marionette = previousMarionette;
    root.Mn = previousMn;
    return this;
  };

  Backbone.Marionette = Marionette;

  // Get the Deferred creator for later use
  Marionette.Deferred = Backbone.$.Deferred;

  /* jshint unused: false *//* global console */
  
  // Helpers
  // -------
  
  // Marionette.extend
  // -----------------
  
  // Borrow the Backbone `extend` method so we can use it as needed
  Marionette.extend = Backbone.Model.extend;
  
  // Marionette.isNodeAttached
  // -------------------------
  
  // Determine if `el` is a child of the document
  Marionette.isNodeAttached = function(el) {
    return Backbone.$.contains(document.documentElement, el);
  };
  
  // Merge `keys` from `options` onto `this`
  Marionette.mergeOptions = function(options, keys) {
    if (!options) { return; }
    _.extend(this, _.pick(options, keys));
  };
  
  // Marionette.getOption
  // --------------------
  
  // Retrieve an object, function or other value from a target
  // object or its `options`, with `options` taking precedence.
  Marionette.getOption = function(target, optionName) {
    if (!target || !optionName) { return; }
    if (target.options && (target.options[optionName] !== undefined)) {
      return target.options[optionName];
    } else {
      return target[optionName];
    }
  };
  
  // Proxy `Marionette.getOption`
  Marionette.proxyGetOption = function(optionName) {
    return Marionette.getOption(this, optionName);
  };
  
  // Similar to `_.result`, this is a simple helper
  // If a function is provided we call it with context
  // otherwise just return the value. If the value is
  // undefined return a default value
  Marionette._getValue = function(value, context, params) {
    if (_.isFunction(value)) {
      value = params ? value.apply(context, params) : value.call(context);
    }
    return value;
  };
  
  // Marionette.normalizeMethods
  // ----------------------
  
  // Pass in a mapping of events => functions or function names
  // and return a mapping of events => functions
  Marionette.normalizeMethods = function(hash) {
    return _.reduce(hash, function(normalizedHash, method, name) {
      if (!_.isFunction(method)) {
        method = this[method];
      }
      if (method) {
        normalizedHash[name] = method;
      }
      return normalizedHash;
    }, {}, this);
  };
  
  // utility method for parsing @ui. syntax strings
  // into associated selector
  Marionette.normalizeUIString = function(uiString, ui) {
    return uiString.replace(/@ui\.[a-zA-Z-_$0-9]*/g, function(r) {
      return ui[r.slice(4)];
    });
  };
  
  // allows for the use of the @ui. syntax within
  // a given key for triggers and events
  // swaps the @ui with the associated selector.
  // Returns a new, non-mutated, parsed events hash.
  Marionette.normalizeUIKeys = function(hash, ui) {
    return _.reduce(hash, function(memo, val, key) {
      var normalizedKey = Marionette.normalizeUIString(key, ui);
      memo[normalizedKey] = val;
      return memo;
    }, {});
  };
  
  // allows for the use of the @ui. syntax within
  // a given value for regions
  // swaps the @ui with the associated selector
  Marionette.normalizeUIValues = function(hash, ui, properties) {
    _.each(hash, function(val, key) {
      if (_.isString(val)) {
        hash[key] = Marionette.normalizeUIString(val, ui);
      } else if (_.isObject(val) && _.isArray(properties)) {
        _.extend(val, Marionette.normalizeUIValues(_.pick(val, properties), ui));
        /* Value is an object, and we got an array of embedded property names to normalize. */
        _.each(properties, function(property) {
          var propertyVal = val[property];
          if (_.isString(propertyVal)) {
            val[property] = Marionette.normalizeUIString(propertyVal, ui);
          }
        });
      }
    });
    return hash;
  };
  
  // Mix in methods from Underscore, for iteration, and other
  // collection related features.
  // Borrowing this code from Backbone.Collection:
  // http://backbonejs.org/docs/backbone.html#section-121
  Marionette.actAsCollection = function(object, listProperty) {
    var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
      'select', 'reject', 'every', 'all', 'some', 'any', 'include',
      'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
      'last', 'without', 'isEmpty', 'pluck'];
  
    _.each(methods, function(method) {
      object[method] = function() {
        var list = _.values(_.result(this, listProperty));
        var args = [list].concat(_.toArray(arguments));
        return _[method].apply(_, args);
      };
    });
  };
  
  var deprecate = Marionette.deprecate = function(message, test) {
    if (_.isObject(message)) {
      message = (
        message.prev + ' is going to be removed in the future. ' +
        'Please use ' + message.next + ' instead.' +
        (message.url ? ' See: ' + message.url : '')
      );
    }
  
    if ((test === undefined || !test) && !deprecate._cache[message]) {
      deprecate._warn('Deprecation warning: ' + message);
      deprecate._cache[message] = true;
    }
  };
  
  deprecate._console = typeof console !== 'undefined' ? console : {};
  deprecate._warn = function() {
    var warn = deprecate._console.warn || deprecate._console.log || function() {};
    return warn.apply(deprecate._console, arguments);
  };
  deprecate._cache = {};
  
  /* jshint maxstatements: 14, maxcomplexity: 7 */
  
  // Trigger Method
  // --------------
  
  Marionette._triggerMethod = (function() {
    // split the event name on the ":"
    var splitter = /(^|:)(\w)/gi;
  
    // take the event section ("section1:section2:section3")
    // and turn it in to uppercase name
    function getEventName(match, prefix, eventName) {
      return eventName.toUpperCase();
    }
  
    return function(context, event, args) {
      var noEventArg = arguments.length < 3;
      if (noEventArg) {
        args = event;
        event = args[0];
      }
  
      // get the method name from the event name
      var methodName = 'on' + event.replace(splitter, getEventName);
      var method = context[methodName];
      var result;
  
      // call the onMethodName if it exists
      if (_.isFunction(method)) {
        // pass all args, except the event name
        result = method.apply(context, noEventArg ? _.rest(args) : args);
      }
  
      // trigger the event, if a trigger method exists
      if (_.isFunction(context.trigger)) {
        if (noEventArg + args.length > 1) {
          context.trigger.apply(context, noEventArg ? args : [event].concat(_.drop(args, 0)));
        } else {
          context.trigger(event);
        }
      }
  
      return result;
    };
  })();
  
  // Trigger an event and/or a corresponding method name. Examples:
  //
  // `this.triggerMethod("foo")` will trigger the "foo" event and
  // call the "onFoo" method.
  //
  // `this.triggerMethod("foo:bar")` will trigger the "foo:bar" event and
  // call the "onFooBar" method.
  Marionette.triggerMethod = function(event) {
    return Marionette._triggerMethod(this, arguments);
  };
  
  // triggerMethodOn invokes triggerMethod on a specific context
  //
  // e.g. `Marionette.triggerMethodOn(view, 'show')`
  // will trigger a "show" event or invoke onShow the view.
  Marionette.triggerMethodOn = function(context) {
    var fnc = _.isFunction(context.triggerMethod) ?
                  context.triggerMethod :
                  Marionette.triggerMethod;
  
    return fnc.apply(context, _.rest(arguments));
  };
  
  // DOM Refresh
  // -----------
  
  // Monitor a view's state, and after it has been rendered and shown
  // in the DOM, trigger a "dom:refresh" event every time it is
  // re-rendered.
  
  Marionette.MonitorDOMRefresh = function(view) {
    if (view._isDomRefreshMonitored) { return; }
    view._isDomRefreshMonitored = true;
  
    // track when the view has been shown in the DOM,
    // using a Marionette.Region (or by other means of triggering "show")
    function handleShow() {
      view._isShown = true;
      triggerDOMRefresh();
    }
  
    // track when the view has been rendered
    function handleRender() {
      view._isRendered = true;
      triggerDOMRefresh();
    }
  
    // Trigger the "dom:refresh" event and corresponding "onDomRefresh" method
    function triggerDOMRefresh() {
      if (view._isShown && view._isRendered && Marionette.isNodeAttached(view.el)) {
        Marionette.triggerMethodOn(view, 'dom:refresh', view);
      }
    }
  
    view.on({
      show: handleShow,
      render: handleRender
    });
  };
  
  /* jshint maxparams: 5 */
  
  // Bind Entity Events & Unbind Entity Events
  // -----------------------------------------
  //
  // These methods are used to bind/unbind a backbone "entity" (e.g. collection/model)
  // to methods on a target object.
  //
  // The first parameter, `target`, must have the Backbone.Events module mixed in.
  //
  // The second parameter is the `entity` (Backbone.Model, Backbone.Collection or
  // any object that has Backbone.Events mixed in) to bind the events from.
  //
  // The third parameter is a hash of { "event:name": "eventHandler" }
  // configuration. Multiple handlers can be separated by a space. A
  // function can be supplied instead of a string handler name.
  
  (function(Marionette) {
    'use strict';
  
    // Bind the event to handlers specified as a string of
    // handler names on the target object
    function bindFromStrings(target, entity, evt, methods) {
      var methodNames = methods.split(/\s+/);
  
      _.each(methodNames, function(methodName) {
  
        var method = target[methodName];
        if (!method) {
          throw new Marionette.Error('Method "' + methodName +
            '" was configured as an event handler, but does not exist.');
        }
  
        target.listenTo(entity, evt, method);
      });
    }
  
    // Bind the event to a supplied callback function
    function bindToFunction(target, entity, evt, method) {
      target.listenTo(entity, evt, method);
    }
  
    // Bind the event to handlers specified as a string of
    // handler names on the target object
    function unbindFromStrings(target, entity, evt, methods) {
      var methodNames = methods.split(/\s+/);
  
      _.each(methodNames, function(methodName) {
        var method = target[methodName];
        target.stopListening(entity, evt, method);
      });
    }
  
    // Bind the event to a supplied callback function
    function unbindToFunction(target, entity, evt, method) {
      target.stopListening(entity, evt, method);
    }
  
    // generic looping function
    function iterateEvents(target, entity, bindings, functionCallback, stringCallback) {
      if (!entity || !bindings) { return; }
  
      // type-check bindings
      if (!_.isObject(bindings)) {
        throw new Marionette.Error({
          message: 'Bindings must be an object or function.',
          url: 'marionette.functions.html#marionettebindentityevents'
        });
      }
  
      // allow the bindings to be a function
      bindings = Marionette._getValue(bindings, target);
  
      // iterate the bindings and bind them
      _.each(bindings, function(methods, evt) {
  
        // allow for a function as the handler,
        // or a list of event names as a string
        if (_.isFunction(methods)) {
          functionCallback(target, entity, evt, methods);
        } else {
          stringCallback(target, entity, evt, methods);
        }
  
      });
    }
  
    // Export Public API
    Marionette.bindEntityEvents = function(target, entity, bindings) {
      iterateEvents(target, entity, bindings, bindToFunction, bindFromStrings);
    };
  
    Marionette.unbindEntityEvents = function(target, entity, bindings) {
      iterateEvents(target, entity, bindings, unbindToFunction, unbindFromStrings);
    };
  
    // Proxy `bindEntityEvents`
    Marionette.proxyBindEntityEvents = function(entity, bindings) {
      return Marionette.bindEntityEvents(this, entity, bindings);
    };
  
    // Proxy `unbindEntityEvents`
    Marionette.proxyUnbindEntityEvents = function(entity, bindings) {
      return Marionette.unbindEntityEvents(this, entity, bindings);
    };
  })(Marionette);
  

  // Error
  // -----
  
  var errorProps = ['description', 'fileName', 'lineNumber', 'name', 'message', 'number'];
  
  Marionette.Error = Marionette.extend.call(Error, {
    urlRoot: 'http://marionettejs.com/docs/v' + Marionette.VERSION + '/',
  
    constructor: function(message, options) {
      if (_.isObject(message)) {
        options = message;
        message = options.message;
      } else if (!options) {
        options = {};
      }
  
      var error = Error.call(this, message);
      _.extend(this, _.pick(error, errorProps), _.pick(options, errorProps));
  
      this.captureStackTrace();
  
      if (options.url) {
        this.url = this.urlRoot + options.url;
      }
    },
  
    captureStackTrace: function() {
      if (Error.captureStackTrace) {
        Error.captureStackTrace(this, Marionette.Error);
      }
    },
  
    toString: function() {
      return this.name + ': ' + this.message + (this.url ? ' See: ' + this.url : '');
    }
  });
  
  Marionette.Error.extend = Marionette.extend;
  
  // Callbacks
  // ---------
  
  // A simple way of managing a collection of callbacks
  // and executing them at a later point in time, using jQuery's
  // `Deferred` object.
  Marionette.Callbacks = function() {
    this._deferred = Marionette.Deferred();
    this._callbacks = [];
  };
  
  _.extend(Marionette.Callbacks.prototype, {
  
    // Add a callback to be executed. Callbacks added here are
    // guaranteed to execute, even if they are added after the
    // `run` method is called.
    add: function(callback, contextOverride) {
      var promise = _.result(this._deferred, 'promise');
  
      this._callbacks.push({cb: callback, ctx: contextOverride});
  
      promise.then(function(args) {
        if (contextOverride) { args.context = contextOverride; }
        callback.call(args.context, args.options);
      });
    },
  
    // Run all registered callbacks with the context specified.
    // Additional callbacks can be added after this has been run
    // and they will still be executed.
    run: function(options, context) {
      this._deferred.resolve({
        options: options,
        context: context
      });
    },
  
    // Resets the list of callbacks to be run, allowing the same list
    // to be run multiple times - whenever the `run` method is called.
    reset: function() {
      var callbacks = this._callbacks;
      this._deferred = Marionette.Deferred();
      this._callbacks = [];
  
      _.each(callbacks, function(cb) {
        this.add(cb.cb, cb.ctx);
      }, this);
    }
  });
  
  // Controller
  // ----------
  
  // A multi-purpose object to use as a controller for
  // modules and routers, and as a mediator for workflow
  // and coordination of other objects, views, and more.
  Marionette.Controller = function(options) {
    this.options = options || {};
  
    if (_.isFunction(this.initialize)) {
      this.initialize(this.options);
    }
  };
  
  Marionette.Controller.extend = Marionette.extend;
  
  // Controller Methods
  // --------------
  
  // Ensure it can trigger events with Backbone.Events
  _.extend(Marionette.Controller.prototype, Backbone.Events, {
    destroy: function() {
      Marionette._triggerMethod(this, 'before:destroy', arguments);
      Marionette._triggerMethod(this, 'destroy', arguments);
  
      this.stopListening();
      this.off();
      return this;
    },
  
    // import the `triggerMethod` to trigger events with corresponding
    // methods if the method exists
    triggerMethod: Marionette.triggerMethod,
  
    // A handy way to merge options onto the instance
    mergeOptions: Marionette.mergeOptions,
  
    // Proxy `getOption` to enable getting options from this or this.options by name.
    getOption: Marionette.proxyGetOption
  
  });
  
  // Object
  // ------
  
  // A Base Class that other Classes should descend from.
  // Object borrows many conventions and utilities from Backbone.
  Marionette.Object = function(options) {
    this.options = _.extend({}, _.result(this, 'options'), options);
  
    this.initialize.apply(this, arguments);
  };
  
  Marionette.Object.extend = Marionette.extend;
  
  // Object Methods
  // --------------
  
  // Ensure it can trigger events with Backbone.Events
  _.extend(Marionette.Object.prototype, Backbone.Events, {
  
    //this is a noop method intended to be overridden by classes that extend from this base
    initialize: function() {},
  
    destroy: function(options) {
      options = options || {};
  
      this.triggerMethod('before:destroy', options);
      this.triggerMethod('destroy', options);
      this.stopListening();
  
      return this;
    },
  
    // Import the `triggerMethod` to trigger events with corresponding
    // methods if the method exists
    triggerMethod: Marionette.triggerMethod,
  
    // A handy way to merge options onto the instance
    mergeOptions: Marionette.mergeOptions,
  
    // Proxy `getOption` to enable getting options from this or this.options by name.
    getOption: Marionette.proxyGetOption,
  
    // Proxy `bindEntityEvents` to enable binding view's events from another entity.
    bindEntityEvents: Marionette.proxyBindEntityEvents,
  
    // Proxy `unbindEntityEvents` to enable unbinding view's events from another entity.
    unbindEntityEvents: Marionette.proxyUnbindEntityEvents
  });
  
  /* jshint maxcomplexity: 16, maxstatements: 45, maxlen: 120 */
  
  // Region
  // ------
  
  // Manage the visual regions of your composite application. See
  // http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
  
  Marionette.Region = Marionette.Object.extend({
    constructor: function(options) {
  
      // set options temporarily so that we can get `el`.
      // options will be overriden by Object.constructor
      this.options = options || {};
      this.el = this.getOption('el');
  
      // Handle when this.el is passed in as a $ wrapped element.
      this.el = this.el instanceof Backbone.$ ? this.el[0] : this.el;
  
      if (!this.el) {
        throw new Marionette.Error({
          name: 'NoElError',
          message: 'An "el" must be specified for a region.'
        });
      }
  
      this.$el = this.getEl(this.el);
      Marionette.Object.call(this, options);
    },
  
    // Displays a backbone view instance inside of the region.
    // Handles calling the `render` method for you. Reads content
    // directly from the `el` attribute. Also calls an optional
    // `onShow` and `onDestroy` method on your view, just after showing
    // or just before destroying the view, respectively.
    // The `preventDestroy` option can be used to prevent a view from
    // the old view being destroyed on show.
    // The `forceShow` option can be used to force a view to be
    // re-rendered if it's already shown in the region.
    show: function(view, options) {
      if (!this._ensureElement()) {
        return;
      }
  
      this._ensureViewIsIntact(view);
      Marionette.MonitorDOMRefresh(view);
  
      var showOptions     = options || {};
      var isDifferentView = view !== this.currentView;
      var preventDestroy  = !!showOptions.preventDestroy;
      var forceShow       = !!showOptions.forceShow;
  
      // We are only changing the view if there is a current view to change to begin with
      var isChangingView = !!this.currentView;
  
      // Only destroy the current view if we don't want to `preventDestroy` and if
      // the view given in the first argument is different than `currentView`
      var _shouldDestroyView = isDifferentView && !preventDestroy;
  
      // Only show the view given in the first argument if it is different than
      // the current view or if we want to re-show the view. Note that if
      // `_shouldDestroyView` is true, then `_shouldShowView` is also necessarily true.
      var _shouldShowView = isDifferentView || forceShow;
  
      if (isChangingView) {
        this.triggerMethod('before:swapOut', this.currentView, this, options);
      }
  
      if (this.currentView && isDifferentView) {
        delete this.currentView._parent;
      }
  
      if (_shouldDestroyView) {
        this.empty();
  
      // A `destroy` event is attached to the clean up manually removed views.
      // We need to detach this event when a new view is going to be shown as it
      // is no longer relevant.
      } else if (isChangingView && _shouldShowView) {
        this.currentView.off('destroy', this.empty, this);
      }
  
      if (_shouldShowView) {
  
        // We need to listen for if a view is destroyed
        // in a way other than through the region.
        // If this happens we need to remove the reference
        // to the currentView since once a view has been destroyed
        // we can not reuse it.
        view.once('destroy', this.empty, this);
  
        // make this region the view's parent,
        // It's important that this parent binding happens before rendering
        // so that any events the child may trigger during render can also be
        // triggered on the child's ancestor views
        view._parent = this;
        this._renderView(view);
  
        if (isChangingView) {
          this.triggerMethod('before:swap', view, this, options);
        }
  
        this.triggerMethod('before:show', view, this, options);
        Marionette.triggerMethodOn(view, 'before:show', view, this, options);
  
        if (isChangingView) {
          this.triggerMethod('swapOut', this.currentView, this, options);
        }
  
        // An array of views that we're about to display
        var attachedRegion = Marionette.isNodeAttached(this.el);
  
        // The views that we're about to attach to the document
        // It's important that we prevent _getNestedViews from being executed unnecessarily
        // as it's a potentially-slow method
        var displayedViews = [];
  
        var attachOptions = _.extend({
          triggerBeforeAttach: this.triggerBeforeAttach,
          triggerAttach: this.triggerAttach
        }, showOptions);
  
        if (attachedRegion && attachOptions.triggerBeforeAttach) {
          displayedViews = this._displayedViews(view);
          this._triggerAttach(displayedViews, 'before:');
        }
  
        this.attachHtml(view);
        this.currentView = view;
  
        if (attachedRegion && attachOptions.triggerAttach) {
          displayedViews = this._displayedViews(view);
          this._triggerAttach(displayedViews);
        }
  
        if (isChangingView) {
          this.triggerMethod('swap', view, this, options);
        }
  
        this.triggerMethod('show', view, this, options);
        Marionette.triggerMethodOn(view, 'show', view, this, options);
  
        return this;
      }
  
      return this;
    },
  
    triggerBeforeAttach: true,
    triggerAttach: true,
  
    _triggerAttach: function(views, prefix) {
      var eventName = (prefix || '') + 'attach';
      _.each(views, function(view) {
        Marionette.triggerMethodOn(view, eventName, view, this);
      }, this);
    },
  
    _displayedViews: function(view) {
      return _.union([view], _.result(view, '_getNestedViews') || []);
    },
  
    _renderView: function(view) {
      if (!view.supportsRenderLifecycle) {
        Marionette.triggerMethodOn(view, 'before:render', view);
      }
      view.render();
      if (!view.supportsRenderLifecycle) {
        Marionette.triggerMethodOn(view, 'render', view);
      }
    },
  
    _ensureElement: function() {
      if (!_.isObject(this.el)) {
        this.$el = this.getEl(this.el);
        this.el = this.$el[0];
      }
  
      if (!this.$el || this.$el.length === 0) {
        if (this.getOption('allowMissingEl')) {
          return false;
        } else {
          throw new Marionette.Error('An "el" ' + this.$el.selector + ' must exist in DOM');
        }
      }
      return true;
    },
  
    _ensureViewIsIntact: function(view) {
      if (!view) {
        throw new Marionette.Error({
          name: 'ViewNotValid',
          message: 'The view passed is undefined and therefore invalid. You must pass a view instance to show.'
        });
      }
  
      if (view.isDestroyed) {
        throw new Marionette.Error({
          name: 'ViewDestroyedError',
          message: 'View (cid: "' + view.cid + '") has already been destroyed and cannot be used.'
        });
      }
    },
  
    // Override this method to change how the region finds the DOM
    // element that it manages. Return a jQuery selector object scoped
    // to a provided parent el or the document if none exists.
    getEl: function(el) {
      return Backbone.$(el, Marionette._getValue(this.options.parentEl, this));
    },
  
    // Override this method to change how the new view is
    // appended to the `$el` that the region is managing
    attachHtml: function(view) {
      this.$el.contents().detach();
  
      this.el.appendChild(view.el);
    },
  
    // Destroy the current view, if there is one. If there is no
    // current view, it does nothing and returns immediately.
    empty: function(options) {
      var view = this.currentView;
  
      var emptyOptions = options || {};
      var preventDestroy  = !!emptyOptions.preventDestroy;
      // If there is no view in the region
      // we should not remove anything
      if (!view) { return this; }
  
      view.off('destroy', this.empty, this);
      this.triggerMethod('before:empty', view);
      if (!preventDestroy) {
        this._destroyView();
      }
      this.triggerMethod('empty', view);
  
      // Remove region pointer to the currentView
      delete this.currentView;
  
      if (preventDestroy) {
        this.$el.contents().detach();
      }
  
      return this;
    },
  
    // call 'destroy' or 'remove', depending on which is found
    // on the view (if showing a raw Backbone view or a Marionette View)
    _destroyView: function() {
      var view = this.currentView;
      if (view.isDestroyed) { return; }
  
      if (!view.supportsDestroyLifecycle) {
        Marionette.triggerMethodOn(view, 'before:destroy', view);
      }
      if (view.destroy) {
        view.destroy();
      } else {
        view.remove();
  
        // appending isDestroyed to raw Backbone View allows regions
        // to throw a ViewDestroyedError for this view
        view.isDestroyed = true;
      }
      if (!view.supportsDestroyLifecycle) {
        Marionette.triggerMethodOn(view, 'destroy', view);
      }
    },
  
    // Attach an existing view to the region. This
    // will not call `render` or `onShow` for the new view,
    // and will not replace the current HTML for the `el`
    // of the region.
    attachView: function(view) {
      if (this.currentView) {
        delete this.currentView._parent;
      }
      view._parent = this;
      this.currentView = view;
      return this;
    },
  
    // Checks whether a view is currently present within
    // the region. Returns `true` if there is and `false` if
    // no view is present.
    hasView: function() {
      return !!this.currentView;
    },
  
    // Reset the region by destroying any existing view and
    // clearing out the cached `$el`. The next time a view
    // is shown via this region, the region will re-query the
    // DOM for the region's `el`.
    reset: function() {
      this.empty();
  
      if (this.$el) {
        this.el = this.$el.selector;
      }
  
      delete this.$el;
      return this;
    }
  
  },
  
  // Static Methods
  {
  
    // Build an instance of a region by passing in a configuration object
    // and a default region class to use if none is specified in the config.
    //
    // The config object should either be a string as a jQuery DOM selector,
    // a Region class directly, or an object literal that specifies a selector,
    // a custom regionClass, and any options to be supplied to the region:
    //
    // ```js
    // {
    //   selector: "#foo",
    //   regionClass: MyCustomRegion,
    //   allowMissingEl: false
    // }
    // ```
    //
    buildRegion: function(regionConfig, DefaultRegionClass) {
      if (_.isString(regionConfig)) {
        return this._buildRegionFromSelector(regionConfig, DefaultRegionClass);
      }
  
      if (regionConfig.selector || regionConfig.el || regionConfig.regionClass) {
        return this._buildRegionFromObject(regionConfig, DefaultRegionClass);
      }
  
      if (_.isFunction(regionConfig)) {
        return this._buildRegionFromRegionClass(regionConfig);
      }
  
      throw new Marionette.Error({
        message: 'Improper region configuration type.',
        url: 'marionette.region.html#region-configuration-types'
      });
    },
  
    // Build the region from a string selector like '#foo-region'
    _buildRegionFromSelector: function(selector, DefaultRegionClass) {
      return new DefaultRegionClass({el: selector});
    },
  
    // Build the region from a configuration object
    // ```js
    // { selector: '#foo', regionClass: FooRegion, allowMissingEl: false }
    // ```
    _buildRegionFromObject: function(regionConfig, DefaultRegionClass) {
      var RegionClass = regionConfig.regionClass || DefaultRegionClass;
      var options = _.omit(regionConfig, 'selector', 'regionClass');
  
      if (regionConfig.selector && !options.el) {
        options.el = regionConfig.selector;
      }
  
      return new RegionClass(options);
    },
  
    // Build the region directly from a given `RegionClass`
    _buildRegionFromRegionClass: function(RegionClass) {
      return new RegionClass();
    }
  });
  
  // Region Manager
  // --------------
  
  // Manage one or more related `Marionette.Region` objects.
  Marionette.RegionManager = Marionette.Controller.extend({
    constructor: function(options) {
      this._regions = {};
      this.length = 0;
  
      Marionette.Controller.call(this, options);
  
      this.addRegions(this.getOption('regions'));
    },
  
    // Add multiple regions using an object literal or a
    // function that returns an object literal, where
    // each key becomes the region name, and each value is
    // the region definition.
    addRegions: function(regionDefinitions, defaults) {
      regionDefinitions = Marionette._getValue(regionDefinitions, this, arguments);
  
      return _.reduce(regionDefinitions, function(regions, definition, name) {
        if (_.isString(definition)) {
          definition = {selector: definition};
        }
        if (definition.selector) {
          definition = _.defaults({}, definition, defaults);
        }
  
        regions[name] = this.addRegion(name, definition);
        return regions;
      }, {}, this);
    },
  
    // Add an individual region to the region manager,
    // and return the region instance
    addRegion: function(name, definition) {
      var region;
  
      if (definition instanceof Marionette.Region) {
        region = definition;
      } else {
        region = Marionette.Region.buildRegion(definition, Marionette.Region);
      }
  
      this.triggerMethod('before:add:region', name, region);
  
      region._parent = this;
      this._store(name, region);
  
      this.triggerMethod('add:region', name, region);
      return region;
    },
  
    // Get a region by name
    get: function(name) {
      return this._regions[name];
    },
  
    // Gets all the regions contained within
    // the `regionManager` instance.
    getRegions: function() {
      return _.clone(this._regions);
    },
  
    // Remove a region by name
    removeRegion: function(name) {
      var region = this._regions[name];
      this._remove(name, region);
  
      return region;
    },
  
    // Empty all regions in the region manager, and
    // remove them
    removeRegions: function() {
      var regions = this.getRegions();
      _.each(this._regions, function(region, name) {
        this._remove(name, region);
      }, this);
  
      return regions;
    },
  
    // Empty all regions in the region manager, but
    // leave them attached
    emptyRegions: function() {
      var regions = this.getRegions();
      _.invoke(regions, 'empty');
      return regions;
    },
  
    // Destroy all regions and shut down the region
    // manager entirely
    destroy: function() {
      this.removeRegions();
      return Marionette.Controller.prototype.destroy.apply(this, arguments);
    },
  
    // internal method to store regions
    _store: function(name, region) {
      if (!this._regions[name]) {
        this.length++;
      }
  
      this._regions[name] = region;
    },
  
    // internal method to remove a region
    _remove: function(name, region) {
      this.triggerMethod('before:remove:region', name, region);
      region.empty();
      region.stopListening();
  
      delete region._parent;
      delete this._regions[name];
      this.length--;
      this.triggerMethod('remove:region', name, region);
    }
  });
  
  Marionette.actAsCollection(Marionette.RegionManager.prototype, '_regions');
  

  // Template Cache
  // --------------
  
  // Manage templates stored in `<script>` blocks,
  // caching them for faster access.
  Marionette.TemplateCache = function(templateId) {
    this.templateId = templateId;
  };
  
  // TemplateCache object-level methods. Manage the template
  // caches from these method calls instead of creating
  // your own TemplateCache instances
  _.extend(Marionette.TemplateCache, {
    templateCaches: {},
  
    // Get the specified template by id. Either
    // retrieves the cached version, or loads it
    // from the DOM.
    get: function(templateId, options) {
      var cachedTemplate = this.templateCaches[templateId];
  
      if (!cachedTemplate) {
        cachedTemplate = new Marionette.TemplateCache(templateId);
        this.templateCaches[templateId] = cachedTemplate;
      }
  
      return cachedTemplate.load(options);
    },
  
    // Clear templates from the cache. If no arguments
    // are specified, clears all templates:
    // `clear()`
    //
    // If arguments are specified, clears each of the
    // specified templates from the cache:
    // `clear("#t1", "#t2", "...")`
    clear: function() {
      var i;
      var args = _.toArray(arguments);
      var length = args.length;
  
      if (length > 0) {
        for (i = 0; i < length; i++) {
          delete this.templateCaches[args[i]];
        }
      } else {
        this.templateCaches = {};
      }
    }
  });
  
  // TemplateCache instance methods, allowing each
  // template cache object to manage its own state
  // and know whether or not it has been loaded
  _.extend(Marionette.TemplateCache.prototype, {
  
    // Internal method to load the template
    load: function(options) {
      // Guard clause to prevent loading this template more than once
      if (this.compiledTemplate) {
        return this.compiledTemplate;
      }
  
      // Load the template and compile it
      var template = this.loadTemplate(this.templateId, options);
      this.compiledTemplate = this.compileTemplate(template, options);
  
      return this.compiledTemplate;
    },
  
    // Load a template from the DOM, by default. Override
    // this method to provide your own template retrieval
    // For asynchronous loading with AMD/RequireJS, consider
    // using a template-loader plugin as described here:
    // https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs
    loadTemplate: function(templateId, options) {
      var $template = Backbone.$(templateId);
  
      if (!$template.length) {
        throw new Marionette.Error({
          name: 'NoTemplateError',
          message: 'Could not find template: "' + templateId + '"'
        });
      }
      return $template.html();
    },
  
    // Pre-compile the template before caching it. Override
    // this method if you do not need to pre-compile a template
    // (JST / RequireJS for example) or if you want to change
    // the template engine used (Handebars, etc).
    compileTemplate: function(rawTemplate, options) {
      return _.template(rawTemplate, options);
    }
  });
  
  // Renderer
  // --------
  
  // Render a template with data by passing in the template
  // selector and the data to render.
  Marionette.Renderer = {
  
    // Render a template with data. The `template` parameter is
    // passed to the `TemplateCache` object to retrieve the
    // template function. Override this method to provide your own
    // custom rendering and template handling for all of Marionette.
    render: function(template, data) {
      if (!template) {
        throw new Marionette.Error({
          name: 'TemplateNotFoundError',
          message: 'Cannot render the template since its false, null or undefined.'
        });
      }
  
      var templateFunc = _.isFunction(template) ? template : Marionette.TemplateCache.get(template);
  
      return templateFunc(data);
    }
  };
  

  /* jshint maxlen: 114, nonew: false */
  // View
  // ----
  
  // The core view class that other Marionette views extend from.
  Marionette.View = Backbone.View.extend({
    isDestroyed: false,
    supportsRenderLifecycle: true,
    supportsDestroyLifecycle: true,
  
    constructor: function(options) {
      this.render = _.bind(this.render, this);
  
      options = Marionette._getValue(options, this);
  
      // this exposes view options to the view initializer
      // this is a backfill since backbone removed the assignment
      // of this.options
      // at some point however this may be removed
      this.options = _.extend({}, _.result(this, 'options'), options);
  
      this._behaviors = Marionette.Behaviors(this);
  
      Backbone.View.call(this, this.options);
  
      Marionette.MonitorDOMRefresh(this);
    },
  
    // Get the template for this view
    // instance. You can set a `template` attribute in the view
    // definition or pass a `template: "whatever"` parameter in
    // to the constructor options.
    getTemplate: function() {
      return this.getOption('template');
    },
  
    // Serialize a model by returning its attributes. Clones
    // the attributes to allow modification.
    serializeModel: function(model) {
      return model.toJSON.apply(model, _.rest(arguments));
    },
  
    // Mix in template helper methods. Looks for a
    // `templateHelpers` attribute, which can either be an
    // object literal, or a function that returns an object
    // literal. All methods and attributes from this object
    // are copies to the object passed in.
    mixinTemplateHelpers: function(target) {
      target = target || {};
      var templateHelpers = this.getOption('templateHelpers');
      templateHelpers = Marionette._getValue(templateHelpers, this);
      return _.extend(target, templateHelpers);
    },
  
    // normalize the keys of passed hash with the views `ui` selectors.
    // `{"@ui.foo": "bar"}`
    normalizeUIKeys: function(hash) {
      var uiBindings = _.result(this, '_uiBindings');
      return Marionette.normalizeUIKeys(hash, uiBindings || _.result(this, 'ui'));
    },
  
    // normalize the values of passed hash with the views `ui` selectors.
    // `{foo: "@ui.bar"}`
    normalizeUIValues: function(hash, properties) {
      var ui = _.result(this, 'ui');
      var uiBindings = _.result(this, '_uiBindings');
      return Marionette.normalizeUIValues(hash, uiBindings || ui, properties);
    },
  
    // Configure `triggers` to forward DOM events to view
    // events. `triggers: {"click .foo": "do:foo"}`
    configureTriggers: function() {
      if (!this.triggers) { return; }
  
      // Allow `triggers` to be configured as a function
      var triggers = this.normalizeUIKeys(_.result(this, 'triggers'));
  
      // Configure the triggers, prevent default
      // action and stop propagation of DOM events
      return _.reduce(triggers, function(events, value, key) {
        events[key] = this._buildViewTrigger(value);
        return events;
      }, {}, this);
    },
  
    // Overriding Backbone.View's delegateEvents to handle
    // the `triggers`, `modelEvents`, and `collectionEvents` configuration
    delegateEvents: function(events) {
      this._delegateDOMEvents(events);
      this.bindEntityEvents(this.model, this.getOption('modelEvents'));
      this.bindEntityEvents(this.collection, this.getOption('collectionEvents'));
  
      _.each(this._behaviors, function(behavior) {
        behavior.bindEntityEvents(this.model, behavior.getOption('modelEvents'));
        behavior.bindEntityEvents(this.collection, behavior.getOption('collectionEvents'));
      }, this);
  
      return this;
    },
  
    // internal method to delegate DOM events and triggers
    _delegateDOMEvents: function(eventsArg) {
      var events = Marionette._getValue(eventsArg || this.events, this);
  
      // normalize ui keys
      events = this.normalizeUIKeys(events);
      if (_.isUndefined(eventsArg)) {this.events = events;}
  
      var combinedEvents = {};
  
      // look up if this view has behavior events
      var behaviorEvents = _.result(this, 'behaviorEvents') || {};
      var triggers = this.configureTriggers();
      var behaviorTriggers = _.result(this, 'behaviorTriggers') || {};
  
      // behavior events will be overriden by view events and or triggers
      _.extend(combinedEvents, behaviorEvents, events, triggers, behaviorTriggers);
  
      Backbone.View.prototype.delegateEvents.call(this, combinedEvents);
    },
  
    // Overriding Backbone.View's undelegateEvents to handle unbinding
    // the `triggers`, `modelEvents`, and `collectionEvents` config
    undelegateEvents: function() {
      Backbone.View.prototype.undelegateEvents.apply(this, arguments);
  
      this.unbindEntityEvents(this.model, this.getOption('modelEvents'));
      this.unbindEntityEvents(this.collection, this.getOption('collectionEvents'));
  
      _.each(this._behaviors, function(behavior) {
        behavior.unbindEntityEvents(this.model, behavior.getOption('modelEvents'));
        behavior.unbindEntityEvents(this.collection, behavior.getOption('collectionEvents'));
      }, this);
  
      return this;
    },
  
    // Internal helper method to verify whether the view hasn't been destroyed
    _ensureViewIsIntact: function() {
      if (this.isDestroyed) {
        throw new Marionette.Error({
          name: 'ViewDestroyedError',
          message: 'View (cid: "' + this.cid + '") has already been destroyed and cannot be used.'
        });
      }
    },
  
    // Default `destroy` implementation, for removing a view from the
    // DOM and unbinding it. Regions will call this method
    // for you. You can specify an `onDestroy` method in your view to
    // add custom code that is called after the view is destroyed.
    destroy: function() {
      if (this.isDestroyed) { return this; }
  
      var args = _.toArray(arguments);
  
      this.triggerMethod.apply(this, ['before:destroy'].concat(args));
  
      // mark as destroyed before doing the actual destroy, to
      // prevent infinite loops within "destroy" event handlers
      // that are trying to destroy other views
      this.isDestroyed = true;
      this.triggerMethod.apply(this, ['destroy'].concat(args));
  
      // unbind UI elements
      this.unbindUIElements();
  
      this.isRendered = false;
  
      // remove the view from the DOM
      this.remove();
  
      // Call destroy on each behavior after
      // destroying the view.
      // This unbinds event listeners
      // that behaviors have registered for.
      _.invoke(this._behaviors, 'destroy', args);
  
      return this;
    },
  
    bindUIElements: function() {
      this._bindUIElements();
      _.invoke(this._behaviors, this._bindUIElements);
    },
  
    // This method binds the elements specified in the "ui" hash inside the view's code with
    // the associated jQuery selectors.
    _bindUIElements: function() {
      if (!this.ui) { return; }
  
      // store the ui hash in _uiBindings so they can be reset later
      // and so re-rendering the view will be able to find the bindings
      if (!this._uiBindings) {
        this._uiBindings = this.ui;
      }
  
      // get the bindings result, as a function or otherwise
      var bindings = _.result(this, '_uiBindings');
  
      // empty the ui so we don't have anything to start with
      this.ui = {};
  
      // bind each of the selectors
      _.each(bindings, function(selector, key) {
        this.ui[key] = this.$(selector);
      }, this);
    },
  
    // This method unbinds the elements specified in the "ui" hash
    unbindUIElements: function() {
      this._unbindUIElements();
      _.invoke(this._behaviors, this._unbindUIElements);
    },
  
    _unbindUIElements: function() {
      if (!this.ui || !this._uiBindings) { return; }
  
      // delete all of the existing ui bindings
      _.each(this.ui, function($el, name) {
        delete this.ui[name];
      }, this);
  
      // reset the ui element to the original bindings configuration
      this.ui = this._uiBindings;
      delete this._uiBindings;
    },
  
    // Internal method to create an event handler for a given `triggerDef` like
    // 'click:foo'
    _buildViewTrigger: function(triggerDef) {
  
      var options = _.defaults({}, triggerDef, {
        preventDefault: true,
        stopPropagation: true
      });
  
      var eventName = _.isObject(triggerDef) ? options.event : triggerDef;
  
      return function(e) {
        if (e) {
          if (e.preventDefault && options.preventDefault) {
            e.preventDefault();
          }
  
          if (e.stopPropagation && options.stopPropagation) {
            e.stopPropagation();
          }
        }
  
        var args = {
          view: this,
          model: this.model,
          collection: this.collection
        };
  
        this.triggerMethod(eventName, args);
      };
    },
  
    setElement: function() {
      var ret = Backbone.View.prototype.setElement.apply(this, arguments);
  
      // proxy behavior $el to the view's $el.
      // This is needed because a view's $el proxy
      // is not set until after setElement is called.
      _.invoke(this._behaviors, 'proxyViewProperties', this);
  
      return ret;
    },
  
    // import the `triggerMethod` to trigger events with corresponding
    // methods if the method exists
    triggerMethod: function() {
      var ret = Marionette._triggerMethod(this, arguments);
  
      this._triggerEventOnBehaviors(arguments);
      this._triggerEventOnParentLayout(arguments[0], _.rest(arguments));
  
      return ret;
    },
  
    _triggerEventOnBehaviors: function(args) {
      var triggerMethod = Marionette._triggerMethod;
      var behaviors = this._behaviors;
      // Use good ol' for as this is a very hot function
      for (var i = 0, length = behaviors && behaviors.length; i < length; i++) {
        triggerMethod(behaviors[i], args);
      }
    },
  
    _triggerEventOnParentLayout: function(eventName, args) {
      var layoutView = this._parentLayoutView();
      if (!layoutView) {
        return;
      }
  
      // invoke triggerMethod on parent view
      var eventPrefix = Marionette.getOption(layoutView, 'childViewEventPrefix');
      var prefixedEventName = eventPrefix + ':' + eventName;
      var callArgs = [this].concat(args);
  
      Marionette._triggerMethod(layoutView, prefixedEventName, callArgs);
  
      // call the parent view's childEvents handler
      var childEvents = Marionette.getOption(layoutView, 'childEvents');
  
      // since childEvents can be an object or a function use Marionette._getValue
      // to handle the abstaction for us.
      childEvents = Marionette._getValue(childEvents, layoutView);
      var normalizedChildEvents = layoutView.normalizeMethods(childEvents);
  
      if (normalizedChildEvents && _.isFunction(normalizedChildEvents[eventName])) {
        normalizedChildEvents[eventName].apply(layoutView, callArgs);
      }
    },
  
    // This method returns any views that are immediate
    // children of this view
    _getImmediateChildren: function() {
      return [];
    },
  
    // Returns an array of every nested view within this view
    _getNestedViews: function() {
      var children = this._getImmediateChildren();
  
      if (!children.length) { return children; }
  
      return _.reduce(children, function(memo, view) {
        if (!view._getNestedViews) { return memo; }
        return memo.concat(view._getNestedViews());
      }, children);
    },
  
    // Walk the _parent tree until we find a layout view (if one exists).
    // Returns the parent layout view hierarchically closest to this view.
    _parentLayoutView: function() {
      var parent  = this._parent;
  
      while (parent) {
        if (parent instanceof Marionette.LayoutView) {
          return parent;
        }
        parent = parent._parent;
      }
    },
  
    // Imports the "normalizeMethods" to transform hashes of
    // events=>function references/names to a hash of events=>function references
    normalizeMethods: Marionette.normalizeMethods,
  
    // A handy way to merge passed-in options onto the instance
    mergeOptions: Marionette.mergeOptions,
  
    // Proxy `getOption` to enable getting options from this or this.options by name.
    getOption: Marionette.proxyGetOption,
  
    // Proxy `bindEntityEvents` to enable binding view's events from another entity.
    bindEntityEvents: Marionette.proxyBindEntityEvents,
  
    // Proxy `unbindEntityEvents` to enable unbinding view's events from another entity.
    unbindEntityEvents: Marionette.proxyUnbindEntityEvents
  });
  
  // Item View
  // ---------
  
  // A single item view implementation that contains code for rendering
  // with underscore.js templates, serializing the view's model or collection,
  // and calling several methods on extended views, such as `onRender`.
  Marionette.ItemView = Marionette.View.extend({
  
    // Setting up the inheritance chain which allows changes to
    // Marionette.View.prototype.constructor which allows overriding
    constructor: function() {
      Marionette.View.apply(this, arguments);
    },
  
    // Serialize the model or collection for the view. If a model is
    // found, the view's `serializeModel` is called. If a collection is found,
    // each model in the collection is serialized by calling
    // the view's `serializeCollection` and put into an `items` array in
    // the resulting data. If both are found, defaults to the model.
    // You can override the `serializeData` method in your own view definition,
    // to provide custom serialization for your view's data.
    serializeData: function() {
      if (!this.model && !this.collection) {
        return {};
      }
  
      var args = [this.model || this.collection];
      if (arguments.length) {
        args.push.apply(args, arguments);
      }
  
      if (this.model) {
        return this.serializeModel.apply(this, args);
      } else {
        return {
          items: this.serializeCollection.apply(this, args)
        };
      }
    },
  
    // Serialize a collection by serializing each of its models.
    serializeCollection: function(collection) {
      return collection.toJSON.apply(collection, _.rest(arguments));
    },
  
    // Render the view, defaulting to underscore.js templates.
    // You can override this in your view definition to provide
    // a very specific rendering for your view. In general, though,
    // you should override the `Marionette.Renderer` object to
    // change how Marionette renders views.
    render: function() {
      this._ensureViewIsIntact();
  
      this.triggerMethod('before:render', this);
  
      this._renderTemplate();
      this.isRendered = true;
      this.bindUIElements();
  
      this.triggerMethod('render', this);
  
      return this;
    },
  
    // Internal method to render the template with the serialized data
    // and template helpers via the `Marionette.Renderer` object.
    // Throws an `UndefinedTemplateError` error if the template is
    // any falsely value but literal `false`.
    _renderTemplate: function() {
      var template = this.getTemplate();
  
      // Allow template-less item views
      if (template === false) {
        return;
      }
  
      if (!template) {
        throw new Marionette.Error({
          name: 'UndefinedTemplateError',
          message: 'Cannot render the template since it is null or undefined.'
        });
      }
  
      // Add in entity data and template helpers
      var data = this.mixinTemplateHelpers(this.serializeData());
  
      // Render and add to el
      var html = Marionette.Renderer.render(template, data, this);
      this.attachElContent(html);
  
      return this;
    },
  
    // Attaches the content of a given view.
    // This method can be overridden to optimize rendering,
    // or to render in a non standard way.
    //
    // For example, using `innerHTML` instead of `$el.html`
    //
    // ```js
    // attachElContent: function(html) {
    //   this.el.innerHTML = html;
    //   return this;
    // }
    // ```
    attachElContent: function(html) {
      this.$el.html(html);
  
      return this;
    }
  });
  
  /* jshint maxstatements: 20, maxcomplexity: 7 */
  
  // Collection View
  // ---------------
  
  // A view that iterates over a Backbone.Collection
  // and renders an individual child view for each model.
  Marionette.CollectionView = Marionette.View.extend({
  
    // used as the prefix for child view events
    // that are forwarded through the collectionview
    childViewEventPrefix: 'childview',
  
    // flag for maintaining the sorted order of the collection
    sort: true,
  
    // constructor
    // option to pass `{sort: false}` to prevent the `CollectionView` from
    // maintaining the sorted order of the collection.
    // This will fallback onto appending childView's to the end.
    //
    // option to pass `{comparator: compFunction()}` to allow the `CollectionView`
    // to use a custom sort order for the collection.
    constructor: function(options) {
      this.once('render', this._initialEvents);
      this._initChildViewStorage();
  
      Marionette.View.apply(this, arguments);
  
      this.on({
        'before:show':   this._onBeforeShowCalled,
        'show':          this._onShowCalled,
        'before:attach': this._onBeforeAttachCalled,
        'attach':        this._onAttachCalled
      });
      this.initRenderBuffer();
    },
  
    // Instead of inserting elements one by one into the page,
    // it's much more performant to insert elements into a document
    // fragment and then insert that document fragment into the page
    initRenderBuffer: function() {
      this._bufferedChildren = [];
    },
  
    startBuffering: function() {
      this.initRenderBuffer();
      this.isBuffering = true;
    },
  
    endBuffering: function() {
      // Only trigger attach if already shown and attached, otherwise Region#show() handles this.
      var canTriggerAttach = this._isShown && Marionette.isNodeAttached(this.el);
      var nestedViews;
  
      this.isBuffering = false;
  
      if (this._isShown) {
        this._triggerMethodMany(this._bufferedChildren, this, 'before:show');
      }
      if (canTriggerAttach && this._triggerBeforeAttach) {
        nestedViews = this._getNestedViews();
        this._triggerMethodMany(nestedViews, this, 'before:attach');
      }
  
      this.attachBuffer(this, this._createBuffer());
  
      if (canTriggerAttach && this._triggerAttach) {
        nestedViews = this._getNestedViews();
        this._triggerMethodMany(nestedViews, this, 'attach');
      }
      if (this._isShown) {
        this._triggerMethodMany(this._bufferedChildren, this, 'show');
      }
      this.initRenderBuffer();
    },
  
    _triggerMethodMany: function(targets, source, eventName) {
      var args = _.drop(arguments, 3);
  
      _.each(targets, function(target) {
        Marionette.triggerMethodOn.apply(target, [target, eventName, target, source].concat(args));
      });
    },
  
    // Configured the initial events that the collection view
    // binds to.
    _initialEvents: function() {
      if (this.collection) {
        this.listenTo(this.collection, 'add', this._onCollectionAdd);
        this.listenTo(this.collection, 'remove', this._onCollectionRemove);
        this.listenTo(this.collection, 'reset', this.render);
  
        if (this.getOption('sort')) {
          this.listenTo(this.collection, 'sort', this._sortViews);
        }
      }
    },
  
    // Handle a child added to the collection
    _onCollectionAdd: function(child, collection, opts) {
      // `index` is present when adding with `at` since BB 1.2; indexOf fallback for < 1.2
      var index = opts.at !== undefined && (opts.index || collection.indexOf(child));
  
      // When filtered or when there is no initial index, calculate index.
      if (this.getOption('filter') || index === false) {
        index = _.indexOf(this._filteredSortedModels(index), child);
      }
  
      if (this._shouldAddChild(child, index)) {
        this.destroyEmptyView();
        var ChildView = this.getChildView(child);
        this.addChild(child, ChildView, index);
      }
    },
  
    // get the child view by model it holds, and remove it
    _onCollectionRemove: function(model) {
      var view = this.children.findByModel(model);
      this.removeChildView(view);
      this.checkEmpty();
    },
  
    _onBeforeShowCalled: function() {
      // Reset attach event flags at the top of the Region#show() event lifecycle; if the Region's
      // show() options permit onBeforeAttach/onAttach events, these flags will be set true again.
      this._triggerBeforeAttach = this._triggerAttach = false;
      this.children.each(function(childView) {
        Marionette.triggerMethodOn(childView, 'before:show', childView);
      });
    },
  
    _onShowCalled: function() {
      this.children.each(function(childView) {
        Marionette.triggerMethodOn(childView, 'show', childView);
      });
    },
  
    // If during Region#show() onBeforeAttach was fired, continue firing it for child views
    _onBeforeAttachCalled: function() {
      this._triggerBeforeAttach = true;
    },
  
    // If during Region#show() onAttach was fired, continue firing it for child views
    _onAttachCalled: function() {
      this._triggerAttach = true;
    },
  
    // Render children views. Override this method to
    // provide your own implementation of a render function for
    // the collection view.
    render: function() {
      this._ensureViewIsIntact();
      this.triggerMethod('before:render', this);
      this._renderChildren();
      this.isRendered = true;
      this.triggerMethod('render', this);
      return this;
    },
  
    // Reorder DOM after sorting. When your element's rendering
    // do not use their index, you can pass reorderOnSort: true
    // to only reorder the DOM after a sort instead of rendering
    // all the collectionView
    reorder: function() {
      var children = this.children;
      var models = this._filteredSortedModels();
  
      if (!models.length && this._showingEmptyView) { return this; }
  
      var anyModelsAdded = _.some(models, function(model) {
        return !children.findByModel(model);
      });
  
      // If there are any new models added due to filtering
      // We need to add child views
      // So render as normal
      if (anyModelsAdded) {
        this.render();
      } else {
        // get the DOM nodes in the same order as the models
        var elsToReorder = _.map(models, function(model, index) {
          var view = children.findByModel(model);
          view._index = index;
          return view.el;
        });
  
        // find the views that were children before but arent in this new ordering
        var filteredOutViews = children.filter(function(view) {
          return !_.contains(elsToReorder, view.el);
        });
  
        this.triggerMethod('before:reorder');
  
        // since append moves elements that are already in the DOM,
        // appending the elements will effectively reorder them
        this._appendReorderedChildren(elsToReorder);
  
        // remove any views that have been filtered out
        _.each(filteredOutViews, this.removeChildView, this);
        this.checkEmpty();
  
        this.triggerMethod('reorder');
      }
    },
  
    // Render view after sorting. Override this method to
    // change how the view renders after a `sort` on the collection.
    // An example of this would be to only `renderChildren` in a `CompositeView`
    // rather than the full view.
    resortView: function() {
      if (Marionette.getOption(this, 'reorderOnSort')) {
        this.reorder();
      } else {
        this.render();
      }
    },
  
    // Internal method. This checks for any changes in the order of the collection.
    // If the index of any view doesn't match, it will render.
    _sortViews: function() {
      var models = this._filteredSortedModels();
  
      // check for any changes in sort order of views
      var orderChanged = _.find(models, function(item, index) {
        var view = this.children.findByModel(item);
        return !view || view._index !== index;
      }, this);
  
      if (orderChanged) {
        this.resortView();
      }
    },
  
    // Internal reference to what index a `emptyView` is.
    _emptyViewIndex: -1,
  
    // Internal method. Separated so that CompositeView can append to the childViewContainer
    // if necessary
    _appendReorderedChildren: function(children) {
      this.$el.append(children);
    },
  
    // Internal method. Separated so that CompositeView can have
    // more control over events being triggered, around the rendering
    // process
    _renderChildren: function() {
      this.destroyEmptyView();
      this.destroyChildren({checkEmpty: false});
  
      if (this.isEmpty(this.collection)) {
        this.showEmptyView();
      } else {
        this.triggerMethod('before:render:collection', this);
        this.startBuffering();
        this.showCollection();
        this.endBuffering();
        this.triggerMethod('render:collection', this);
  
        // If we have shown children and none have passed the filter, show the empty view
        if (this.children.isEmpty() && this.getOption('filter')) {
          this.showEmptyView();
        }
      }
    },
  
    // Internal method to loop through collection and show each child view.
    showCollection: function() {
      var ChildView;
  
      var models = this._filteredSortedModels();
  
      _.each(models, function(child, index) {
        ChildView = this.getChildView(child);
        this.addChild(child, ChildView, index);
      }, this);
    },
  
    // Allow the collection to be sorted by a custom view comparator
    _filteredSortedModels: function(addedAt) {
      var viewComparator = this.getViewComparator();
      var models = this.collection.models;
      addedAt = Math.min(Math.max(addedAt, 0), models.length - 1);
  
      if (viewComparator) {
        var addedModel;
        // Preserve `at` location, even for a sorted view
        if (addedAt) {
          addedModel = models[addedAt];
          models = models.slice(0, addedAt).concat(models.slice(addedAt + 1));
        }
        models = this._sortModelsBy(models, viewComparator);
        if (addedModel) {
          models.splice(addedAt, 0, addedModel);
        }
      }
  
      // Filter after sorting in case the filter uses the index
      if (this.getOption('filter')) {
        models = _.filter(models, function(model, index) {
          return this._shouldAddChild(model, index);
        }, this);
      }
  
      return models;
    },
  
    _sortModelsBy: function(models, comparator) {
      if (typeof comparator === 'string') {
        return _.sortBy(models, function(model) {
          return model.get(comparator);
        }, this);
      } else if (comparator.length === 1) {
        return _.sortBy(models, comparator, this);
      } else {
        return models.sort(_.bind(comparator, this));
      }
    },
  
    // Internal method to show an empty view in place of
    // a collection of child views, when the collection is empty
    showEmptyView: function() {
      var EmptyView = this.getEmptyView();
  
      if (EmptyView && !this._showingEmptyView) {
        this.triggerMethod('before:render:empty');
  
        this._showingEmptyView = true;
        var model = new Backbone.Model();
        this.addEmptyView(model, EmptyView);
  
        this.triggerMethod('render:empty');
      }
    },
  
    // Internal method to destroy an existing emptyView instance
    // if one exists. Called when a collection view has been
    // rendered empty, and then a child is added to the collection.
    destroyEmptyView: function() {
      if (this._showingEmptyView) {
        this.triggerMethod('before:remove:empty');
  
        this.destroyChildren();
        delete this._showingEmptyView;
  
        this.triggerMethod('remove:empty');
      }
    },
  
    // Retrieve the empty view class
    getEmptyView: function() {
      return this.getOption('emptyView');
    },
  
    // Render and show the emptyView. Similar to addChild method
    // but "add:child" events are not fired, and the event from
    // emptyView are not forwarded
    addEmptyView: function(child, EmptyView) {
      // Only trigger attach if already shown, attached, and not buffering, otherwise endBuffer() or
      // Region#show() handles this.
      var canTriggerAttach = this._isShown && !this.isBuffering && Marionette.isNodeAttached(this.el);
      var nestedViews;
  
      // get the emptyViewOptions, falling back to childViewOptions
      var emptyViewOptions = this.getOption('emptyViewOptions') ||
                            this.getOption('childViewOptions');
  
      if (_.isFunction(emptyViewOptions)) {
        emptyViewOptions = emptyViewOptions.call(this, child, this._emptyViewIndex);
      }
  
      // build the empty view
      var view = this.buildChildView(child, EmptyView, emptyViewOptions);
  
      view._parent = this;
  
      // Proxy emptyView events
      this.proxyChildEvents(view);
  
      view.once('render', function() {
        // trigger the 'before:show' event on `view` if the collection view has already been shown
        if (this._isShown) {
          Marionette.triggerMethodOn(view, 'before:show', view);
        }
  
        // Trigger `before:attach` following `render` to avoid adding logic and event triggers
        // to public method `renderChildView()`.
        if (canTriggerAttach && this._triggerBeforeAttach) {
          nestedViews = this._getViewAndNested(view);
          this._triggerMethodMany(nestedViews, this, 'before:attach');
        }
      }, this);
  
      // Store the `emptyView` like a `childView` so we can properly remove and/or close it later
      this.children.add(view);
      this.renderChildView(view, this._emptyViewIndex);
  
      // Trigger `attach`
      if (canTriggerAttach && this._triggerAttach) {
        nestedViews = this._getViewAndNested(view);
        this._triggerMethodMany(nestedViews, this, 'attach');
      }
      // call the 'show' method if the collection view has already been shown
      if (this._isShown) {
        Marionette.triggerMethodOn(view, 'show', view);
      }
    },
  
    // Retrieve the `childView` class, either from `this.options.childView`
    // or from the `childView` in the object definition. The "options"
    // takes precedence.
    // This method receives the model that will be passed to the instance
    // created from this `childView`. Overriding methods may use the child
    // to determine what `childView` class to return.
    getChildView: function(child) {
      var childView = this.getOption('childView');
  
      if (!childView) {
        throw new Marionette.Error({
          name: 'NoChildViewError',
          message: 'A "childView" must be specified'
        });
      }
  
      return childView;
    },
  
    // Render the child's view and add it to the
    // HTML for the collection view at a given index.
    // This will also update the indices of later views in the collection
    // in order to keep the children in sync with the collection.
    addChild: function(child, ChildView, index) {
      var childViewOptions = this.getOption('childViewOptions');
      childViewOptions = Marionette._getValue(childViewOptions, this, [child, index]);
  
      var view = this.buildChildView(child, ChildView, childViewOptions);
  
      // increment indices of views after this one
      this._updateIndices(view, true, index);
  
      this.triggerMethod('before:add:child', view);
      this._addChildView(view, index);
      this.triggerMethod('add:child', view);
  
      view._parent = this;
  
      return view;
    },
  
    // Internal method. This decrements or increments the indices of views after the
    // added/removed view to keep in sync with the collection.
    _updateIndices: function(view, increment, index) {
      if (!this.getOption('sort')) {
        return;
      }
  
      if (increment) {
        // assign the index to the view
        view._index = index;
      }
  
      // update the indexes of views after this one
      this.children.each(function(laterView) {
        if (laterView._index >= view._index) {
          laterView._index += increment ? 1 : -1;
        }
      });
    },
  
    // Internal Method. Add the view to children and render it at
    // the given index.
    _addChildView: function(view, index) {
      // Only trigger attach if already shown, attached, and not buffering, otherwise endBuffer() or
      // Region#show() handles this.
      var canTriggerAttach = this._isShown && !this.isBuffering && Marionette.isNodeAttached(this.el);
      var nestedViews;
  
      // set up the child view event forwarding
      this.proxyChildEvents(view);
  
      view.once('render', function() {
        // trigger the 'before:show' event on `view` if the collection view has already been shown
        if (this._isShown && !this.isBuffering) {
          Marionette.triggerMethodOn(view, 'before:show', view);
        }
  
        // Trigger `before:attach` following `render` to avoid adding logic and event triggers
        // to public method `renderChildView()`.
        if (canTriggerAttach && this._triggerBeforeAttach) {
          nestedViews = this._getViewAndNested(view);
          this._triggerMethodMany(nestedViews, this, 'before:attach');
        }
      }, this);
  
      // Store the child view itself so we can properly remove and/or destroy it later
      this.children.add(view);
      this.renderChildView(view, index);
  
      // Trigger `attach`
      if (canTriggerAttach && this._triggerAttach) {
        nestedViews = this._getViewAndNested(view);
        this._triggerMethodMany(nestedViews, this, 'attach');
      }
      // Trigger `show`
      if (this._isShown && !this.isBuffering) {
        Marionette.triggerMethodOn(view, 'show', view);
      }
    },
  
    // render the child view
    renderChildView: function(view, index) {
      if (!view.supportsRenderLifecycle) {
        Marionette.triggerMethodOn(view, 'before:render', view);
      }
      view.render();
      if (!view.supportsRenderLifecycle) {
        Marionette.triggerMethodOn(view, 'render', view);
      }
      this.attachHtml(this, view, index);
      return view;
    },
  
    // Build a `childView` for a model in the collection.
    buildChildView: function(child, ChildViewClass, childViewOptions) {
      var options = _.extend({model: child}, childViewOptions);
      var childView = new ChildViewClass(options);
      Marionette.MonitorDOMRefresh(childView);
      return childView;
    },
  
    // Remove the child view and destroy it.
    // This function also updates the indices of
    // later views in the collection in order to keep
    // the children in sync with the collection.
    removeChildView: function(view) {
      if (!view) { return view; }
  
      this.triggerMethod('before:remove:child', view);
  
      if (!view.supportsDestroyLifecycle) {
        Marionette.triggerMethodOn(view, 'before:destroy', view);
      }
      // call 'destroy' or 'remove', depending on which is found
      if (view.destroy) {
        view.destroy();
      } else {
        view.remove();
      }
      if (!view.supportsDestroyLifecycle) {
        Marionette.triggerMethodOn(view, 'destroy', view);
      }
  
      delete view._parent;
      this.stopListening(view);
      this.children.remove(view);
      this.triggerMethod('remove:child', view);
  
      // decrement the index of views after this one
      this._updateIndices(view, false);
  
      return view;
    },
  
    // check if the collection is empty
    isEmpty: function() {
      return !this.collection || this.collection.length === 0;
    },
  
    // If empty, show the empty view
    checkEmpty: function() {
      if (this.isEmpty(this.collection)) {
        this.showEmptyView();
      }
    },
  
    // You might need to override this if you've overridden attachHtml
    attachBuffer: function(collectionView, buffer) {
      collectionView.$el.append(buffer);
    },
  
    // Create a fragment buffer from the currently buffered children
    _createBuffer: function() {
      var elBuffer = document.createDocumentFragment();
      _.each(this._bufferedChildren, function(b) {
        elBuffer.appendChild(b.el);
      });
      return elBuffer;
    },
  
    // Append the HTML to the collection's `el`.
    // Override this method to do something other
    // than `.append`.
    attachHtml: function(collectionView, childView, index) {
      if (collectionView.isBuffering) {
        // buffering happens on reset events and initial renders
        // in order to reduce the number of inserts into the
        // document, which are expensive.
        collectionView._bufferedChildren.splice(index, 0, childView);
      } else {
        // If we've already rendered the main collection, append
        // the new child into the correct order if we need to. Otherwise
        // append to the end.
        if (!collectionView._insertBefore(childView, index)) {
          collectionView._insertAfter(childView);
        }
      }
    },
  
    // Internal method. Check whether we need to insert the view into
    // the correct position.
    _insertBefore: function(childView, index) {
      var currentView;
      var findPosition = this.getOption('sort') && (index < this.children.length - 1);
      if (findPosition) {
        // Find the view after this one
        currentView = this.children.find(function(view) {
          return view._index === index + 1;
        });
      }
  
      if (currentView) {
        currentView.$el.before(childView.el);
        return true;
      }
  
      return false;
    },
  
    // Internal method. Append a view to the end of the $el
    _insertAfter: function(childView) {
      this.$el.append(childView.el);
    },
  
    // Internal method to set up the `children` object for
    // storing all of the child views
    _initChildViewStorage: function() {
      this.children = new Backbone.ChildViewContainer();
    },
  
    // Handle cleanup and other destroying needs for the collection of views
    destroy: function() {
      if (this.isDestroyed) { return this; }
  
      this.triggerMethod('before:destroy:collection');
      this.destroyChildren({checkEmpty: false});
      this.triggerMethod('destroy:collection');
  
      return Marionette.View.prototype.destroy.apply(this, arguments);
    },
  
    // Destroy the child views that this collection view
    // is holding on to, if any
    destroyChildren: function(options) {
      var destroyOptions = options || {};
      var shouldCheckEmpty = true;
      var childViews = this.children.map(_.identity);
  
      if (!_.isUndefined(destroyOptions.checkEmpty)) {
        shouldCheckEmpty = destroyOptions.checkEmpty;
      }
  
      this.children.each(this.removeChildView, this);
  
      if (shouldCheckEmpty) {
        this.checkEmpty();
      }
      return childViews;
    },
  
    // Return true if the given child should be shown
    // Return false otherwise
    // The filter will be passed (child, index, collection)
    // Where
    //  'child' is the given model
    //  'index' is the index of that model in the collection
    //  'collection' is the collection referenced by this CollectionView
    _shouldAddChild: function(child, index) {
      var filter = this.getOption('filter');
      return !_.isFunction(filter) || filter.call(this, child, index, this.collection);
    },
  
    // Set up the child view event forwarding. Uses a "childview:"
    // prefix in front of all forwarded events.
    proxyChildEvents: function(view) {
      var prefix = this.getOption('childViewEventPrefix');
  
      // Forward all child view events through the parent,
      // prepending "childview:" to the event name
      this.listenTo(view, 'all', function() {
        var args = _.toArray(arguments);
        var rootEvent = args[0];
        var childEvents = this.normalizeMethods(_.result(this, 'childEvents'));
  
        args[0] = prefix + ':' + rootEvent;
        args.splice(1, 0, view);
  
        // call collectionView childEvent if defined
        if (typeof childEvents !== 'undefined' && _.isFunction(childEvents[rootEvent])) {
          childEvents[rootEvent].apply(this, args.slice(1));
        }
  
        this.triggerMethod.apply(this, args);
      });
    },
  
    _getImmediateChildren: function() {
      return _.values(this.children._views);
    },
  
    _getViewAndNested: function(view) {
      // This will not fail on Backbone.View which does not have #_getNestedViews.
      return [view].concat(_.result(view, '_getNestedViews') || []);
    },
  
    getViewComparator: function() {
      return this.getOption('viewComparator');
    }
  });
  
  /* jshint maxstatements: 17, maxlen: 117 */
  
  // Composite View
  // --------------
  
  // Used for rendering a branch-leaf, hierarchical structure.
  // Extends directly from CollectionView and also renders an
  // a child view as `modelView`, for the top leaf
  Marionette.CompositeView = Marionette.CollectionView.extend({
  
    // Setting up the inheritance chain which allows changes to
    // Marionette.CollectionView.prototype.constructor which allows overriding
    // option to pass '{sort: false}' to prevent the CompositeView from
    // maintaining the sorted order of the collection.
    // This will fallback onto appending childView's to the end.
    constructor: function() {
      Marionette.CollectionView.apply(this, arguments);
    },
  
    // Configured the initial events that the composite view
    // binds to. Override this method to prevent the initial
    // events, or to add your own initial events.
    _initialEvents: function() {
  
      // Bind only after composite view is rendered to avoid adding child views
      // to nonexistent childViewContainer
  
      if (this.collection) {
        this.listenTo(this.collection, 'add', this._onCollectionAdd);
        this.listenTo(this.collection, 'remove', this._onCollectionRemove);
        this.listenTo(this.collection, 'reset', this._renderChildren);
  
        if (this.getOption('sort')) {
          this.listenTo(this.collection, 'sort', this._sortViews);
        }
      }
    },
  
    // Retrieve the `childView` to be used when rendering each of
    // the items in the collection. The default is to return
    // `this.childView` or Marionette.CompositeView if no `childView`
    // has been defined
    getChildView: function(child) {
      var childView = this.getOption('childView') || this.constructor;
  
      return childView;
    },
  
    // Serialize the model for the view.
    // You can override the `serializeData` method in your own view
    // definition, to provide custom serialization for your view's data.
    serializeData: function() {
      var data = {};
  
      if (this.model) {
        data = _.partial(this.serializeModel, this.model).apply(this, arguments);
      }
  
      return data;
    },
  
    // Renders the model and the collection.
    render: function() {
      this._ensureViewIsIntact();
      this._isRendering = true;
      this.resetChildViewContainer();
  
      this.triggerMethod('before:render', this);
  
      this._renderTemplate();
      this._renderChildren();
  
      this._isRendering = false;
      this.isRendered = true;
      this.triggerMethod('render', this);
      return this;
    },
  
    _renderChildren: function() {
      if (this.isRendered || this._isRendering) {
        Marionette.CollectionView.prototype._renderChildren.call(this);
      }
    },
  
    // Render the root template that the children
    // views are appended to
    _renderTemplate: function() {
      var data = {};
      data = this.serializeData();
      data = this.mixinTemplateHelpers(data);
  
      this.triggerMethod('before:render:template');
  
      var template = this.getTemplate();
      var html = Marionette.Renderer.render(template, data, this);
      this.attachElContent(html);
  
      // the ui bindings is done here and not at the end of render since they
      // will not be available until after the model is rendered, but should be
      // available before the collection is rendered.
      this.bindUIElements();
      this.triggerMethod('render:template');
    },
  
    // Attaches the content of the root.
    // This method can be overridden to optimize rendering,
    // or to render in a non standard way.
    //
    // For example, using `innerHTML` instead of `$el.html`
    //
    // ```js
    // attachElContent: function(html) {
    //   this.el.innerHTML = html;
    //   return this;
    // }
    // ```
    attachElContent: function(html) {
      this.$el.html(html);
  
      return this;
    },
  
    // You might need to override this if you've overridden attachHtml
    attachBuffer: function(compositeView, buffer) {
      var $container = this.getChildViewContainer(compositeView);
      $container.append(buffer);
    },
  
    // Internal method. Append a view to the end of the $el.
    // Overidden from CollectionView to ensure view is appended to
    // childViewContainer
    _insertAfter: function(childView) {
      var $container = this.getChildViewContainer(this, childView);
      $container.append(childView.el);
    },
  
    // Internal method. Append reordered childView'.
    // Overidden from CollectionView to ensure reordered views
    // are appended to childViewContainer
    _appendReorderedChildren: function(children) {
      var $container = this.getChildViewContainer(this);
      $container.append(children);
    },
  
    // Internal method to ensure an `$childViewContainer` exists, for the
    // `attachHtml` method to use.
    getChildViewContainer: function(containerView, childView) {
      if (!!containerView.$childViewContainer) {
        return containerView.$childViewContainer;
      }
  
      var container;
      var childViewContainer = Marionette.getOption(containerView, 'childViewContainer');
      if (childViewContainer) {
  
        var selector = Marionette._getValue(childViewContainer, containerView);
  
        if (selector.charAt(0) === '@' && containerView.ui) {
          container = containerView.ui[selector.substr(4)];
        } else {
          container = containerView.$(selector);
        }
  
        if (container.length <= 0) {
          throw new Marionette.Error({
            name: 'ChildViewContainerMissingError',
            message: 'The specified "childViewContainer" was not found: ' + containerView.childViewContainer
          });
        }
  
      } else {
        container = containerView.$el;
      }
  
      containerView.$childViewContainer = container;
      return container;
    },
  
    // Internal method to reset the `$childViewContainer` on render
    resetChildViewContainer: function() {
      if (this.$childViewContainer) {
        this.$childViewContainer = undefined;
      }
    }
  });
  
  // Layout View
  // -----------
  
  // Used for managing application layoutViews, nested layoutViews and
  // multiple regions within an application or sub-application.
  //
  // A specialized view class that renders an area of HTML and then
  // attaches `Region` instances to the specified `regions`.
  // Used for composite view management and sub-application areas.
  Marionette.LayoutView = Marionette.ItemView.extend({
    regionClass: Marionette.Region,
  
    options: {
      destroyImmediate: false
    },
  
    // used as the prefix for child view events
    // that are forwarded through the layoutview
    childViewEventPrefix: 'childview',
  
    // Ensure the regions are available when the `initialize` method
    // is called.
    constructor: function(options) {
      options = options || {};
  
      this._firstRender = true;
      this._initializeRegions(options);
  
      Marionette.ItemView.call(this, options);
    },
  
    // LayoutView's render will use the existing region objects the
    // first time it is called. Subsequent calls will destroy the
    // views that the regions are showing and then reset the `el`
    // for the regions to the newly rendered DOM elements.
    render: function() {
      this._ensureViewIsIntact();
  
      if (this._firstRender) {
        // if this is the first render, don't do anything to
        // reset the regions
        this._firstRender = false;
      } else {
        // If this is not the first render call, then we need to
        // re-initialize the `el` for each region
        this._reInitializeRegions();
      }
  
      return Marionette.ItemView.prototype.render.apply(this, arguments);
    },
  
    // Handle destroying regions, and then destroy the view itself.
    destroy: function() {
      if (this.isDestroyed) { return this; }
      // #2134: remove parent element before destroying the child views, so
      // removing the child views doesn't retrigger repaints
      if (this.getOption('destroyImmediate') === true) {
        this.$el.remove();
      }
      this.regionManager.destroy();
      return Marionette.ItemView.prototype.destroy.apply(this, arguments);
    },
  
    showChildView: function(regionName, view, options) {
      var region = this.getRegion(regionName);
      return region.show.apply(region, _.rest(arguments));
    },
  
    getChildView: function(regionName) {
      return this.getRegion(regionName).currentView;
    },
  
    // Add a single region, by name, to the layoutView
    addRegion: function(name, definition) {
      var regions = {};
      regions[name] = definition;
      return this._buildRegions(regions)[name];
    },
  
    // Add multiple regions as a {name: definition, name2: def2} object literal
    addRegions: function(regions) {
      this.regions = _.extend({}, this.regions, regions);
      return this._buildRegions(regions);
    },
  
    // Remove a single region from the LayoutView, by name
    removeRegion: function(name) {
      delete this.regions[name];
      return this.regionManager.removeRegion(name);
    },
  
    // Provides alternative access to regions
    // Accepts the region name
    // getRegion('main')
    getRegion: function(region) {
      return this.regionManager.get(region);
    },
  
    // Get all regions
    getRegions: function() {
      return this.regionManager.getRegions();
    },
  
    // internal method to build regions
    _buildRegions: function(regions) {
      var defaults = {
        regionClass: this.getOption('regionClass'),
        parentEl: _.partial(_.result, this, 'el')
      };
  
      return this.regionManager.addRegions(regions, defaults);
    },
  
    // Internal method to initialize the regions that have been defined in a
    // `regions` attribute on this layoutView.
    _initializeRegions: function(options) {
      var regions;
      this._initRegionManager();
  
      regions = Marionette._getValue(this.regions, this, [options]) || {};
  
      // Enable users to define `regions` as instance options.
      var regionOptions = this.getOption.call(options, 'regions');
  
      // enable region options to be a function
      regionOptions = Marionette._getValue(regionOptions, this, [options]);
  
      _.extend(regions, regionOptions);
  
      // Normalize region selectors hash to allow
      // a user to use the @ui. syntax.
      regions = this.normalizeUIValues(regions, ['selector', 'el']);
  
      this.addRegions(regions);
    },
  
    // Internal method to re-initialize all of the regions by updating the `el` that
    // they point to
    _reInitializeRegions: function() {
      this.regionManager.invoke('reset');
    },
  
    // Enable easy overriding of the default `RegionManager`
    // for customized region interactions and business specific
    // view logic for better control over single regions.
    getRegionManager: function() {
      return new Marionette.RegionManager();
    },
  
    // Internal method to initialize the region manager
    // and all regions in it
    _initRegionManager: function() {
      this.regionManager = this.getRegionManager();
      this.regionManager._parent = this;
  
      this.listenTo(this.regionManager, 'before:add:region', function(name) {
        this.triggerMethod('before:add:region', name);
      });
  
      this.listenTo(this.regionManager, 'add:region', function(name, region) {
        this[name] = region;
        this.triggerMethod('add:region', name, region);
      });
  
      this.listenTo(this.regionManager, 'before:remove:region', function(name) {
        this.triggerMethod('before:remove:region', name);
      });
  
      this.listenTo(this.regionManager, 'remove:region', function(name, region) {
        delete this[name];
        this.triggerMethod('remove:region', name, region);
      });
    },
  
    _getImmediateChildren: function() {
      return _.chain(this.regionManager.getRegions())
        .pluck('currentView')
        .compact()
        .value();
    }
  });
  

  // Behavior
  // --------
  
  // A Behavior is an isolated set of DOM /
  // user interactions that can be mixed into any View.
  // Behaviors allow you to blackbox View specific interactions
  // into portable logical chunks, keeping your views simple and your code DRY.
  
  Marionette.Behavior = Marionette.Object.extend({
    constructor: function(options, view) {
      // Setup reference to the view.
      // this comes in handle when a behavior
      // wants to directly talk up the chain
      // to the view.
      this.view = view;
      this.defaults = _.result(this, 'defaults') || {};
      this.options  = _.extend({}, this.defaults, options);
      // Construct an internal UI hash using
      // the views UI hash and then the behaviors UI hash.
      // This allows the user to use UI hash elements
      // defined in the parent view as well as those
      // defined in the given behavior.
      this.ui = _.extend({}, _.result(view, 'ui'), _.result(this, 'ui'));
  
      Marionette.Object.apply(this, arguments);
    },
  
    // proxy behavior $ method to the view
    // this is useful for doing jquery DOM lookups
    // scoped to behaviors view.
    $: function() {
      return this.view.$.apply(this.view, arguments);
    },
  
    // Stops the behavior from listening to events.
    // Overrides Object#destroy to prevent additional events from being triggered.
    destroy: function() {
      this.stopListening();
  
      return this;
    },
  
    proxyViewProperties: function(view) {
      this.$el = view.$el;
      this.el = view.el;
    }
  });
  
  /* jshint maxlen: 143 */
  // Behaviors
  // ---------
  
  // Behaviors is a utility class that takes care of
  // gluing your behavior instances to their given View.
  // The most important part of this class is that you
  // **MUST** override the class level behaviorsLookup
  // method for things to work properly.
  
  Marionette.Behaviors = (function(Marionette, _) {
    // Borrow event splitter from Backbone
    var delegateEventSplitter = /^(\S+)\s*(.*)$/;
  
    function Behaviors(view, behaviors) {
  
      if (!_.isObject(view.behaviors)) {
        return {};
      }
  
      // Behaviors defined on a view can be a flat object literal
      // or it can be a function that returns an object.
      behaviors = Behaviors.parseBehaviors(view, behaviors || _.result(view, 'behaviors'));
  
      // Wraps several of the view's methods
      // calling the methods first on each behavior
      // and then eventually calling the method on the view.
      Behaviors.wrap(view, behaviors, _.keys(methods));
      return behaviors;
    }
  
    var methods = {
      behaviorTriggers: function(behaviorTriggers, behaviors) {
        var triggerBuilder = new BehaviorTriggersBuilder(this, behaviors);
        return triggerBuilder.buildBehaviorTriggers();
      },
  
      behaviorEvents: function(behaviorEvents, behaviors) {
        var _behaviorsEvents = {};
  
        _.each(behaviors, function(b, i) {
          var _events = {};
          var behaviorEvents = _.clone(_.result(b, 'events')) || {};
  
          // Normalize behavior events hash to allow
          // a user to use the @ui. syntax.
          behaviorEvents = Marionette.normalizeUIKeys(behaviorEvents, getBehaviorsUI(b));
  
          var j = 0;
          _.each(behaviorEvents, function(behaviour, key) {
            var match     = key.match(delegateEventSplitter);
  
            // Set event name to be namespaced using the view cid,
            // the behavior index, and the behavior event index
            // to generate a non colliding event namespace
            // http://api.jquery.com/event.namespace/
            var eventName = match[1] + '.' + [this.cid, i, j++, ' '].join('');
            var selector  = match[2];
  
            var eventKey  = eventName + selector;
            var handler   = _.isFunction(behaviour) ? behaviour : b[behaviour];
            if (!handler) { return; }
            _events[eventKey] = _.bind(handler, b);
          }, this);
  
          _behaviorsEvents = _.extend(_behaviorsEvents, _events);
        }, this);
  
        return _behaviorsEvents;
      }
    };
  
    _.extend(Behaviors, {
  
      // Placeholder method to be extended by the user.
      // The method should define the object that stores the behaviors.
      // i.e.
      //
      // ```js
      // Marionette.Behaviors.behaviorsLookup: function() {
      //   return App.Behaviors
      // }
      // ```
      behaviorsLookup: function() {
        throw new Marionette.Error({
          message: 'You must define where your behaviors are stored.',
          url: 'marionette.behaviors.html#behaviorslookup'
        });
      },
  
      // Takes care of getting the behavior class
      // given options and a key.
      // If a user passes in options.behaviorClass
      // default to using that. Otherwise delegate
      // the lookup to the users `behaviorsLookup` implementation.
      getBehaviorClass: function(options, key) {
        if (options.behaviorClass) {
          return options.behaviorClass;
        }
  
        // Get behavior class can be either a flat object or a method
        return Marionette._getValue(Behaviors.behaviorsLookup, this, [options, key])[key];
      },
  
      // Iterate over the behaviors object, for each behavior
      // instantiate it and get its grouped behaviors.
      parseBehaviors: function(view, behaviors) {
        return _.chain(behaviors).map(function(options, key) {
          var BehaviorClass = Behaviors.getBehaviorClass(options, key);
  
          var behavior = new BehaviorClass(options, view);
          var nestedBehaviors = Behaviors.parseBehaviors(view, _.result(behavior, 'behaviors'));
  
          return [behavior].concat(nestedBehaviors);
        }).flatten().value();
      },
  
      // Wrap view internal methods so that they delegate to behaviors. For example,
      // `onDestroy` should trigger destroy on all of the behaviors and then destroy itself.
      // i.e.
      //
      // `view.delegateEvents = _.partial(methods.delegateEvents, view.delegateEvents, behaviors);`
      wrap: function(view, behaviors, methodNames) {
        _.each(methodNames, function(methodName) {
          view[methodName] = _.partial(methods[methodName], view[methodName], behaviors);
        });
      }
    });
  
    // Class to build handlers for `triggers` on behaviors
    // for views
    function BehaviorTriggersBuilder(view, behaviors) {
      this._view      = view;
      this._behaviors = behaviors;
      this._triggers  = {};
    }
  
    _.extend(BehaviorTriggersBuilder.prototype, {
      // Main method to build the triggers hash with event keys and handlers
      buildBehaviorTriggers: function() {
        _.each(this._behaviors, this._buildTriggerHandlersForBehavior, this);
        return this._triggers;
      },
  
      // Internal method to build all trigger handlers for a given behavior
      _buildTriggerHandlersForBehavior: function(behavior, i) {
        var triggersHash = _.clone(_.result(behavior, 'triggers')) || {};
  
        triggersHash = Marionette.normalizeUIKeys(triggersHash, getBehaviorsUI(behavior));
  
        _.each(triggersHash, _.bind(this._setHandlerForBehavior, this, behavior, i));
      },
  
      // Internal method to create and assign the trigger handler for a given
      // behavior
      _setHandlerForBehavior: function(behavior, i, eventName, trigger) {
        // Unique identifier for the `this._triggers` hash
        var triggerKey = trigger.replace(/^\S+/, function(triggerName) {
          return triggerName + '.' + 'behaviortriggers' + i;
        });
  
        this._triggers[triggerKey] = this._view._buildViewTrigger(eventName);
      }
    });
  
    function getBehaviorsUI(behavior) {
      return behavior._uiBindings || behavior.ui;
    }
  
    return Behaviors;
  
  })(Marionette, _);
  

  // App Router
  // ----------
  
  // Reduce the boilerplate code of handling route events
  // and then calling a single method on another object.
  // Have your routers configured to call the method on
  // your object, directly.
  //
  // Configure an AppRouter with `appRoutes`.
  //
  // App routers can only take one `controller` object.
  // It is recommended that you divide your controller
  // objects in to smaller pieces of related functionality
  // and have multiple routers / controllers, instead of
  // just one giant router and controller.
  //
  // You can also add standard routes to an AppRouter.
  
  Marionette.AppRouter = Backbone.Router.extend({
  
    constructor: function(options) {
      this.options = options || {};
  
      Backbone.Router.apply(this, arguments);
  
      var appRoutes = this.getOption('appRoutes');
      var controller = this._getController();
      this.processAppRoutes(controller, appRoutes);
      this.on('route', this._processOnRoute, this);
    },
  
    // Similar to route method on a Backbone Router but
    // method is called on the controller
    appRoute: function(route, methodName) {
      var controller = this._getController();
      this._addAppRoute(controller, route, methodName);
    },
  
    // process the route event and trigger the onRoute
    // method call, if it exists
    _processOnRoute: function(routeName, routeArgs) {
      // make sure an onRoute before trying to call it
      if (_.isFunction(this.onRoute)) {
        // find the path that matches the current route
        var routePath = _.invert(this.getOption('appRoutes'))[routeName];
        this.onRoute(routeName, routePath, routeArgs);
      }
    },
  
    // Internal method to process the `appRoutes` for the
    // router, and turn them in to routes that trigger the
    // specified method on the specified `controller`.
    processAppRoutes: function(controller, appRoutes) {
      if (!appRoutes) { return; }
  
      var routeNames = _.keys(appRoutes).reverse(); // Backbone requires reverted order of routes
  
      _.each(routeNames, function(route) {
        this._addAppRoute(controller, route, appRoutes[route]);
      }, this);
    },
  
    _getController: function() {
      return this.getOption('controller');
    },
  
    _addAppRoute: function(controller, route, methodName) {
      var method = controller[methodName];
  
      if (!method) {
        throw new Marionette.Error('Method "' + methodName + '" was not found on the controller');
      }
  
      this.route(route, methodName, _.bind(method, controller));
    },
  
    mergeOptions: Marionette.mergeOptions,
  
    // Proxy `getOption` to enable getting options from this or this.options by name.
    getOption: Marionette.proxyGetOption,
  
    triggerMethod: Marionette.triggerMethod,
  
    bindEntityEvents: Marionette.proxyBindEntityEvents,
  
    unbindEntityEvents: Marionette.proxyUnbindEntityEvents
  });
  
  // Application
  // -----------
  
  // Contain and manage the composite application as a whole.
  // Stores and starts up `Region` objects, includes an
  // event aggregator as `app.vent`
  Marionette.Application = Marionette.Object.extend({
    constructor: function(options) {
      this._initializeRegions(options);
      this._initCallbacks = new Marionette.Callbacks();
      this.submodules = {};
      _.extend(this, options);
      this._initChannel();
      Marionette.Object.apply(this, arguments);
    },
  
    // Command execution, facilitated by Backbone.Wreqr.Commands
    execute: function() {
      this.commands.execute.apply(this.commands, arguments);
    },
  
    // Request/response, facilitated by Backbone.Wreqr.RequestResponse
    request: function() {
      return this.reqres.request.apply(this.reqres, arguments);
    },
  
    // Add an initializer that is either run at when the `start`
    // method is called, or run immediately if added after `start`
    // has already been called.
    addInitializer: function(initializer) {
      this._initCallbacks.add(initializer);
    },
  
    // kick off all of the application's processes.
    // initializes all of the regions that have been added
    // to the app, and runs all of the initializer functions
    start: function(options) {
      this.triggerMethod('before:start', options);
      this._initCallbacks.run(options, this);
      this.triggerMethod('start', options);
    },
  
    // Add regions to your app.
    // Accepts a hash of named strings or Region objects
    // addRegions({something: "#someRegion"})
    // addRegions({something: Region.extend({el: "#someRegion"}) });
    addRegions: function(regions) {
      return this._regionManager.addRegions(regions);
    },
  
    // Empty all regions in the app, without removing them
    emptyRegions: function() {
      return this._regionManager.emptyRegions();
    },
  
    // Removes a region from your app, by name
    // Accepts the regions name
    // removeRegion('myRegion')
    removeRegion: function(region) {
      return this._regionManager.removeRegion(region);
    },
  
    // Provides alternative access to regions
    // Accepts the region name
    // getRegion('main')
    getRegion: function(region) {
      return this._regionManager.get(region);
    },
  
    // Get all the regions from the region manager
    getRegions: function() {
      return this._regionManager.getRegions();
    },
  
    // Create a module, attached to the application
    module: function(moduleNames, moduleDefinition) {
  
      // Overwrite the module class if the user specifies one
      var ModuleClass = Marionette.Module.getClass(moduleDefinition);
  
      var args = _.toArray(arguments);
      args.unshift(this);
  
      // see the Marionette.Module object for more information
      return ModuleClass.create.apply(ModuleClass, args);
    },
  
    // Enable easy overriding of the default `RegionManager`
    // for customized region interactions and business-specific
    // view logic for better control over single regions.
    getRegionManager: function() {
      return new Marionette.RegionManager();
    },
  
    // Internal method to initialize the regions that have been defined in a
    // `regions` attribute on the application instance
    _initializeRegions: function(options) {
      var regions = _.isFunction(this.regions) ? this.regions(options) : this.regions || {};
  
      this._initRegionManager();
  
      // Enable users to define `regions` in instance options.
      var optionRegions = Marionette.getOption(options, 'regions');
  
      // Enable region options to be a function
      if (_.isFunction(optionRegions)) {
        optionRegions = optionRegions.call(this, options);
      }
  
      // Overwrite current regions with those passed in options
      _.extend(regions, optionRegions);
  
      this.addRegions(regions);
  
      return this;
    },
  
    // Internal method to set up the region manager
    _initRegionManager: function() {
      this._regionManager = this.getRegionManager();
      this._regionManager._parent = this;
  
      this.listenTo(this._regionManager, 'before:add:region', function() {
        Marionette._triggerMethod(this, 'before:add:region', arguments);
      });
  
      this.listenTo(this._regionManager, 'add:region', function(name, region) {
        this[name] = region;
        Marionette._triggerMethod(this, 'add:region', arguments);
      });
  
      this.listenTo(this._regionManager, 'before:remove:region', function() {
        Marionette._triggerMethod(this, 'before:remove:region', arguments);
      });
  
      this.listenTo(this._regionManager, 'remove:region', function(name) {
        delete this[name];
        Marionette._triggerMethod(this, 'remove:region', arguments);
      });
    },
  
    // Internal method to setup the Wreqr.radio channel
    _initChannel: function() {
      this.channelName = _.result(this, 'channelName') || 'global';
      this.channel = _.result(this, 'channel') || Backbone.Wreqr.radio.channel(this.channelName);
      this.vent = _.result(this, 'vent') || this.channel.vent;
      this.commands = _.result(this, 'commands') || this.channel.commands;
      this.reqres = _.result(this, 'reqres') || this.channel.reqres;
    }
  });
  
  /* jshint maxparams: 9 */
  
  // Module
  // ------
  
  // A simple module system, used to create privacy and encapsulation in
  // Marionette applications
  Marionette.Module = function(moduleName, app, options) {
    this.moduleName = moduleName;
    this.options = _.extend({}, this.options, options);
    // Allow for a user to overide the initialize
    // for a given module instance.
    this.initialize = options.initialize || this.initialize;
  
    // Set up an internal store for sub-modules.
    this.submodules = {};
  
    this._setupInitializersAndFinalizers();
  
    // Set an internal reference to the app
    // within a module.
    this.app = app;
  
    if (_.isFunction(this.initialize)) {
      this.initialize(moduleName, app, this.options);
    }
  };
  
  Marionette.Module.extend = Marionette.extend;
  
  // Extend the Module prototype with events / listenTo, so that the module
  // can be used as an event aggregator or pub/sub.
  _.extend(Marionette.Module.prototype, Backbone.Events, {
  
    // By default modules start with their parents.
    startWithParent: true,
  
    // Initialize is an empty function by default. Override it with your own
    // initialization logic when extending Marionette.Module.
    initialize: function() {},
  
    // Initializer for a specific module. Initializers are run when the
    // module's `start` method is called.
    addInitializer: function(callback) {
      this._initializerCallbacks.add(callback);
    },
  
    // Finalizers are run when a module is stopped. They are used to teardown
    // and finalize any variables, references, events and other code that the
    // module had set up.
    addFinalizer: function(callback) {
      this._finalizerCallbacks.add(callback);
    },
  
    // Start the module, and run all of its initializers
    start: function(options) {
      // Prevent re-starting a module that is already started
      if (this._isInitialized) { return; }
  
      // start the sub-modules (depth-first hierarchy)
      _.each(this.submodules, function(mod) {
        // check to see if we should start the sub-module with this parent
        if (mod.startWithParent) {
          mod.start(options);
        }
      });
  
      // run the callbacks to "start" the current module
      this.triggerMethod('before:start', options);
  
      this._initializerCallbacks.run(options, this);
      this._isInitialized = true;
  
      this.triggerMethod('start', options);
    },
  
    // Stop this module by running its finalizers and then stop all of
    // the sub-modules for this module
    stop: function() {
      // if we are not initialized, don't bother finalizing
      if (!this._isInitialized) { return; }
      this._isInitialized = false;
  
      this.triggerMethod('before:stop');
  
      // stop the sub-modules; depth-first, to make sure the
      // sub-modules are stopped / finalized before parents
      _.invoke(this.submodules, 'stop');
  
      // run the finalizers
      this._finalizerCallbacks.run(undefined, this);
  
      // reset the initializers and finalizers
      this._initializerCallbacks.reset();
      this._finalizerCallbacks.reset();
  
      this.triggerMethod('stop');
    },
  
    // Configure the module with a definition function and any custom args
    // that are to be passed in to the definition function
    addDefinition: function(moduleDefinition, customArgs) {
      this._runModuleDefinition(moduleDefinition, customArgs);
    },
  
    // Internal method: run the module definition function with the correct
    // arguments
    _runModuleDefinition: function(definition, customArgs) {
      // If there is no definition short circut the method.
      if (!definition) { return; }
  
      // build the correct list of arguments for the module definition
      var args = _.flatten([
        this,
        this.app,
        Backbone,
        Marionette,
        Backbone.$, _,
        customArgs
      ]);
  
      definition.apply(this, args);
    },
  
    // Internal method: set up new copies of initializers and finalizers.
    // Calling this method will wipe out all existing initializers and
    // finalizers.
    _setupInitializersAndFinalizers: function() {
      this._initializerCallbacks = new Marionette.Callbacks();
      this._finalizerCallbacks = new Marionette.Callbacks();
    },
  
    // import the `triggerMethod` to trigger events with corresponding
    // methods if the method exists
    triggerMethod: Marionette.triggerMethod
  });
  
  // Class methods to create modules
  _.extend(Marionette.Module, {
  
    // Create a module, hanging off the app parameter as the parent object.
    create: function(app, moduleNames, moduleDefinition) {
      var module = app;
  
      // get the custom args passed in after the module definition and
      // get rid of the module name and definition function
      var customArgs = _.drop(arguments, 3);
  
      // Split the module names and get the number of submodules.
      // i.e. an example module name of `Doge.Wow.Amaze` would
      // then have the potential for 3 module definitions.
      moduleNames = moduleNames.split('.');
      var length = moduleNames.length;
  
      // store the module definition for the last module in the chain
      var moduleDefinitions = [];
      moduleDefinitions[length - 1] = moduleDefinition;
  
      // Loop through all the parts of the module definition
      _.each(moduleNames, function(moduleName, i) {
        var parentModule = module;
        module = this._getModule(parentModule, moduleName, app, moduleDefinition);
        this._addModuleDefinition(parentModule, module, moduleDefinitions[i], customArgs);
      }, this);
  
      // Return the last module in the definition chain
      return module;
    },
  
    _getModule: function(parentModule, moduleName, app, def, args) {
      var options = _.extend({}, def);
      var ModuleClass = this.getClass(def);
  
      // Get an existing module of this name if we have one
      var module = parentModule[moduleName];
  
      if (!module) {
        // Create a new module if we don't have one
        module = new ModuleClass(moduleName, app, options);
        parentModule[moduleName] = module;
        // store the module on the parent
        parentModule.submodules[moduleName] = module;
      }
  
      return module;
    },
  
    // ## Module Classes
    //
    // Module classes can be used as an alternative to the define pattern.
    // The extend function of a Module is identical to the extend functions
    // on other Backbone and Marionette classes.
    // This allows module lifecyle events like `onStart` and `onStop` to be called directly.
    getClass: function(moduleDefinition) {
      var ModuleClass = Marionette.Module;
  
      if (!moduleDefinition) {
        return ModuleClass;
      }
  
      // If all of the module's functionality is defined inside its class,
      // then the class can be passed in directly. `MyApp.module("Foo", FooModule)`.
      if (moduleDefinition.prototype instanceof ModuleClass) {
        return moduleDefinition;
      }
  
      return moduleDefinition.moduleClass || ModuleClass;
    },
  
    // Add the module definition and add a startWithParent initializer function.
    // This is complicated because module definitions are heavily overloaded
    // and support an anonymous function, module class, or options object
    _addModuleDefinition: function(parentModule, module, def, args) {
      var fn = this._getDefine(def);
      var startWithParent = this._getStartWithParent(def, module);
  
      if (fn) {
        module.addDefinition(fn, args);
      }
  
      this._addStartWithParent(parentModule, module, startWithParent);
    },
  
    _getStartWithParent: function(def, module) {
      var swp;
  
      if (_.isFunction(def) && (def.prototype instanceof Marionette.Module)) {
        swp = module.constructor.prototype.startWithParent;
        return _.isUndefined(swp) ? true : swp;
      }
  
      if (_.isObject(def)) {
        swp = def.startWithParent;
        return _.isUndefined(swp) ? true : swp;
      }
  
      return true;
    },
  
    _getDefine: function(def) {
      if (_.isFunction(def) && !(def.prototype instanceof Marionette.Module)) {
        return def;
      }
  
      if (_.isObject(def)) {
        return def.define;
      }
  
      return null;
    },
  
    _addStartWithParent: function(parentModule, module, startWithParent) {
      module.startWithParent = module.startWithParent && startWithParent;
  
      if (!module.startWithParent || !!module.startWithParentIsConfigured) {
        return;
      }
  
      module.startWithParentIsConfigured = true;
  
      parentModule.addInitializer(function(options) {
        if (module.startWithParent) {
          module.start(options);
        }
      });
    }
  });
  

  return Marionette;
}));
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab: */
/**
 * Backbone-relational.js 0.10.0
 * (c) 2011-2014 Paul Uithol and contributors (https://github.com/PaulUithol/Backbone-relational/graphs/contributors)
 *
 * Backbone-relational may be freely distributed under the MIT license; see the accompanying LICENSE.txt.
 * For details and documentation: https://github.com/PaulUithol/Backbone-relational.
 * Depends on Backbone (and thus on Underscore as well): https://github.com/documentcloud/backbone.
 *
 * Example:
 *
	Zoo = Backbone.RelationalModel.extend({
		relations: [ {
			type: Backbone.HasMany,
			key: 'animals',
			relatedModel: 'Animal',
			reverseRelation: {
				key: 'livesIn',
				includeInJSON: 'id'
				// 'relatedModel' is automatically set to 'Zoo'; the 'relationType' to 'HasOne'.
			}
		} ],

		toString: function() {
			return this.get( 'name' );
		}
	});

	Animal = Backbone.RelationalModel.extend({
		toString: function() {
			return this.get( 'species' );
		}
	});

	// Creating the zoo will give it a collection with one animal in it: the monkey.
	// The animal created after that has a relation `livesIn` that points to the zoo it's currently associated with.
	// If you instantiate (or fetch) the zebra later, it will automatically be added.

	var zoo = new Zoo({
		name: 'Artis',
		animals: [ { id: 'monkey-1', species: 'Chimp' }, 'lion-1', 'zebra-1' ]
	});

	var lion = new Animal( { id: 'lion-1', species: 'Lion' } ),
		monkey = zoo.get( 'animals' ).first(),
		sameZoo = lion.get( 'livesIn' );
 */
( function( root, factory ) {
	// Set up Backbone-relational for the environment. Start with AMD.
	if ( true ) {
		!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ exports, __webpack_require__(6), __webpack_require__(5) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	}
	// Next for Node.js or CommonJS.
	else {}
}( this, function( exports, Backbone, _ ) {
	"use strict";

	Backbone.Relational = {
		showWarnings: true
	};

	/**
	 * Semaphore mixin; can be used as both binary and counting.
	 **/
	Backbone.Semaphore = {
		_permitsAvailable: null,
		_permitsUsed: 0,

		acquire: function() {
			if ( this._permitsAvailable && this._permitsUsed >= this._permitsAvailable ) {
				throw new Error( 'Max permits acquired' );
			}
			else {
				this._permitsUsed++;
			}
		},

		release: function() {
			if ( this._permitsUsed === 0 ) {
				throw new Error( 'All permits released' );
			}
			else {
				this._permitsUsed--;
			}
		},

		isLocked: function() {
			return this._permitsUsed > 0;
		},

		setAvailablePermits: function( amount ) {
			if ( this._permitsUsed > amount ) {
				throw new Error( 'Available permits cannot be less than used permits' );
			}
			this._permitsAvailable = amount;
		}
	};

	/**
	 * A BlockingQueue that accumulates items while blocked (via 'block'),
	 * and processes them when unblocked (via 'unblock').
	 * Process can also be called manually (via 'process').
	 */
	Backbone.BlockingQueue = function() {
		this._queue = [];
	};
	_.extend( Backbone.BlockingQueue.prototype, Backbone.Semaphore, {
		_queue: null,

		add: function( func ) {
			if ( this.isBlocked() ) {
				this._queue.push( func );
			}
			else {
				func();
			}
		},

		// Some of the queued events may trigger other blocking events. By
		// copying the queue here it allows queued events to process closer to
		// the natural order.
		//
		// queue events [ 'A', 'B', 'C' ]
		// A handler of 'B' triggers 'D' and 'E'
		// By copying `this._queue` this executes:
		// [ 'A', 'B', 'D', 'E', 'C' ]
		// The same order the would have executed if they didn't have to be
		// delayed and queued.
		process: function() {
			var queue = this._queue;
			this._queue = [];
			while ( queue && queue.length ) {
				queue.shift()();
			}
		},

		block: function() {
			this.acquire();
		},

		unblock: function() {
			this.release();
			if ( !this.isBlocked() ) {
				this.process();
			}
		},

		isBlocked: function() {
			return this.isLocked();
		}
	});
	/**
	 * Global event queue. Accumulates external events ('add:<key>', 'remove:<key>' and 'change:<key>')
	 * until the top-level object is fully initialized (see 'Backbone.RelationalModel').
	 */
	Backbone.Relational.eventQueue = new Backbone.BlockingQueue();

	/**
	 * Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel.
	 * Handles lookup for relations.
	 */
	Backbone.Store = function() {
		this._collections = [];
		this._reverseRelations = [];
		this._orphanRelations = [];
		this._subModels = [];
		this._modelScopes = [ exports ];
	};
	_.extend( Backbone.Store.prototype, Backbone.Events, {
		/**
		 * Create a new `Relation`.
		 * @param {Backbone.RelationalModel} [model]
		 * @param {Object} relation
		 * @param {Object} [options]
		 */
		initializeRelation: function( model, relation, options ) {
			var type = !_.isString( relation.type ) ? relation.type : Backbone[ relation.type ] || this.getObjectByName( relation.type );
			if ( type && type.prototype instanceof Backbone.Relation ) {
				var rel = new type( model, relation, options ); // Also pushes the new Relation into `model._relations`
			}
			else {
				Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn( 'Relation=%o; missing or invalid relation type!', relation );
			}
		},

		/**
		 * Add a scope for `getObjectByName` to look for model types by name.
		 * @param {Object} scope
		 */
		addModelScope: function( scope ) {
			this._modelScopes.push( scope );
		},

		/**
		 * Remove a scope.
		 * @param {Object} scope
		 */
		removeModelScope: function( scope ) {
			this._modelScopes = _.without( this._modelScopes, scope );
		},

		/**
		 * Add a set of subModelTypes to the store, that can be used to resolve the '_superModel'
		 * for a model later in 'setupSuperModel'.
		 *
		 * @param {Backbone.RelationalModel} subModelTypes
		 * @param {Backbone.RelationalModel} superModelType
		 */
		addSubModels: function( subModelTypes, superModelType ) {
			this._subModels.push({
				'superModelType': superModelType,
				'subModels': subModelTypes
			});
		},

		/**
		 * Check if the given modelType is registered as another model's subModel. If so, add it to the super model's
		 * '_subModels', and set the modelType's '_superModel', '_subModelTypeName', and '_subModelTypeAttribute'.
		 *
		 * @param {Backbone.RelationalModel} modelType
		 */
		setupSuperModel: function( modelType ) {
			_.find( this._subModels, function( subModelDef ) {
				return _.filter( subModelDef.subModels || [], function( subModelTypeName, typeValue ) {
					var subModelType = this.getObjectByName( subModelTypeName );

					if ( modelType === subModelType ) {
						// Set 'modelType' as a child of the found superModel
						subModelDef.superModelType._subModels[ typeValue ] = modelType;

						// Set '_superModel', '_subModelTypeValue', and '_subModelTypeAttribute' on 'modelType'.
						modelType._superModel = subModelDef.superModelType;
						modelType._subModelTypeValue = typeValue;
						modelType._subModelTypeAttribute = subModelDef.superModelType.prototype.subModelTypeAttribute;
						return true;
					}
				}, this ).length;
			}, this );
		},

		/**
		 * Add a reverse relation. Is added to the 'relations' property on model's prototype, and to
		 * existing instances of 'model' in the store as well.
		 * @param {Object} relation
		 * @param {Backbone.RelationalModel} relation.model
		 * @param {String} relation.type
		 * @param {String} relation.key
		 * @param {String|Object} relation.relatedModel
		 */
		addReverseRelation: function( relation ) {
			var exists = _.any( this._reverseRelations, function( rel ) {
				return _.all( relation || [], function( val, key ) {
					return val === rel[ key ];
				});
			});

			if ( !exists && relation.model && relation.type ) {
				this._reverseRelations.push( relation );
				this._addRelation( relation.model, relation );
				this.retroFitRelation( relation );
			}
		},

		/**
		 * Deposit a `relation` for which the `relatedModel` can't be resolved at the moment.
		 *
		 * @param {Object} relation
		 */
		addOrphanRelation: function( relation ) {
			var exists = _.any( this._orphanRelations, function( rel ) {
				return _.all( relation || [], function( val, key ) {
					return val === rel[ key ];
				});
			});

			if ( !exists && relation.model && relation.type ) {
				this._orphanRelations.push( relation );
			}
		},

		/**
		 * Try to initialize any `_orphanRelation`s
		 */
		processOrphanRelations: function() {
			// Make sure to operate on a copy since we're removing while iterating
			_.each( this._orphanRelations.slice( 0 ), function( rel ) {
				var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
				if ( relatedModel ) {
					this.initializeRelation( null, rel );
					this._orphanRelations = _.without( this._orphanRelations, rel );
				}
			}, this );
		},

		/**
		 *
		 * @param {Backbone.RelationalModel.constructor} type
		 * @param {Object} relation
		 * @private
		 */
		_addRelation: function( type, relation ) {
			if ( !type.prototype.relations ) {
				type.prototype.relations = [];
			}
			type.prototype.relations.push( relation );

			_.each( type._subModels || [], function( subModel ) {
				this._addRelation( subModel, relation );
			}, this );
		},

		/**
		 * Add a 'relation' to all existing instances of 'relation.model' in the store
		 * @param {Object} relation
		 */
		retroFitRelation: function( relation ) {
			var coll = this.getCollection( relation.model, false );
			coll && coll.each( function( model ) {
				if ( !( model instanceof relation.model ) ) {
					return;
				}

				var rel = new relation.type( model, relation );
			}, this );
		},

		/**
		 * Find the Store's collection for a certain type of model.
		 * @param {Backbone.RelationalModel} type
		 * @param {Boolean} [create=true] Should a collection be created if none is found?
		 * @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null
		 */
		getCollection: function( type, create ) {
			if ( type instanceof Backbone.RelationalModel ) {
				type = type.constructor;
			}

			var rootModel = type;
			while ( rootModel._superModel ) {
				rootModel = rootModel._superModel;
			}

			var coll = _.find( this._collections, function( item ) {
				return item.model === rootModel;
			});

			if ( !coll && create !== false ) {
				coll = this._createCollection( rootModel );
			}

			return coll;
		},

		/**
		 * Find a model type on one of the modelScopes by name. Names are split on dots.
		 * @param {String} name
		 * @return {Object}
		 */
		getObjectByName: function( name ) {
			var parts = name.split( '.' ),
				type = null;

			_.find( this._modelScopes, function( scope ) {
				type = _.reduce( parts || [], function( memo, val ) {
					return memo ? memo[ val ] : undefined;
				}, scope );

				if ( type && type !== scope ) {
					return true;
				}
			}, this );

			return type;
		},

		_createCollection: function( type ) {
			var coll;

			// If 'type' is an instance, take its constructor
			if ( type instanceof Backbone.RelationalModel ) {
				type = type.constructor;
			}

			// Type should inherit from Backbone.RelationalModel.
			if ( type.prototype instanceof Backbone.RelationalModel ) {
				coll = new Backbone.Collection();
				coll.model = type;

				this._collections.push( coll );
			}

			return coll;
		},

		/**
		 * Find the attribute that is to be used as the `id` on a given object
		 * @param type
		 * @param {String|Number|Object|Backbone.RelationalModel} item
		 * @return {String|Number}
		 */
		resolveIdForItem: function( type, item ) {
			var id = _.isString( item ) || _.isNumber( item ) ? item : null;

			if ( id === null ) {
				if ( item instanceof Backbone.RelationalModel ) {
					id = item.id;
				}
				else if ( _.isObject( item ) ) {
					id = item[ type.prototype.idAttribute ];
				}
			}

			// Make all falsy values `null` (except for 0, which could be an id.. see '/issues/179')
			if ( !id && id !== 0 ) {
				id = null;
			}

			return id;
		},

		/**
		 * Find a specific model of a certain `type` in the store
		 * @param type
		 * @param {String|Number|Object|Backbone.RelationalModel} item
		 */
		find: function( type, item ) {
			var id = this.resolveIdForItem( type, item ),
				coll = this.getCollection( type );

			// Because the found object could be of any of the type's superModel
			// types, only return it if it's actually of the type asked for.
			if ( coll ) {
				var obj = coll.get( id );

				if ( obj instanceof type ) {
					return obj;
				}
			}

			return null;
		},

		/**
		 * Add a 'model' to its appropriate collection. Retain the original contents of 'model.collection'.
		 * @param {Backbone.RelationalModel} model
		 */
		register: function( model ) {
			var coll = this.getCollection( model );

			if ( coll ) {
				var modelColl = model.collection;
				coll.add( model );
				model.collection = modelColl;
			}
		},

		/**
		 * Check if the given model may use the given `id`
		 * @param model
		 * @param [id]
		 */
		checkId: function( model, id ) {
			var coll = this.getCollection( model ),
				duplicate = coll && coll.get( id );

			if ( duplicate && model !== duplicate ) {
				if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
					console.warn( 'Duplicate id! Old RelationalModel=%o, new RelationalModel=%o', duplicate, model );
				}

				throw new Error( "Cannot instantiate more than one Backbone.RelationalModel with the same id per type!" );
			}
		},

		/**
		 * Explicitly update a model's id in its store collection
		 * @param {Backbone.RelationalModel} model
		 */
		update: function( model ) {
			var coll = this.getCollection( model );

			// Register a model if it isn't yet (which happens if it was created without an id).
			if ( !coll.contains( model ) ) {
				this.register( model );
			}

			// This triggers updating the lookup indices kept in a collection
			coll._onModelEvent( 'change:' + model.idAttribute, model, coll );

			// Trigger an event on model so related models (having the model's new id in their keyContents) can add it.
			model.trigger( 'relational:change:id', model, coll );
		},

		/**
		 * Unregister from the store: a specific model, a collection, or a model type.
		 * @param {Backbone.RelationalModel|Backbone.RelationalModel.constructor|Backbone.Collection} type
		 */
		unregister: function( type ) {
			var coll,
				models;

			if ( type instanceof Backbone.Model ) {
				coll = this.getCollection( type );
				models = [ type ];
			}
			else if ( type instanceof Backbone.Collection ) {
				coll = this.getCollection( type.model );
				models = _.clone( type.models );
			}
			else {
				coll = this.getCollection( type );
				models = _.clone( coll.models );
			}

			_.each( models, function( model ) {
				this.stopListening( model );
				_.invoke( model.getRelations(), 'stopListening' );
			}, this );


			// If we've unregistered an entire store collection, reset the collection (which is much faster).
			// Otherwise, remove each model one by one.
			if ( _.contains( this._collections, type ) ) {
				coll.reset( [] );
			}
			else {
				_.each( models, function( model ) {
					if ( coll.get( model ) ) {
						coll.remove( model );
					}
					else {
						coll.trigger( 'relational:remove', model, coll );
					}
				}, this );
			}
		},

		/**
		 * Reset the `store` to it's original state. The `reverseRelations` are kept though, since attempting to
		 * re-initialize these on models would lead to a large amount of warnings.
		 */
		reset: function() {
			this.stopListening();

			// Unregister each collection to remove event listeners
			_.each( this._collections, function( coll ) {
				this.unregister( coll );
			}, this );

			this._collections = [];
			this._subModels = [];
			this._modelScopes = [ exports ];
		}
	});
	Backbone.Relational.store = new Backbone.Store();

	/**
	 * The main Relation class, from which 'HasOne' and 'HasMany' inherit. Internally, 'relational:<key>' events
	 * are used to regulate addition and removal of models from relations.
	 *
	 * @param {Backbone.RelationalModel} [instance] Model that this relation is created for. If no model is supplied,
	 *      Relation just tries to instantiate it's `reverseRelation` if specified, and bails out after that.
	 * @param {Object} options
	 * @param {string} options.key
	 * @param {Backbone.RelationalModel.constructor} options.relatedModel
	 * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids.
	 * @param {Boolean} [options.createModels=true] Create objects from the contents of keys if the object is not found in Backbone.store.
	 * @param {Object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate
	 *    the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs
	 *    {Backbone.Relation|String} type ('HasOne' or 'HasMany').
	 * @param {Object} opts
	 */
	Backbone.Relation = function( instance, options, opts ) {
		this.instance = instance;
		// Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype
		options = _.isObject( options ) ? options : {};
		this.reverseRelation = _.defaults( options.reverseRelation || {}, this.options.reverseRelation );
		this.options = _.defaults( options, this.options, Backbone.Relation.prototype.options );

		this.reverseRelation.type = !_.isString( this.reverseRelation.type ) ? this.reverseRelation.type :
			Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName( this.reverseRelation.type );

		this.key = this.options.key;
		this.keySource = this.options.keySource || this.key;
		this.keyDestination = this.options.keyDestination || this.keySource || this.key;

		this.model = this.options.model || this.instance.constructor;

		this.relatedModel = this.options.relatedModel;

		// No 'relatedModel' is interpreted as self-referential
		if ( _.isUndefined( this.relatedModel ) ) {
			this.relatedModel = this.model;
		}

		// Otherwise, try to resolve the given value to an object
		if ( _.isFunction( this.relatedModel ) && !( this.relatedModel.prototype instanceof Backbone.RelationalModel ) ) {
			this.relatedModel = _.result( this, 'relatedModel' );
		}
		if ( _.isString( this.relatedModel ) ) {
			this.relatedModel = Backbone.Relational.store.getObjectByName( this.relatedModel );
		}


		if ( !this.checkPreconditions() ) {
			return;
		}

		// Add the reverse relation on 'relatedModel' to the store's reverseRelations
		if ( !this.options.isAutoRelation && this.reverseRelation.type && this.reverseRelation.key ) {
			Backbone.Relational.store.addReverseRelation( _.defaults( {
					isAutoRelation: true,
					model: this.relatedModel,
					relatedModel: this.model,
					reverseRelation: this.options // current relation is the 'reverseRelation' for its own reverseRelation
				},
				this.reverseRelation // Take further properties from this.reverseRelation (type, key, etc.)
			) );
		}

		if ( instance ) {
			var contentKey = this.keySource;
			if ( contentKey !== this.key && _.isObject( this.instance.get( this.key ) ) ) {
				contentKey = this.key;
			}

			this.setKeyContents( this.instance.get( contentKey ) );
			this.relatedCollection = Backbone.Relational.store.getCollection( this.relatedModel );

			// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
			if ( this.keySource !== this.key ) {
				delete this.instance.attributes[ this.keySource ];
			}

			// Add this Relation to instance._relations
			this.instance._relations[ this.key ] = this;

			this.initialize( opts );

			if ( this.options.autoFetch ) {
				this.instance.getAsync( this.key, _.isObject( this.options.autoFetch ) ? this.options.autoFetch : {} );
			}

			// When 'relatedModel' are created or destroyed, check if it affects this relation.
			this.listenTo( this.instance, 'destroy', this.destroy )
				.listenTo( this.relatedCollection, 'relational:add relational:change:id', this.tryAddRelated )
				.listenTo( this.relatedCollection, 'relational:remove', this.removeRelated );
		}
	};
	// Fix inheritance :\
	Backbone.Relation.extend = Backbone.Model.extend;
	// Set up all inheritable **Backbone.Relation** properties and methods.
	_.extend( Backbone.Relation.prototype, Backbone.Events, Backbone.Semaphore, {
		options: {
			createModels: true,
			includeInJSON: true,
			isAutoRelation: false,
			autoFetch: false,
			parse: false
		},

		instance: null,
		key: null,
		keyContents: null,
		relatedModel: null,
		relatedCollection: null,
		reverseRelation: null,
		related: null,

		/**
		 * Check several pre-conditions.
		 * @return {Boolean} True if pre-conditions are satisfied, false if they're not.
		 */
		checkPreconditions: function() {
			var i = this.instance,
				k = this.key,
				m = this.model,
				rm = this.relatedModel,
				warn = Backbone.Relational.showWarnings && typeof console !== 'undefined';

			if ( !m || !k || !rm ) {
				warn && console.warn( 'Relation=%o: missing model, key or relatedModel (%o, %o, %o).', this, m, k, rm );
				return false;
			}
			// Check if the type in 'model' inherits from Backbone.RelationalModel
			if ( !( m.prototype instanceof Backbone.RelationalModel ) ) {
				warn && console.warn( 'Relation=%o: model does not inherit from Backbone.RelationalModel (%o).', this, i );
				return false;
			}
			// Check if the type in 'relatedModel' inherits from Backbone.RelationalModel
			if ( !( rm.prototype instanceof Backbone.RelationalModel ) ) {
				warn && console.warn( 'Relation=%o: relatedModel does not inherit from Backbone.RelationalModel (%o).', this, rm );
				return false;
			}
			// Check if this is not a HasMany, and the reverse relation is HasMany as well
			if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany ) {
				warn && console.warn( 'Relation=%o: relation is a HasMany, and the reverseRelation is HasMany as well.', this );
				return false;
			}
			// Check if we're not attempting to create a relationship on a `key` that's already used.
			if ( i && _.keys( i._relations ).length ) {
				var existing = _.find( i._relations, function( rel ) {
					return rel.key === k;
				}, this );

				if ( existing ) {
					warn && console.warn( 'Cannot create relation=%o on %o for model=%o: already taken by relation=%o.',
						this, k, i, existing );
					return false;
				}
			}

			return true;
		},

		/**
		 * Set the related model(s) for this relation
		 * @param {Backbone.Model|Backbone.Collection} related
		 */
		setRelated: function( related ) {
			this.related = related;
			this.instance.attributes[ this.key ] = related;
		},

		/**
		 * Determine if a relation (on a different RelationalModel) is the reverse
		 * relation of the current one.
		 * @param {Backbone.Relation} relation
		 * @return {Boolean}
		 */
		_isReverseRelation: function( relation ) {
			return relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key &&
				this.key === relation.reverseRelation.key;
		},

		/**
		 * Get the reverse relations (pointing back to 'this.key' on 'this.instance') for the currently related model(s).
		 * @param {Backbone.RelationalModel} [model] Get the reverse relations for a specific model.
		 *    If not specified, 'this.related' is used.
		 * @return {Backbone.Relation[]}
		 */
		getReverseRelations: function( model ) {
			var reverseRelations = [];
			// Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array.
			var models = !_.isUndefined( model ) ? [ model ] : this.related && ( this.related.models || [ this.related ] ),
				relations = null,
				relation = null;

			for( var i = 0; i < ( models || [] ).length; i++ ) {
				relations = models[ i ].getRelations() || [];

				for( var j = 0; j < relations.length; j++ ) {
					relation = relations[ j ];

					if ( this._isReverseRelation( relation ) ) {
						reverseRelations.push( relation );
					}
				}
			}

			return reverseRelations;
		},

		/**
		 * When `this.instance` is destroyed, cleanup our relations.
		 * Get reverse relation, call removeRelated on each.
		 */
		destroy: function() {
			this.stopListening();

			if ( this instanceof Backbone.HasOne ) {
				this.setRelated( null );
			}
			else if ( this instanceof Backbone.HasMany ) {
				this.setRelated( this._prepareCollection() );
			}

			_.each( this.getReverseRelations(), function( relation ) {
				relation.removeRelated( this.instance );
			}, this );
		}
	});

	Backbone.HasOne = Backbone.Relation.extend({
		options: {
			reverseRelation: { type: 'HasMany' }
		},

		initialize: function( opts ) {
			this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange );

			var related = this.findRelated( opts );
			this.setRelated( related );

			// Notify new 'related' object of the new relation.
			_.each( this.getReverseRelations(), function( relation ) {
				relation.addRelated( this.instance, opts );
			}, this );
		},

		/**
		 * Find related Models.
		 * @param {Object} [options]
		 * @return {Backbone.Model}
		 */
		findRelated: function( options ) {
			var related = null;

			options = _.defaults( { parse: this.options.parse }, options );

			if ( this.keyContents instanceof this.relatedModel ) {
				related = this.keyContents;
			}
			else if ( this.keyContents || this.keyContents === 0 ) { // since 0 can be a valid `id` as well
				var opts = _.defaults( { create: this.options.createModels }, options );
				related = this.relatedModel.findOrCreate( this.keyContents, opts );
			}

			// Nullify `keyId` if we have a related model; in case it was already part of the relation
			if ( related ) {
				this.keyId = null;
			}

			return related;
		},

		/**
		 * Normalize and reduce `keyContents` to an `id`, for easier comparison
		 * @param {String|Number|Backbone.Model} keyContents
		 */
		setKeyContents: function( keyContents ) {
			this.keyContents = keyContents;
			this.keyId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, this.keyContents );
		},

		/**
		 * Event handler for `change:<key>`.
		 * If the key is changed, notify old & new reverse relations and initialize the new relation.
		 */
		onChange: function( model, attr, options ) {
			// Don't accept recursive calls to onChange (like onChange->findRelated->findOrCreate->initializeRelations->addRelated->onChange)
			if ( this.isLocked() ) {
				return;
			}
			this.acquire();
			options = options ? _.clone( options ) : {};

			// 'options.__related' is set by 'addRelated'/'removeRelated'. If it is set, the change
			// is the result of a call from a relation. If it's not, the change is the result of
			// a 'set' call on this.instance.
			var changed = _.isUndefined( options.__related ),
				oldRelated = changed ? this.related : options.__related;

			if ( changed ) {
				this.setKeyContents( attr );
				var related = this.findRelated( options );
				this.setRelated( related );
			}

			// Notify old 'related' object of the terminated relation
			if ( oldRelated && this.related !== oldRelated ) {
				_.each( this.getReverseRelations( oldRelated ), function( relation ) {
					relation.removeRelated( this.instance, null, options );
				}, this );
			}

			// Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated;
			// that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'.
			// In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet.
			_.each( this.getReverseRelations(), function( relation ) {
				relation.addRelated( this.instance, options );
			}, this );

			// Fire the 'change:<key>' event if 'related' was updated
			if ( !options.silent && this.related !== oldRelated ) {
				var dit = this;
				this.changed = true;
				Backbone.Relational.eventQueue.add( function() {
					dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true );
					dit.changed = false;
				});
			}
			this.release();
		},

		/**
		 * If a new 'this.relatedModel' appears in the 'store', try to match it to the last set 'keyContents'
		 */
		tryAddRelated: function( model, coll, options ) {
			if ( ( this.keyId || this.keyId === 0 ) && model.id === this.keyId ) { // since 0 can be a valid `id` as well
				this.addRelated( model, options );
				this.keyId = null;
			}
		},

		addRelated: function( model, options ) {
			// Allow 'model' to set up its relations before proceeding.
			// (which can result in a call to 'addRelated' from a relation of 'model')
			var dit = this;
			model.queue( function() {
				if ( model !== dit.related ) {
					var oldRelated = dit.related || null;
					dit.setRelated( model );
					dit.onChange( dit.instance, model, _.defaults( { __related: oldRelated }, options ) );
				}
			});
		},

		removeRelated: function( model, coll, options ) {
			if ( !this.related ) {
				return;
			}

			if ( model === this.related ) {
				var oldRelated = this.related || null;
				this.setRelated( null );
				this.onChange( this.instance, model, _.defaults( { __related: oldRelated }, options ) );
			}
		}
	});

	Backbone.HasMany = Backbone.Relation.extend({
		collectionType: null,

		options: {
			reverseRelation: { type: 'HasOne' },
			collectionType: Backbone.Collection,
			collectionKey: true,
			collectionOptions: {}
		},

		initialize: function( opts ) {
			this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange );

			// Handle a custom 'collectionType'
			this.collectionType = this.options.collectionType;
			if ( _.isFunction( this.collectionType ) && this.collectionType !== Backbone.Collection && !( this.collectionType.prototype instanceof Backbone.Collection ) ) {
				this.collectionType = _.result( this, 'collectionType' );
			}
			if ( _.isString( this.collectionType ) ) {
				this.collectionType = Backbone.Relational.store.getObjectByName( this.collectionType );
			}
			if ( this.collectionType !== Backbone.Collection && !( this.collectionType.prototype instanceof Backbone.Collection ) ) {
				throw new Error( '`collectionType` must inherit from Backbone.Collection' );
			}

			var related = this.findRelated( opts );
			this.setRelated( related );
		},

		/**
		 * Bind events and setup collectionKeys for a collection that is to be used as the backing store for a HasMany.
		 * If no 'collection' is supplied, a new collection will be created of the specified 'collectionType' option.
		 * @param {Backbone.Collection} [collection]
		 * @return {Backbone.Collection}
		 */
		_prepareCollection: function( collection ) {
			if ( this.related ) {
				this.stopListening( this.related );
			}

			if ( !collection || !( collection instanceof Backbone.Collection ) ) {
				var options = _.isFunction( this.options.collectionOptions ) ?
					this.options.collectionOptions( this.instance ) : this.options.collectionOptions;

				collection = new this.collectionType( null, options );
			}

			collection.model = this.relatedModel;

			if ( this.options.collectionKey ) {
				var key = this.options.collectionKey === true ? this.options.reverseRelation.key : this.options.collectionKey;

				if ( collection[ key ] && collection[ key ] !== this.instance ) {
					if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
						console.warn( 'Relation=%o; collectionKey=%s already exists on collection=%o', this, key, this.options.collectionKey );
					}
				}
				else if ( key ) {
					collection[ key ] = this.instance;
				}
			}

			this.listenTo( collection, 'relational:add', this.handleAddition )
				.listenTo( collection, 'relational:remove', this.handleRemoval )
				.listenTo( collection, 'relational:reset', this.handleReset );

			return collection;
		},

		/**
		 * Find related Models.
		 * @param {Object} [options]
		 * @return {Backbone.Collection}
		 */
		findRelated: function( options ) {
			var related = null;

			options = _.defaults( { parse: this.options.parse }, options );

			// Replace 'this.related' by 'this.keyContents' if it is a Backbone.Collection
			if ( this.keyContents instanceof Backbone.Collection ) {
				this._prepareCollection( this.keyContents );
				related = this.keyContents;
			}
			// Otherwise, 'this.keyContents' should be an array of related object ids.
			// Re-use the current 'this.related' if it is a Backbone.Collection; otherwise, create a new collection.
			else {
				var toAdd = [];

				_.each( this.keyContents, function( attributes ) {
					var model = null;

					if ( attributes instanceof this.relatedModel ) {
						model = attributes;
					}
					else {
						// If `merge` is true, update models here, instead of during update.
						model = ( _.isObject( attributes ) && options.parse && this.relatedModel.prototype.parse ) ?
							this.relatedModel.prototype.parse( _.clone( attributes ), options ) : attributes;
					}

					model && toAdd.push( model );
				}, this );

				if ( this.related instanceof Backbone.Collection ) {
					related = this.related;
				}
				else {
					related = this._prepareCollection();
				}

				// By now, `parse` will already have been executed just above for models if specified.
				// Disable to prevent additional calls.
				related.set( toAdd, _.defaults( { parse: false }, options ) );
			}

			// Remove entries from `keyIds` that were already part of the relation (and are thus 'unchanged')
			this.keyIds = _.difference( this.keyIds, _.pluck( related.models, 'id' ) );

			return related;
		},

		/**
		 * Normalize and reduce `keyContents` to a list of `ids`, for easier comparison
		 * @param {String|Number|String[]|Number[]|Backbone.Collection} keyContents
		 */
		setKeyContents: function( keyContents ) {
			this.keyContents = keyContents instanceof Backbone.Collection ? keyContents : null;
			this.keyIds = [];

			if ( !this.keyContents && ( keyContents || keyContents === 0 ) ) { // since 0 can be a valid `id` as well
				// Handle cases the an API/user supplies just an Object/id instead of an Array
				this.keyContents = _.isArray( keyContents ) ? keyContents : [ keyContents ];

				_.each( this.keyContents, function( item ) {
					var itemId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
					if ( itemId || itemId === 0 ) {
						this.keyIds.push( itemId );
					}
				}, this );
			}
		},

		/**
		 * Event handler for `change:<key>`.
		 * If the contents of the key are changed, notify old & new reverse relations and initialize the new relation.
		 */
		onChange: function( model, attr, options ) {
			options = options ? _.clone( options ) : {};
			this.setKeyContents( attr );
			this.changed = false;

			var related = this.findRelated( options );
			this.setRelated( related );

			if ( !options.silent ) {
				var dit = this;
				Backbone.Relational.eventQueue.add( function() {
					// The `changed` flag can be set in `handleAddition` or `handleRemoval`
					if ( dit.changed ) {
						dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true );
						dit.changed = false;
					}
				});
			}
		},

		/**
		 * When a model is added to a 'HasMany', trigger 'add' on 'this.instance' and notify reverse relations.
		 * (should be 'HasOne', must set 'this.instance' as their related).
		 */
		handleAddition: function( model, coll, options ) {
			//console.debug('handleAddition called; args=%o', arguments);
			options = options ? _.clone( options ) : {};
			this.changed = true;

			_.each( this.getReverseRelations( model ), function( relation ) {
				relation.addRelated( this.instance, options );
			}, this );

			// Only trigger 'add' once the newly added model is initialized (so, has its relations set up)
			var dit = this;
			!options.silent && Backbone.Relational.eventQueue.add( function() {
				dit.instance.trigger( 'add:' + dit.key, model, dit.related, options );
			});
		},

		/**
		 * When a model is removed from a 'HasMany', trigger 'remove' on 'this.instance' and notify reverse relations.
		 * (should be 'HasOne', which should be nullified)
		 */
		handleRemoval: function( model, coll, options ) {
			//console.debug('handleRemoval called; args=%o', arguments);
			options = options ? _.clone( options ) : {};
			this.changed = true;

			_.each( this.getReverseRelations( model ), function( relation ) {
				relation.removeRelated( this.instance, null, options );
			}, this );

			var dit = this;
			!options.silent && Backbone.Relational.eventQueue.add( function() {
				dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options );
			});
		},

		handleReset: function( coll, options ) {
			var dit = this;
			options = options ? _.clone( options ) : {};
			!options.silent && Backbone.Relational.eventQueue.add( function() {
				dit.instance.trigger( 'reset:' + dit.key, dit.related, options );
			});
		},

		tryAddRelated: function( model, coll, options ) {
			var item = _.contains( this.keyIds, model.id );

			if ( item ) {
				this.addRelated( model, options );
				this.keyIds = _.without( this.keyIds, model.id );
			}
		},

		addRelated: function( model, options ) {
			// Allow 'model' to set up its relations before proceeding.
			// (which can result in a call to 'addRelated' from a relation of 'model')
			var dit = this;
			model.queue( function() {
				if ( dit.related && !dit.related.get( model ) ) {
					dit.related.add( model, _.defaults( { parse: false }, options ) );
				}
			});
		},

		removeRelated: function( model, coll, options ) {
			if ( this.related.get( model ) ) {
				this.related.remove( model, options );
			}
		}
	});

	/**
	 * A type of Backbone.Model that also maintains relations to other models and collections.
	 * New events when compared to the original:
	 *  - 'add:<key>' (model, related collection, options)
	 *  - 'remove:<key>' (model, related collection, options)
	 *  - 'change:<key>' (model, related model or collection, options)
	 */
	Backbone.RelationalModel = Backbone.Model.extend({
		relations: null, // Relation descriptions on the prototype
		_relations: null, // Relation instances
		_isInitialized: false,
		_deferProcessing: false,
		_queue: null,
		_attributeChangeFired: false, // Keeps track of `change` event firing under some conditions (like nested `set`s)

		subModelTypeAttribute: 'type',
		subModelTypes: null,

		constructor: function( attributes, options ) {
			// Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'.
			// Defer 'processQueue', so that when 'Relation.createModels' is used we trigger 'HasMany'
			// collection events only after the model is really fully set up.
			// Example: event for "p.on( 'add:jobs' )" -> "p.get('jobs').add( { company: c.id, person: p.id } )".
			if ( options && options.collection ) {
				var dit = this,
					collection = this.collection = options.collection;

				// Prevent `collection` from cascading down to nested models; they shouldn't go into this `if` clause.
				delete options.collection;

				this._deferProcessing = true;

				var processQueue = function( model ) {
					if ( model === dit ) {
						dit._deferProcessing = false;
						dit.processQueue();
						collection.off( 'relational:add', processQueue );
					}
				};
				collection.on( 'relational:add', processQueue );

				// So we do process the queue eventually, regardless of whether this model actually gets added to 'options.collection'.
				_.defer( function() {
					processQueue( dit );
				});
			}

			Backbone.Relational.store.processOrphanRelations();
			Backbone.Relational.store.listenTo( this, 'relational:unregister', Backbone.Relational.store.unregister );

			this._queue = new Backbone.BlockingQueue();
			this._queue.block();
			Backbone.Relational.eventQueue.block();

			try {
				Backbone.Model.apply( this, arguments );
			}
			finally {
				// Try to run the global queue holding external events
				Backbone.Relational.eventQueue.unblock();
			}
		},

		/**
		 * Override 'trigger' to queue 'change' and 'change:*' events
		 */
		trigger: function( eventName ) {
			if ( eventName.length > 5 && eventName.indexOf( 'change' ) === 0 ) {
				var dit = this,
					args = arguments;

				if ( !Backbone.Relational.eventQueue.isBlocked() ) {
					// If we're not in a more complicated nested scenario, fire the change event right away
					Backbone.Model.prototype.trigger.apply( dit, args );
				}
				else {
					Backbone.Relational.eventQueue.add( function() {
						// Determine if the `change` event is still valid, now that all relations are populated
						var changed = true;
						if ( eventName === 'change' ) {
							// `hasChanged` may have gotten reset by nested calls to `set`.
							changed = dit.hasChanged() || dit._attributeChangeFired;
							dit._attributeChangeFired = false;
						}
						else {
							var attr = eventName.slice( 7 ),
								rel = dit.getRelation( attr );

							if ( rel ) {
								// If `attr` is a relation, `change:attr` get triggered from `Relation.onChange`.
								// These take precedence over `change:attr` events triggered by `Model.set`.
								// The relation sets a fourth attribute to `true`. If this attribute is present,
								// continue triggering this event; otherwise, it's from `Model.set` and should be stopped.
								changed = ( args[ 4 ] === true );

								// If this event was triggered by a relation, set the right value in `this.changed`
								// (a Collection or Model instead of raw data).
								if ( changed ) {
									dit.changed[ attr ] = args[ 2 ];
								}
								// Otherwise, this event is from `Model.set`. If the relation doesn't report a change,
								// remove attr from `dit.changed` so `hasChanged` doesn't take it into account.
								else if ( !rel.changed ) {
									delete dit.changed[ attr ];
								}
							}
							else if ( changed ) {
								dit._attributeChangeFired = true;
							}
						}

						changed && Backbone.Model.prototype.trigger.apply( dit, args );
					});
				}
			}
			else if ( eventName === 'destroy' ) {
				Backbone.Model.prototype.trigger.apply( this, arguments );
				Backbone.Relational.store.unregister( this );
			}
			else {
				Backbone.Model.prototype.trigger.apply( this, arguments );
			}

			return this;
		},

		/**
		 * Initialize Relations present in this.relations; determine the type (HasOne/HasMany), then creates a new instance.
		 * Invoked in the first call so 'set' (which is made from the Backbone.Model constructor).
		 */
		initializeRelations: function( options ) {
			this.acquire(); // Setting up relations often also involve calls to 'set', and we only want to enter this function once
			this._relations = {};

			_.each( this.relations || [], function( rel ) {
				Backbone.Relational.store.initializeRelation( this, rel, options );
			}, this );

			this._isInitialized = true;
			this.release();
			this.processQueue();
		},

		/**
		 * When new values are set, notify this model's relations (also if options.silent is set).
		 * (called from `set`; Relation.setRelated locks this model before calling 'set' on it to prevent loops)
		 * @param {Object} [changedAttrs]
		 * @param {Object} [options]
		 */
		updateRelations: function( changedAttrs, options ) {
			if ( this._isInitialized && !this.isLocked() ) {
				_.each( this._relations, function( rel ) {
					if ( !changedAttrs || ( rel.keySource in changedAttrs || rel.key in changedAttrs ) ) {
						// Fetch data in `rel.keySource` if data got set in there, or `rel.key` otherwise
						var value = this.attributes[ rel.keySource ] || this.attributes[ rel.key ],
							attr = changedAttrs && ( changedAttrs[ rel.keySource ] || changedAttrs[ rel.key ] );

						// Update a relation if its value differs from this model's attributes, or it's been explicitly nullified.
						// Which can also happen before the originally intended related model has been found (`val` is null).
						if ( rel.related !== value || ( value === null && attr === null ) ) {
							this.trigger( 'relational:change:' + rel.key, this, value, options || {} );
						}
					}

					// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
					if ( rel.keySource !== rel.key ) {
						delete this.attributes[ rel.keySource ];
					}
				}, this );
			}
		},

		/**
		 * Either add to the queue (if we're not initialized yet), or execute right away.
		 */
		queue: function( func ) {
			this._queue.add( func );
		},

		/**
		 * Process _queue
		 */
		processQueue: function() {
			if ( this._isInitialized && !this._deferProcessing && this._queue.isBlocked() ) {
				this._queue.unblock();
			}
		},

		/**
		 * Get a specific relation.
		 * @param {string} attr The relation key to look for.
		 * @return {Backbone.Relation} An instance of 'Backbone.Relation', if a relation was found for 'attr', or null.
		 */
		getRelation: function( attr ) {
			return this._relations[ attr ];
		},

		/**
		 * Get all of the created relations.
		 * @return {Backbone.Relation[]}
		 */
		getRelations: function() {
			return _.values( this._relations );
		},


		/**
		 * Get a list of ids that will be fetched on a call to `getAsync`.
		 * @param {string|Backbone.Relation} attr The relation key to fetch models for.
		 * @param [refresh=false] Add ids for models that are already in the relation, refreshing them?
		 * @return {Array} An array of ids that need to be fetched.
		 */
		getIdsToFetch: function( attr, refresh ) {
			var rel = attr instanceof Backbone.Relation ? attr : this.getRelation( attr ),
				ids = rel ? ( rel.keyIds && rel.keyIds.slice( 0 ) ) || ( ( rel.keyId || rel.keyId === 0 ) ? [ rel.keyId ] : [] ) : [];

			// On `refresh`, add the ids for current models in the relation to `idsToFetch`
			if ( refresh ) {
				var models = rel.related && ( rel.related.models || [ rel.related ] );
				_.each( models, function( model ) {
					if ( model.id || model.id === 0 ) {
						ids.push( model.id );
					}
				});
			}

			return ids;
		},

		/**
		 * Get related objects. Returns a single promise, which can either resolve immediately (if the related model[s])
		 * are already present locally, or after fetching the contents of the requested attribute.
		 * @param {string} attr The relation key to fetch models for.
		 * @param {Object} [options] Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
		 * @param {Boolean} [options.refresh=false] Fetch existing models from the server as well (in order to update them).
		 * @return {jQuery.Deferred} A jQuery promise object. When resolved, its `done` callback will be called with
		 *  contents of `attr`.
		 */
		getAsync: function( attr, options ) {
			// Set default `options` for fetch
			options = _.extend( { add: true, remove: false, refresh: false }, options );

			var dit = this,
				requests = [],
				rel = this.getRelation( attr ),
				idsToFetch = rel && this.getIdsToFetch( rel, options.refresh ),
				coll = rel.related instanceof Backbone.Collection ? rel.related : rel.relatedCollection;

			if ( idsToFetch && idsToFetch.length ) {
				var models = [],
					createdModels = [],
					setUrl,
					createModels = function() {
						// Find (or create) a model for each one that is to be fetched
						models = _.map( idsToFetch, function( id ) {
							var model = rel.relatedModel.findModel( id );

							if ( !model ) {
								var attrs = {};
								attrs[ rel.relatedModel.prototype.idAttribute ] = id;
								model = rel.relatedModel.findOrCreate( attrs, options );
								createdModels.push( model );
							}

							return model;
						}, this );
					};

				// Try if the 'collection' can provide a url to fetch a set of models in one request.
				// This assumes that when 'Backbone.Collection.url' is a function, it can handle building of set urls.
				// To make sure it can, test if the url we got by supplying a list of models to fetch is different from
				// the one supplied for the default fetch action (without args to 'url').
				if ( coll instanceof Backbone.Collection && _.isFunction( coll.url ) ) {
					var defaultUrl = coll.url();
					setUrl = coll.url( idsToFetch );

					if ( setUrl === defaultUrl ) {
						createModels();
						setUrl = coll.url( models );

						if ( setUrl === defaultUrl ) {
							setUrl = null;
						}
					}
				}

				if ( setUrl ) {
					// Do a single request to fetch all models
					var opts = _.defaults(
						{
							error: function() {
								_.each( createdModels, function( model ) {
									model.trigger( 'destroy', model, model.collection, options );
								});
								
								options.error && options.error.apply( models, arguments );
							},
							url: setUrl
						},
						options
					);

					requests = [ coll.fetch( opts ) ];
				}
				else {
					// Make a request per model to fetch
					if  ( !models.length ) {
						createModels();
					}

					requests = _.map( models, function( model ) {
						var opts = _.defaults(
							{
								error: function() {
									if ( _.contains( createdModels, model ) ) {
										model.trigger( 'destroy', model, model.collection, options );
									}
									options.error && options.error.apply( models, arguments );
								}
							},
							options
						);
						return model.fetch( opts );
					}, this );
				}
			}

			return this.deferArray(requests).then(
				function() {
					return Backbone.Model.prototype.get.call( dit, attr );
				}
			);
		},
		
		deferArray: function(deferArray) {
			return Backbone.$.when.apply(null, deferArray);
		},

		set: function( key, value, options ) {
			Backbone.Relational.eventQueue.block();

			// Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object
			var attributes,
				result;

			if ( _.isObject( key ) || key == null ) {
				attributes = key;
				options = value;
			}
			else {
				attributes = {};
				attributes[ key ] = value;
			}

			try {
				var id = this.id,
					newId = attributes && this.idAttribute in attributes && attributes[ this.idAttribute ];

				// Check if we're not setting a duplicate id before actually calling `set`.
				Backbone.Relational.store.checkId( this, newId );

				result = Backbone.Model.prototype.set.apply( this, arguments );

				// Ideal place to set up relations, if this is the first time we're here for this model
				if ( !this._isInitialized && !this.isLocked() ) {
					this.constructor.initializeModelHierarchy();

					// Only register models that have an id. A model will be registered when/if it gets an id later on.
					if ( newId || newId === 0 ) {
						Backbone.Relational.store.register( this );
					}

					this.initializeRelations( options );
				}
				// The store should know about an `id` update asap
				else if ( newId && newId !== id ) {
					Backbone.Relational.store.update( this );
				}

				if ( attributes ) {
					this.updateRelations( attributes, options );
				}
			}
			finally {
				// Try to run the global queue holding external events
				Backbone.Relational.eventQueue.unblock();
			}

			return result;
		},

		clone: function() {
			var attributes = _.clone( this.attributes );
			if ( !_.isUndefined( attributes[ this.idAttribute ] ) ) {
				attributes[ this.idAttribute ] = null;
			}

			_.each( this.getRelations(), function( rel ) {
				delete attributes[ rel.key ];
			});

			return new this.constructor( attributes );
		},

		/**
		 * Convert relations to JSON, omits them when required
		 */
		toJSON: function( options ) {
			// If this Model has already been fully serialized in this branch once, return to avoid loops
			if ( this.isLocked() ) {
				return this.id;
			}

			this.acquire();
			var json = Backbone.Model.prototype.toJSON.call( this, options );

			if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) {
				json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue;
			}

			_.each( this._relations, function( rel ) {
				var related = json[ rel.key ],
					includeInJSON = rel.options.includeInJSON,
					value = null;

				if ( includeInJSON === true ) {
					if ( related && _.isFunction( related.toJSON ) ) {
						value = related.toJSON( options );
					}
				}
				else if ( _.isString( includeInJSON ) ) {
					if ( related instanceof Backbone.Collection ) {
						value = related.pluck( includeInJSON );
					}
					else if ( related instanceof Backbone.Model ) {
						value = related.get( includeInJSON );
					}

					// Add ids for 'unfound' models if includeInJSON is equal to (only) the relatedModel's `idAttribute`
					if ( includeInJSON === rel.relatedModel.prototype.idAttribute ) {
						if ( rel instanceof Backbone.HasMany ) {
							value = value.concat( rel.keyIds );
						}
						else if ( rel instanceof Backbone.HasOne ) {
							value = value || rel.keyId;

							if ( !value && !_.isObject( rel.keyContents ) ) {
								value = rel.keyContents || null;
							}
						}
					}
				}
				else if ( _.isArray( includeInJSON ) ) {
					if ( related instanceof Backbone.Collection ) {
						value = [];
						related.each( function( model ) {
							var curJson = {};
							_.each( includeInJSON, function( key ) {
								curJson[ key ] = model.get( key );
							});
							value.push( curJson );
						});
					}
					else if ( related instanceof Backbone.Model ) {
						value = {};
						_.each( includeInJSON, function( key ) {
							value[ key ] = related.get( key );
						});
					}
				}
				else {
					delete json[ rel.key ];
				}

				// In case of `wait: true`, Backbone will simply push whatever's passed into `save` into attributes.
				// We'll want to get this information into the JSON, even if it doesn't conform to our normal
				// expectations of what's contained in it (no model/collection for a relation, etc).
				if ( value === null && options && options.wait ) {
					value = related;
				}

				if ( includeInJSON ) {
					json[ rel.keyDestination ] = value;
				}

				if ( rel.keyDestination !== rel.key ) {
					delete json[ rel.key ];
				}
			});

			this.release();
			return json;
		}
	},
	{
		/**
		 *
		 * @param superModel
		 * @returns {Backbone.RelationalModel.constructor}
		 */
		setup: function( superModel ) {
			// We don't want to share a relations array with a parent, as this will cause problems with reverse
			// relations. Since `relations` may also be a property or function, only use slice if we have an array.
			this.prototype.relations = ( this.prototype.relations || [] ).slice( 0 );

			this._subModels = {};
			this._superModel = null;

			// If this model has 'subModelTypes' itself, remember them in the store
			if ( this.prototype.hasOwnProperty( 'subModelTypes' ) ) {
				Backbone.Relational.store.addSubModels( this.prototype.subModelTypes, this );
			}
			// The 'subModelTypes' property should not be inherited, so reset it.
			else {
				this.prototype.subModelTypes = null;
			}

			// Initialize all reverseRelations that belong to this new model.
			_.each( this.prototype.relations || [], function( rel ) {
				if ( !rel.model ) {
					rel.model = this;
				}

				if ( rel.reverseRelation && rel.model === this ) {
					var preInitialize = true;
					if ( _.isString( rel.relatedModel ) ) {
						/**
						 * The related model might not be defined for two reasons
						 *  1. it is related to itself
						 *  2. it never gets defined, e.g. a typo
						 *  3. the model hasn't been defined yet, but will be later
						 * In neither of these cases do we need to pre-initialize reverse relations.
						 * However, for 3. (which is, to us, indistinguishable from 2.), we do need to attempt
						 * setting up this relation again later, in case the related model is defined later.
						 */
						var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
						preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel );
					}

					if ( preInitialize ) {
						Backbone.Relational.store.initializeRelation( null, rel );
					}
					else if ( _.isString( rel.relatedModel ) ) {
						Backbone.Relational.store.addOrphanRelation( rel );
					}
				}
			}, this );

			return this;
		},

		/**
		 * Create a 'Backbone.Model' instance based on 'attributes'.
		 * @param {Object} attributes
		 * @param {Object} [options]
		 * @return {Backbone.Model}
		 */
		build: function( attributes, options ) {
			// 'build' is a possible entrypoint; it's possible no model hierarchy has been determined yet.
			this.initializeModelHierarchy();

			// Determine what type of (sub)model should be built if applicable.
			var model = this._findSubModelType( this, attributes ) || this;

			return new model( attributes, options );
		},

		/**
		 * Determines what type of (sub)model should be built if applicable.
		 * Looks up the proper subModelType in 'this._subModels', recursing into
		 * types until a match is found.  Returns the applicable 'Backbone.Model'
		 * or null if no match is found.
		 * @param {Backbone.Model} type
		 * @param {Object} attributes
		 * @return {Backbone.Model}
		 */
		_findSubModelType: function( type, attributes ) {
			if ( type._subModels && type.prototype.subModelTypeAttribute in attributes ) {
				var subModelTypeAttribute = attributes[ type.prototype.subModelTypeAttribute ];
				var subModelType = type._subModels[ subModelTypeAttribute ];
				if ( subModelType ) {
					return subModelType;
				}
				else {
					// Recurse into subModelTypes to find a match
					for ( subModelTypeAttribute in type._subModels ) {
						subModelType = this._findSubModelType( type._subModels[ subModelTypeAttribute ], attributes );
						if ( subModelType ) {
							return subModelType;
						}
					}
				}
			}

			return null;
		},

		/**
		 *
		 */
		initializeModelHierarchy: function() {
			// Inherit any relations that have been defined in the parent model.
			this.inheritRelations();

			// If we came here through 'build' for a model that has 'subModelTypes' then try to initialize the ones that
			// haven't been resolved yet.
			if ( this.prototype.subModelTypes ) {
				var resolvedSubModels = _.keys( this._subModels );
				var unresolvedSubModels = _.omit( this.prototype.subModelTypes, resolvedSubModels );
				_.each( unresolvedSubModels, function( subModelTypeName ) {
					var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName );
					subModelType && subModelType.initializeModelHierarchy();
				});
			}
		},

		inheritRelations: function() {
			// Bail out if we've been here before.
			if ( !_.isUndefined( this._superModel ) && !_.isNull( this._superModel ) ) {
				return;
			}
			// Try to initialize the _superModel.
			Backbone.Relational.store.setupSuperModel( this );

			// If a superModel has been found, copy relations from the _superModel if they haven't been inherited automatically
			// (due to a redefinition of 'relations').
			if ( this._superModel ) {
				// The _superModel needs a chance to initialize its own inherited relations before we attempt to inherit relations
				// from the _superModel. You don't want to call 'initializeModelHierarchy' because that could cause sub-models of
				// this class to inherit their relations before this class has had chance to inherit it's relations.
				this._superModel.inheritRelations();
				if ( this._superModel.prototype.relations ) {
					// Find relations that exist on the '_superModel', but not yet on this model.
					var inheritedRelations = _.filter( this._superModel.prototype.relations || [], function( superRel ) {
						return !_.any( this.prototype.relations || [], function( rel ) {
							return superRel.relatedModel === rel.relatedModel && superRel.key === rel.key;
						}, this );
					}, this );

					this.prototype.relations = inheritedRelations.concat( this.prototype.relations );
				}
			}
			// Otherwise, make sure we don't get here again for this type by making '_superModel' false so we fail the
			// isUndefined/isNull check next time.
			else {
				this._superModel = false;
			}
		},

		/**
		 * Find an instance of `this` type in 'Backbone.Relational.store'.
		 * A new model is created if no matching model is found, `attributes` is an object, and `options.create` is true.
		 * - If `attributes` is a string or a number, `findOrCreate` will query the `store` and return a model if found.
		 * - If `attributes` is an object and is found in the store, the model will be updated with `attributes` unless `options.merge` is `false`.
		 * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
		 * @param {Object} [options]
		 * @param {Boolean} [options.create=true]
		 * @param {Boolean} [options.merge=true]
		 * @param {Boolean} [options.parse=false]
		 * @return {Backbone.RelationalModel}
		 */
		findOrCreate: function( attributes, options ) {
			options || ( options = {} );
			var parsedAttributes = ( _.isObject( attributes ) && options.parse && this.prototype.parse ) ?
				this.prototype.parse( _.clone( attributes ), options ) : attributes;

			// If specified, use a custom `find` function to match up existing models to the given attributes.
			// Otherwise, try to find an instance of 'this' model type in the store
			var model = this.findModel( parsedAttributes );

			// If we found an instance, update it with the data in 'item' (unless 'options.merge' is false).
			// If not, create an instance (unless 'options.create' is false).
			if ( _.isObject( attributes ) ) {
				if ( model && options.merge !== false ) {
					// Make sure `options.collection` and `options.url` doesn't cascade to nested models
					delete options.collection;
					delete options.url;

					model.set( parsedAttributes, options );
				}
				else if ( !model && options.create !== false ) {
					model = this.build( parsedAttributes, _.defaults( { parse: false }, options ) );
				}
			}

			return model;
		},

		/**
		 * Find an instance of `this` type in 'Backbone.Relational.store'.
		 * - If `attributes` is a string or a number, `find` will query the `store` and return a model if found.
		 * - If `attributes` is an object and is found in the store, the model will be updated with `attributes` unless `options.merge` is `false`.
		 * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
		 * @param {Object} [options]
		 * @param {Boolean} [options.merge=true]
		 * @param {Boolean} [options.parse=false]
		 * @return {Backbone.RelationalModel}
		 */
		find: function( attributes, options ) {
			options || ( options = {} );
			options.create = false;
			return this.findOrCreate( attributes, options );
		},

		/**
		 * A hook to override the matching when updating (or creating) a model.
		 * The default implementation is to look up the model by id in the store.
		 * @param {Object} attributes
		 * @returns {Backbone.RelationalModel}
		 */
		findModel: function( attributes ) {
			return Backbone.Relational.store.find( this, attributes );
		}
	});
	_.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore );

	/**
	 * Override Backbone.Collection._prepareModel, so objects will be built using the correct type
	 * if the collection.model has subModels.
	 * Attempts to find a model for `attrs` in Backbone.store through `findOrCreate`
	 * (which sets the new properties on it if found), or instantiates a new model.
	 */
	Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel;
	Backbone.Collection.prototype._prepareModel = function( attrs, options ) {
		var model;

		if ( attrs instanceof Backbone.Model ) {
			if ( !attrs.collection ) {
				attrs.collection = this;
			}
			model = attrs;
		}
		else {
			options = options ? _.clone( options ) : {};
			options.collection = this;

			if ( typeof this.model.findOrCreate !== 'undefined' ) {
				model = this.model.findOrCreate( attrs, options );
			}
			else {
				model = new this.model( attrs, options );
			}

			if ( model && model.validationError ) {
				this.trigger( 'invalid', this, attrs, options );
				model = false;
			}
		}

		return model;
	};


	/**
	 * Override Backbone.Collection.set, so we'll create objects from attributes where required,
	 * and update the existing models. Also, trigger 'relational:add'.
	 */
	var set = Backbone.Collection.prototype.__set = Backbone.Collection.prototype.set;
	Backbone.Collection.prototype.set = function( models, options ) {
		// Short-circuit if this Collection doesn't hold RelationalModels
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
			return set.call( this, models, options );
		}

		if ( options && options.parse ) {
			models = this.parse( models, options );
		}

		var singular = !_.isArray( models ),
			newModels = [],
			toAdd = [],
			model = null;

		models = singular ? ( models ? [ models ] : [] ) : _.clone( models );

		//console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options );
		for ( var i = 0; i < models.length; i++ ) {
			model = models[i];
			if ( !( model instanceof Backbone.Model ) ) {
				model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
			}
			if ( model ) {
				toAdd.push( model );
				if ( !( this.get( model ) || this.get( model.cid ) ) ) {
					newModels.push( model );
				}
				// If we arrive in `add` while performing a `set` (after a create, so the model gains an `id`),
				// we may get here before `_onModelEvent` has had the chance to update `_byId`.
				else if ( model.id !== null && model.id !== undefined ) {
					this._byId[ model.id ] = model;
				}
			}
		}

		// Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc).
		// If `parse` was specified, the collection and contained models have been parsed now.
		toAdd = singular ? ( toAdd.length ? toAdd[ 0 ] : null ) : toAdd;
		var result = set.call( this, toAdd, _.defaults( { merge: false, parse: false }, options ) );

		for ( i = 0; i < newModels.length; i++ ) {
			model = newModels[i];
			// Fire a `relational:add` event for any model in `newModels` that has actually been added to the collection.
			if ( this.get( model ) || this.get( model.cid ) ) {
				this.trigger( 'relational:add', model, this, options );
			}
		}

		return result;
	};

	/**
	 * Override 'Backbone.Collection._removeModels' to trigger 'relational:remove'.
	 */
	var _removeModels = Backbone.Collection.prototype.___removeModels = Backbone.Collection.prototype._removeModels;
	Backbone.Collection.prototype._removeModels = function( models, options ) {
		// Short-circuit if this Collection doesn't hold RelationalModels
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
			return _removeModels.call( this, models, options );
		}

		var toRemove = [];

		//console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options );
		_.each( models, function( model ) {
			model = this.get( model ) || ( model && this.get( model.cid ) );
			model && toRemove.push( model );
		}, this );

		var result = _removeModels.call( this, toRemove, options );

		_.each( toRemove, function( model ) {
			this.trigger( 'relational:remove', model, this, options );
		}, this );

		return result;
	};

	/**
	 * Override 'Backbone.Collection.reset' to trigger 'relational:reset'.
	 */
	var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset;
	Backbone.Collection.prototype.reset = function( models, options ) {
		options = _.extend( { merge: true }, options );
		var result = reset.call( this, models, options );

		if ( this.model.prototype instanceof Backbone.RelationalModel ) {
			this.trigger( 'relational:reset', this, options );
		}

		return result;
	};

	/**
	 * Override 'Backbone.Collection.sort' to trigger 'relational:reset'.
	 */
	var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort;
	Backbone.Collection.prototype.sort = function( options ) {
		var result = sort.call( this, options );

		if ( this.model.prototype instanceof Backbone.RelationalModel ) {
			this.trigger( 'relational:reset', this, options );
		}

		return result;
	};

	/**
	 * Override 'Backbone.Collection.trigger' so 'add', 'remove' and 'reset' events are queued until relations
	 * are ready.
	 */
	var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger;
	Backbone.Collection.prototype.trigger = function( eventName ) {
		// Short-circuit if this Collection doesn't hold RelationalModels
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
			return trigger.apply( this, arguments );
		}

		if ( eventName === 'add' || eventName === 'remove' || eventName === 'reset' || eventName === 'sort' ) {
			var dit = this,
				args = arguments;

			if ( _.isObject( args[ 3 ] ) ) {
				args = _.toArray( args );
				// the fourth argument is the option object.
				// we need to clone it, as it could be modified while we wait on the eventQueue to be unblocked
				args[ 3 ] = _.clone( args[ 3 ] );
			}

			Backbone.Relational.eventQueue.add( function() {
				trigger.apply( dit, args );
			});
		}
		else {
			trigger.apply( this, arguments );
		}

		return this;
	};

	// Override .extend() to automatically call .setup()
	Backbone.RelationalModel.extend = function( protoProps, classProps ) {
		var child = Backbone.Model.extend.call( this, protoProps, classProps );

		child.setup( this );

		return child;
	};
}));
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return HttpError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return TimeoutError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AbortError; });
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var __extends = (undefined && undefined.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
/** Error thrown when an HTTP request fails. */
var HttpError = /** @class */ (function (_super) {
    __extends(HttpError, _super);
    /** Constructs a new instance of {@link @microsoft/signalr.HttpError}.
     *
     * @param {string} errorMessage A descriptive error message.
     * @param {number} statusCode The HTTP status code represented by this error.
     */
    function HttpError(errorMessage, statusCode) {
        var _newTarget = this.constructor;
        var _this = this;
        var trueProto = _newTarget.prototype;
        _this = _super.call(this, errorMessage) || this;
        _this.statusCode = statusCode;
        // Workaround issue in Typescript compiler
        // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200
        _this.__proto__ = trueProto;
        return _this;
    }
    return HttpError;
}(Error));

/** Error thrown when a timeout elapses. */
var TimeoutError = /** @class */ (function (_super) {
    __extends(TimeoutError, _super);
    /** Constructs a new instance of {@link @microsoft/signalr.TimeoutError}.
     *
     * @param {string} errorMessage A descriptive error message.
     */
    function TimeoutError(errorMessage) {
        var _newTarget = this.constructor;
        if (errorMessage === void 0) { errorMessage = "A timeout occurred."; }
        var _this = this;
        var trueProto = _newTarget.prototype;
        _this = _super.call(this, errorMessage) || this;
        // Workaround issue in Typescript compiler
        // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200
        _this.__proto__ = trueProto;
        return _this;
    }
    return TimeoutError;
}(Error));

/** Error thrown when an action is aborted. */
var AbortError = /** @class */ (function (_super) {
    __extends(AbortError, _super);
    /** Constructs a new instance of {@link AbortError}.
     *
     * @param {string} errorMessage A descriptive error message.
     */
    function AbortError(errorMessage) {
        var _newTarget = this.constructor;
        if (errorMessage === void 0) { errorMessage = "An abort occurred."; }
        var _this = this;
        var trueProto = _newTarget.prototype;
        _this = _super.call(this, errorMessage) || this;
        // Workaround issue in Typescript compiler
        // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200
        _this.__proto__ = trueProto;
        return _this;
    }
    return AbortError;
}(Error));

//# sourceMappingURL=Errors.js.map/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return HttpResponse; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return HttpClient; });
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var __assign = (undefined && undefined.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
/** Represents an HTTP response. */
var HttpResponse = /** @class */ (function () {
    function HttpResponse(statusCode, statusText, content) {
        this.statusCode = statusCode;
        this.statusText = statusText;
        this.content = content;
    }
    return HttpResponse;
}());

/** Abstraction over an HTTP client.
 *
 * This class provides an abstraction over an HTTP client so that a different implementation can be provided on different platforms.
 */
var HttpClient = /** @class */ (function () {
    function HttpClient() {
    }
    HttpClient.prototype.get = function (url, options) {
        return this.send(__assign({}, options, { method: "GET", url: url }));
    };
    HttpClient.prototype.post = function (url, options) {
        return this.send(__assign({}, options, { method: "POST", url: url }));
    };
    HttpClient.prototype.delete = function (url, options) {
        return this.send(__assign({}, options, { method: "DELETE", url: url }));
    };
    /** Gets all cookies that apply to the specified URL.
     *
     * @param url The URL that the cookies are valid for.
     * @returns {string} A string containing all the key-value cookie pairs for the specified URL.
     */
    // @ts-ignore
    HttpClient.prototype.getCookieString = function (url) {
        return "";
    };
    return HttpClient;
}());

//# sourceMappingURL=HttpClient.js.map/* WEBPACK VAR INJECTION */(function(Buffer) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return NodeHttpClient; });
/* harmony import */ var _Errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(60);
/* harmony import */ var _HttpClient__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(125);
/* harmony import */ var _ILogger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
/* harmony import */ var _Utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(29);
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var __extends = (undefined && undefined.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (undefined && undefined.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};




var requestModule;
if (typeof XMLHttpRequest === "undefined") {
    // In order to ignore the dynamic require in webpack builds we need to do this magic
    // @ts-ignore: TS doesn't know about these names
    var requireFunc =  true ? require : undefined;
    requestModule = requireFunc("request");
}
var NodeHttpClient = /** @class */ (function (_super) {
    __extends(NodeHttpClient, _super);
    function NodeHttpClient(logger) {
        var _this = _super.call(this) || this;
        if (typeof requestModule === "undefined") {
            throw new Error("The 'request' module could not be loaded.");
        }
        _this.logger = logger;
        _this.cookieJar = requestModule.jar();
        _this.request = requestModule.defaults({ jar: _this.cookieJar });
        return _this;
    }
    NodeHttpClient.prototype.send = function (httpRequest) {
        var _this = this;
        return new Promise(function (resolve, reject) {
            var requestBody;
            if (Object(_Utils__WEBPACK_IMPORTED_MODULE_3__[/* isArrayBuffer */ "g"])(httpRequest.content)) {
                requestBody = Buffer.from(httpRequest.content);
            }
            else {
                requestBody = httpRequest.content || "";
            }
            var currentRequest = _this.request(httpRequest.url, {
                body: requestBody,
                // If binary is expected 'null' should be used, otherwise for text 'utf8'
                encoding: httpRequest.responseType === "arraybuffer" ? null : "utf8",
                headers: __assign({ 
                    // Tell auth middleware to 401 instead of redirecting
                    "X-Requested-With": "XMLHttpRequest" }, httpRequest.headers),
                method: httpRequest.method,
                timeout: httpRequest.timeout,
            }, function (error, response, body) {
                if (httpRequest.abortSignal) {
                    httpRequest.abortSignal.onabort = null;
                }
                if (error) {
                    if (error.code === "ETIMEDOUT") {
                        _this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_2__[/* LogLevel */ "a"].Warning, "Timeout from HTTP request.");
                        reject(new _Errors__WEBPACK_IMPORTED_MODULE_0__[/* TimeoutError */ "c"]());
                    }
                    _this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_2__[/* LogLevel */ "a"].Warning, "Error from HTTP request. " + error);
                    reject(error);
                    return;
                }
                if (response.statusCode >= 200 && response.statusCode < 300) {
                    resolve(new _HttpClient__WEBPACK_IMPORTED_MODULE_1__[/* HttpResponse */ "b"](response.statusCode, response.statusMessage || "", body));
                }
                else {
                    reject(new _Errors__WEBPACK_IMPORTED_MODULE_0__[/* HttpError */ "b"](response.statusMessage || "", response.statusCode || 0));
                }
            });
            if (httpRequest.abortSignal) {
                httpRequest.abortSignal.onabort = function () {
                    currentRequest.abort();
                    reject(new _Errors__WEBPACK_IMPORTED_MODULE_0__[/* AbortError */ "a"]());
                };
            }
        });
    };
    NodeHttpClient.prototype.getCookieString = function (url) {
        return this.cookieJar.getCookieString(url);
    };
    return NodeHttpClient;
}(_HttpClient__WEBPACK_IMPORTED_MODULE_1__[/* HttpClient */ "a"]));

//# sourceMappingURL=NodeHttpClient.js.map
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(626).Buffer))/* WEBPACK VAR INJECTION */(function(global) {/*!
 * The buffer module from node.js, for the browser.
 *
 * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
 * @license  MIT
 */
/* eslint-disable no-proto */



var base64 = __webpack_require__(752)
var ieee754 = __webpack_require__(753)
var isArray = __webpack_require__(338)

exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50

/**
 * If `Buffer.TYPED_ARRAY_SUPPORT`:
 *   === true    Use Uint8Array implementation (fastest)
 *   === false   Use Object implementation (most compatible, even IE6)
 *
 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
 * Opera 11.6+, iOS 4.2+.
 *
 * Due to various browser bugs, sometimes the Object implementation will be used even
 * when the browser supports typed arrays.
 *
 * Note:
 *
 *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
 *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
 *
 *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
 *
 *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
 *     incorrect length in some situations.

 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
 * get the Object implementation, which is slower but behaves correctly.
 */
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
  ? global.TYPED_ARRAY_SUPPORT
  : typedArraySupport()

/*
 * Export kMaxLength after typed array support is determined.
 */
exports.kMaxLength = kMaxLength()

function typedArraySupport () {
  try {
    var arr = new Uint8Array(1)
    arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
    return arr.foo() === 42 && // typed array instances can be augmented
        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
  } catch (e) {
    return false
  }
}

function kMaxLength () {
  return Buffer.TYPED_ARRAY_SUPPORT
    ? 0x7fffffff
    : 0x3fffffff
}

function createBuffer (that, length) {
  if (kMaxLength() < length) {
    throw new RangeError('Invalid typed array length')
  }
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    // Return an augmented `Uint8Array` instance, for best performance
    that = new Uint8Array(length)
    that.__proto__ = Buffer.prototype
  } else {
    // Fallback: Return an object instance of the Buffer class
    if (that === null) {
      that = new Buffer(length)
    }
    that.length = length
  }

  return that
}

/**
 * The Buffer constructor returns instances of `Uint8Array` that have their
 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
 * and the `Uint8Array` methods. Square bracket notation works as expected -- it
 * returns a single octet.
 *
 * The `Uint8Array` prototype remains unmodified.
 */

function Buffer (arg, encodingOrOffset, length) {
  if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
    return new Buffer(arg, encodingOrOffset, length)
  }

  // Common case.
  if (typeof arg === 'number') {
    if (typeof encodingOrOffset === 'string') {
      throw new Error(
        'If encoding is specified then the first argument must be a string'
      )
    }
    return allocUnsafe(this, arg)
  }
  return from(this, arg, encodingOrOffset, length)
}

Buffer.poolSize = 8192 // not used by this implementation

// TODO: Legacy, not needed anymore. Remove in next major version.
Buffer._augment = function (arr) {
  arr.__proto__ = Buffer.prototype
  return arr
}

function from (that, value, encodingOrOffset, length) {
  if (typeof value === 'number') {
    throw new TypeError('"value" argument must not be a number')
  }

  if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
    return fromArrayBuffer(that, value, encodingOrOffset, length)
  }

  if (typeof value === 'string') {
    return fromString(that, value, encodingOrOffset)
  }

  return fromObject(that, value)
}

/**
 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
 * if value is a number.
 * Buffer.from(str[, encoding])
 * Buffer.from(array)
 * Buffer.from(buffer)
 * Buffer.from(arrayBuffer[, byteOffset[, length]])
 **/
Buffer.from = function (value, encodingOrOffset, length) {
  return from(null, value, encodingOrOffset, length)
}

if (Buffer.TYPED_ARRAY_SUPPORT) {
  Buffer.prototype.__proto__ = Uint8Array.prototype
  Buffer.__proto__ = Uint8Array
  if (typeof Symbol !== 'undefined' && Symbol.species &&
      Buffer[Symbol.species] === Buffer) {
    // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
    Object.defineProperty(Buffer, Symbol.species, {
      value: null,
      configurable: true
    })
  }
}

function assertSize (size) {
  if (typeof size !== 'number') {
    throw new TypeError('"size" argument must be a number')
  } else if (size < 0) {
    throw new RangeError('"size" argument must not be negative')
  }
}

function alloc (that, size, fill, encoding) {
  assertSize(size)
  if (size <= 0) {
    return createBuffer(that, size)
  }
  if (fill !== undefined) {
    // Only pay attention to encoding if it's a string. This
    // prevents accidentally sending in a number that would
    // be interpretted as a start offset.
    return typeof encoding === 'string'
      ? createBuffer(that, size).fill(fill, encoding)
      : createBuffer(that, size).fill(fill)
  }
  return createBuffer(that, size)
}

/**
 * Creates a new filled Buffer instance.
 * alloc(size[, fill[, encoding]])
 **/
Buffer.alloc = function (size, fill, encoding) {
  return alloc(null, size, fill, encoding)
}

function allocUnsafe (that, size) {
  assertSize(size)
  that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
  if (!Buffer.TYPED_ARRAY_SUPPORT) {
    for (var i = 0; i < size; ++i) {
      that[i] = 0
    }
  }
  return that
}

/**
 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
 * */
Buffer.allocUnsafe = function (size) {
  return allocUnsafe(null, size)
}
/**
 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
 */
Buffer.allocUnsafeSlow = function (size) {
  return allocUnsafe(null, size)
}

function fromString (that, string, encoding) {
  if (typeof encoding !== 'string' || encoding === '') {
    encoding = 'utf8'
  }

  if (!Buffer.isEncoding(encoding)) {
    throw new TypeError('"encoding" must be a valid string encoding')
  }

  var length = byteLength(string, encoding) | 0
  that = createBuffer(that, length)

  var actual = that.write(string, encoding)

  if (actual !== length) {
    // Writing a hex string, for example, that contains invalid characters will
    // cause everything after the first invalid character to be ignored. (e.g.
    // 'abxxcd' will be treated as 'ab')
    that = that.slice(0, actual)
  }

  return that
}

function fromArrayLike (that, array) {
  var length = array.length < 0 ? 0 : checked(array.length) | 0
  that = createBuffer(that, length)
  for (var i = 0; i < length; i += 1) {
    that[i] = array[i] & 255
  }
  return that
}

function fromArrayBuffer (that, array, byteOffset, length) {
  array.byteLength // this throws if `array` is not a valid ArrayBuffer

  if (byteOffset < 0 || array.byteLength < byteOffset) {
    throw new RangeError('\'offset\' is out of bounds')
  }

  if (array.byteLength < byteOffset + (length || 0)) {
    throw new RangeError('\'length\' is out of bounds')
  }

  if (byteOffset === undefined && length === undefined) {
    array = new Uint8Array(array)
  } else if (length === undefined) {
    array = new Uint8Array(array, byteOffset)
  } else {
    array = new Uint8Array(array, byteOffset, length)
  }

  if (Buffer.TYPED_ARRAY_SUPPORT) {
    // Return an augmented `Uint8Array` instance, for best performance
    that = array
    that.__proto__ = Buffer.prototype
  } else {
    // Fallback: Return an object instance of the Buffer class
    that = fromArrayLike(that, array)
  }
  return that
}

function fromObject (that, obj) {
  if (Buffer.isBuffer(obj)) {
    var len = checked(obj.length) | 0
    that = createBuffer(that, len)

    if (that.length === 0) {
      return that
    }

    obj.copy(that, 0, 0, len)
    return that
  }

  if (obj) {
    if ((typeof ArrayBuffer !== 'undefined' &&
        obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
      if (typeof obj.length !== 'number' || isnan(obj.length)) {
        return createBuffer(that, 0)
      }
      return fromArrayLike(that, obj)
    }

    if (obj.type === 'Buffer' && isArray(obj.data)) {
      return fromArrayLike(that, obj.data)
    }
  }

  throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
}

function checked (length) {
  // Note: cannot use `length < kMaxLength()` here because that fails when
  // length is NaN (which is otherwise coerced to zero.)
  if (length >= kMaxLength()) {
    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
  }
  return length | 0
}

function SlowBuffer (length) {
  if (+length != length) { // eslint-disable-line eqeqeq
    length = 0
  }
  return Buffer.alloc(+length)
}

Buffer.isBuffer = function isBuffer (b) {
  return !!(b != null && b._isBuffer)
}

Buffer.compare = function compare (a, b) {
  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
    throw new TypeError('Arguments must be Buffers')
  }

  if (a === b) return 0

  var x = a.length
  var y = b.length

  for (var i = 0, len = Math.min(x, y); i < len; ++i) {
    if (a[i] !== b[i]) {
      x = a[i]
      y = b[i]
      break
    }
  }

  if (x < y) return -1
  if (y < x) return 1
  return 0
}

Buffer.isEncoding = function isEncoding (encoding) {
  switch (String(encoding).toLowerCase()) {
    case 'hex':
    case 'utf8':
    case 'utf-8':
    case 'ascii':
    case 'latin1':
    case 'binary':
    case 'base64':
    case 'ucs2':
    case 'ucs-2':
    case 'utf16le':
    case 'utf-16le':
      return true
    default:
      return false
  }
}

Buffer.concat = function concat (list, length) {
  if (!isArray(list)) {
    throw new TypeError('"list" argument must be an Array of Buffers')
  }

  if (list.length === 0) {
    return Buffer.alloc(0)
  }

  var i
  if (length === undefined) {
    length = 0
    for (i = 0; i < list.length; ++i) {
      length += list[i].length
    }
  }

  var buffer = Buffer.allocUnsafe(length)
  var pos = 0
  for (i = 0; i < list.length; ++i) {
    var buf = list[i]
    if (!Buffer.isBuffer(buf)) {
      throw new TypeError('"list" argument must be an Array of Buffers')
    }
    buf.copy(buffer, pos)
    pos += buf.length
  }
  return buffer
}

function byteLength (string, encoding) {
  if (Buffer.isBuffer(string)) {
    return string.length
  }
  if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
      (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
    return string.byteLength
  }
  if (typeof string !== 'string') {
    string = '' + string
  }

  var len = string.length
  if (len === 0) return 0

  // Use a for loop to avoid recursion
  var loweredCase = false
  for (;;) {
    switch (encoding) {
      case 'ascii':
      case 'latin1':
      case 'binary':
        return len
      case 'utf8':
      case 'utf-8':
      case undefined:
        return utf8ToBytes(string).length
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return len * 2
      case 'hex':
        return len >>> 1
      case 'base64':
        return base64ToBytes(string).length
      default:
        if (loweredCase) return utf8ToBytes(string).length // assume utf8
        encoding = ('' + encoding).toLowerCase()
        loweredCase = true
    }
  }
}
Buffer.byteLength = byteLength

function slowToString (encoding, start, end) {
  var loweredCase = false

  // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
  // property of a typed array.

  // This behaves neither like String nor Uint8Array in that we set start/end
  // to their upper/lower bounds if the value passed is out of range.
  // undefined is handled specially as per ECMA-262 6th Edition,
  // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
  if (start === undefined || start < 0) {
    start = 0
  }
  // Return early if start > this.length. Done here to prevent potential uint32
  // coercion fail below.
  if (start > this.length) {
    return ''
  }

  if (end === undefined || end > this.length) {
    end = this.length
  }

  if (end <= 0) {
    return ''
  }

  // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
  end >>>= 0
  start >>>= 0

  if (end <= start) {
    return ''
  }

  if (!encoding) encoding = 'utf8'

  while (true) {
    switch (encoding) {
      case 'hex':
        return hexSlice(this, start, end)

      case 'utf8':
      case 'utf-8':
        return utf8Slice(this, start, end)

      case 'ascii':
        return asciiSlice(this, start, end)

      case 'latin1':
      case 'binary':
        return latin1Slice(this, start, end)

      case 'base64':
        return base64Slice(this, start, end)

      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return utf16leSlice(this, start, end)

      default:
        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
        encoding = (encoding + '').toLowerCase()
        loweredCase = true
    }
  }
}

// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
// Buffer instances.
Buffer.prototype._isBuffer = true

function swap (b, n, m) {
  var i = b[n]
  b[n] = b[m]
  b[m] = i
}

Buffer.prototype.swap16 = function swap16 () {
  var len = this.length
  if (len % 2 !== 0) {
    throw new RangeError('Buffer size must be a multiple of 16-bits')
  }
  for (var i = 0; i < len; i += 2) {
    swap(this, i, i + 1)
  }
  return this
}

Buffer.prototype.swap32 = function swap32 () {
  var len = this.length
  if (len % 4 !== 0) {
    throw new RangeError('Buffer size must be a multiple of 32-bits')
  }
  for (var i = 0; i < len; i += 4) {
    swap(this, i, i + 3)
    swap(this, i + 1, i + 2)
  }
  return this
}

Buffer.prototype.swap64 = function swap64 () {
  var len = this.length
  if (len % 8 !== 0) {
    throw new RangeError('Buffer size must be a multiple of 64-bits')
  }
  for (var i = 0; i < len; i += 8) {
    swap(this, i, i + 7)
    swap(this, i + 1, i + 6)
    swap(this, i + 2, i + 5)
    swap(this, i + 3, i + 4)
  }
  return this
}

Buffer.prototype.toString = function toString () {
  var length = this.length | 0
  if (length === 0) return ''
  if (arguments.length === 0) return utf8Slice(this, 0, length)
  return slowToString.apply(this, arguments)
}

Buffer.prototype.equals = function equals (b) {
  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
  if (this === b) return true
  return Buffer.compare(this, b) === 0
}

Buffer.prototype.inspect = function inspect () {
  var str = ''
  var max = exports.INSPECT_MAX_BYTES
  if (this.length > 0) {
    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
    if (this.length > max) str += ' ... '
  }
  return '<Buffer ' + str + '>'
}

Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
  if (!Buffer.isBuffer(target)) {
    throw new TypeError('Argument must be a Buffer')
  }

  if (start === undefined) {
    start = 0
  }
  if (end === undefined) {
    end = target ? target.length : 0
  }
  if (thisStart === undefined) {
    thisStart = 0
  }
  if (thisEnd === undefined) {
    thisEnd = this.length
  }

  if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
    throw new RangeError('out of range index')
  }

  if (thisStart >= thisEnd && start >= end) {
    return 0
  }
  if (thisStart >= thisEnd) {
    return -1
  }
  if (start >= end) {
    return 1
  }

  start >>>= 0
  end >>>= 0
  thisStart >>>= 0
  thisEnd >>>= 0

  if (this === target) return 0

  var x = thisEnd - thisStart
  var y = end - start
  var len = Math.min(x, y)

  var thisCopy = this.slice(thisStart, thisEnd)
  var targetCopy = target.slice(start, end)

  for (var i = 0; i < len; ++i) {
    if (thisCopy[i] !== targetCopy[i]) {
      x = thisCopy[i]
      y = targetCopy[i]
      break
    }
  }

  if (x < y) return -1
  if (y < x) return 1
  return 0
}

// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
//
// Arguments:
// - buffer - a Buffer to search
// - val - a string, Buffer, or number
// - byteOffset - an index into `buffer`; will be clamped to an int32
// - encoding - an optional encoding, relevant is val is a string
// - dir - true for indexOf, false for lastIndexOf
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
  // Empty buffer means no match
  if (buffer.length === 0) return -1

  // Normalize byteOffset
  if (typeof byteOffset === 'string') {
    encoding = byteOffset
    byteOffset = 0
  } else if (byteOffset > 0x7fffffff) {
    byteOffset = 0x7fffffff
  } else if (byteOffset < -0x80000000) {
    byteOffset = -0x80000000
  }
  byteOffset = +byteOffset  // Coerce to Number.
  if (isNaN(byteOffset)) {
    // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
    byteOffset = dir ? 0 : (buffer.length - 1)
  }

  // Normalize byteOffset: negative offsets start from the end of the buffer
  if (byteOffset < 0) byteOffset = buffer.length + byteOffset
  if (byteOffset >= buffer.length) {
    if (dir) return -1
    else byteOffset = buffer.length - 1
  } else if (byteOffset < 0) {
    if (dir) byteOffset = 0
    else return -1
  }

  // Normalize val
  if (typeof val === 'string') {
    val = Buffer.from(val, encoding)
  }

  // Finally, search either indexOf (if dir is true) or lastIndexOf
  if (Buffer.isBuffer(val)) {
    // Special case: looking for empty string/buffer always fails
    if (val.length === 0) {
      return -1
    }
    return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
  } else if (typeof val === 'number') {
    val = val & 0xFF // Search for a byte value [0-255]
    if (Buffer.TYPED_ARRAY_SUPPORT &&
        typeof Uint8Array.prototype.indexOf === 'function') {
      if (dir) {
        return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
      } else {
        return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
      }
    }
    return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
  }

  throw new TypeError('val must be string, number or Buffer')
}

function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
  var indexSize = 1
  var arrLength = arr.length
  var valLength = val.length

  if (encoding !== undefined) {
    encoding = String(encoding).toLowerCase()
    if (encoding === 'ucs2' || encoding === 'ucs-2' ||
        encoding === 'utf16le' || encoding === 'utf-16le') {
      if (arr.length < 2 || val.length < 2) {
        return -1
      }
      indexSize = 2
      arrLength /= 2
      valLength /= 2
      byteOffset /= 2
    }
  }

  function read (buf, i) {
    if (indexSize === 1) {
      return buf[i]
    } else {
      return buf.readUInt16BE(i * indexSize)
    }
  }

  var i
  if (dir) {
    var foundIndex = -1
    for (i = byteOffset; i < arrLength; i++) {
      if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
        if (foundIndex === -1) foundIndex = i
        if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
      } else {
        if (foundIndex !== -1) i -= i - foundIndex
        foundIndex = -1
      }
    }
  } else {
    if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
    for (i = byteOffset; i >= 0; i--) {
      var found = true
      for (var j = 0; j < valLength; j++) {
        if (read(arr, i + j) !== read(val, j)) {
          found = false
          break
        }
      }
      if (found) return i
    }
  }

  return -1
}

Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
  return this.indexOf(val, byteOffset, encoding) !== -1
}

Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
  return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
}

Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
  return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
}

function hexWrite (buf, string, offset, length) {
  offset = Number(offset) || 0
  var remaining = buf.length - offset
  if (!length) {
    length = remaining
  } else {
    length = Number(length)
    if (length > remaining) {
      length = remaining
    }
  }

  // must be an even number of digits
  var strLen = string.length
  if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')

  if (length > strLen / 2) {
    length = strLen / 2
  }
  for (var i = 0; i < length; ++i) {
    var parsed = parseInt(string.substr(i * 2, 2), 16)
    if (isNaN(parsed)) return i
    buf[offset + i] = parsed
  }
  return i
}

function utf8Write (buf, string, offset, length) {
  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}

function asciiWrite (buf, string, offset, length) {
  return blitBuffer(asciiToBytes(string), buf, offset, length)
}

function latin1Write (buf, string, offset, length) {
  return asciiWrite(buf, string, offset, length)
}

function base64Write (buf, string, offset, length) {
  return blitBuffer(base64ToBytes(string), buf, offset, length)
}

function ucs2Write (buf, string, offset, length) {
  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}

Buffer.prototype.write = function write (string, offset, length, encoding) {
  // Buffer#write(string)
  if (offset === undefined) {
    encoding = 'utf8'
    length = this.length
    offset = 0
  // Buffer#write(string, encoding)
  } else if (length === undefined && typeof offset === 'string') {
    encoding = offset
    length = this.length
    offset = 0
  // Buffer#write(string, offset[, length][, encoding])
  } else if (isFinite(offset)) {
    offset = offset | 0
    if (isFinite(length)) {
      length = length | 0
      if (encoding === undefined) encoding = 'utf8'
    } else {
      encoding = length
      length = undefined
    }
  // legacy write(string, encoding, offset, length) - remove in v0.13
  } else {
    throw new Error(
      'Buffer.write(string, encoding, offset[, length]) is no longer supported'
    )
  }

  var remaining = this.length - offset
  if (length === undefined || length > remaining) length = remaining

  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
    throw new RangeError('Attempt to write outside buffer bounds')
  }

  if (!encoding) encoding = 'utf8'

  var loweredCase = false
  for (;;) {
    switch (encoding) {
      case 'hex':
        return hexWrite(this, string, offset, length)

      case 'utf8':
      case 'utf-8':
        return utf8Write(this, string, offset, length)

      case 'ascii':
        return asciiWrite(this, string, offset, length)

      case 'latin1':
      case 'binary':
        return latin1Write(this, string, offset, length)

      case 'base64':
        // Warning: maxLength not taken into account in base64Write
        return base64Write(this, string, offset, length)

      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return ucs2Write(this, string, offset, length)

      default:
        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
        encoding = ('' + encoding).toLowerCase()
        loweredCase = true
    }
  }
}

Buffer.prototype.toJSON = function toJSON () {
  return {
    type: 'Buffer',
    data: Array.prototype.slice.call(this._arr || this, 0)
  }
}

function base64Slice (buf, start, end) {
  if (start === 0 && end === buf.length) {
    return base64.fromByteArray(buf)
  } else {
    return base64.fromByteArray(buf.slice(start, end))
  }
}

function utf8Slice (buf, start, end) {
  end = Math.min(buf.length, end)
  var res = []

  var i = start
  while (i < end) {
    var firstByte = buf[i]
    var codePoint = null
    var bytesPerSequence = (firstByte > 0xEF) ? 4
      : (firstByte > 0xDF) ? 3
      : (firstByte > 0xBF) ? 2
      : 1

    if (i + bytesPerSequence <= end) {
      var secondByte, thirdByte, fourthByte, tempCodePoint

      switch (bytesPerSequence) {
        case 1:
          if (firstByte < 0x80) {
            codePoint = firstByte
          }
          break
        case 2:
          secondByte = buf[i + 1]
          if ((secondByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
            if (tempCodePoint > 0x7F) {
              codePoint = tempCodePoint
            }
          }
          break
        case 3:
          secondByte = buf[i + 1]
          thirdByte = buf[i + 2]
          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
              codePoint = tempCodePoint
            }
          }
          break
        case 4:
          secondByte = buf[i + 1]
          thirdByte = buf[i + 2]
          fourthByte = buf[i + 3]
          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
              codePoint = tempCodePoint
            }
          }
      }
    }

    if (codePoint === null) {
      // we did not generate a valid codePoint so insert a
      // replacement char (U+FFFD) and advance only 1 byte
      codePoint = 0xFFFD
      bytesPerSequence = 1
    } else if (codePoint > 0xFFFF) {
      // encode to utf16 (surrogate pair dance)
      codePoint -= 0x10000
      res.push(codePoint >>> 10 & 0x3FF | 0xD800)
      codePoint = 0xDC00 | codePoint & 0x3FF
    }

    res.push(codePoint)
    i += bytesPerSequence
  }

  return decodeCodePointsArray(res)
}

// Based on http://stackoverflow.com/a/22747272/680742, the browser with
// the lowest limit is Chrome, with 0x10000 args.
// We go 1 magnitude less, for safety
var MAX_ARGUMENTS_LENGTH = 0x1000

function decodeCodePointsArray (codePoints) {
  var len = codePoints.length
  if (len <= MAX_ARGUMENTS_LENGTH) {
    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
  }

  // Decode in chunks to avoid "call stack size exceeded".
  var res = ''
  var i = 0
  while (i < len) {
    res += String.fromCharCode.apply(
      String,
      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
    )
  }
  return res
}

function asciiSlice (buf, start, end) {
  var ret = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; ++i) {
    ret += String.fromCharCode(buf[i] & 0x7F)
  }
  return ret
}

function latin1Slice (buf, start, end) {
  var ret = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; ++i) {
    ret += String.fromCharCode(buf[i])
  }
  return ret
}

function hexSlice (buf, start, end) {
  var len = buf.length

  if (!start || start < 0) start = 0
  if (!end || end < 0 || end > len) end = len

  var out = ''
  for (var i = start; i < end; ++i) {
    out += toHex(buf[i])
  }
  return out
}

function utf16leSlice (buf, start, end) {
  var bytes = buf.slice(start, end)
  var res = ''
  for (var i = 0; i < bytes.length; i += 2) {
    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
  }
  return res
}

Buffer.prototype.slice = function slice (start, end) {
  var len = this.length
  start = ~~start
  end = end === undefined ? len : ~~end

  if (start < 0) {
    start += len
    if (start < 0) start = 0
  } else if (start > len) {
    start = len
  }

  if (end < 0) {
    end += len
    if (end < 0) end = 0
  } else if (end > len) {
    end = len
  }

  if (end < start) end = start

  var newBuf
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    newBuf = this.subarray(start, end)
    newBuf.__proto__ = Buffer.prototype
  } else {
    var sliceLen = end - start
    newBuf = new Buffer(sliceLen, undefined)
    for (var i = 0; i < sliceLen; ++i) {
      newBuf[i] = this[i + start]
    }
  }

  return newBuf
}

/*
 * Need to make sure that buffer isn't trying to write out of bounds.
 */
function checkOffset (offset, ext, length) {
  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
}

Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var val = this[offset]
  var mul = 1
  var i = 0
  while (++i < byteLength && (mul *= 0x100)) {
    val += this[offset + i] * mul
  }

  return val
}

Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) {
    checkOffset(offset, byteLength, this.length)
  }

  var val = this[offset + --byteLength]
  var mul = 1
  while (byteLength > 0 && (mul *= 0x100)) {
    val += this[offset + --byteLength] * mul
  }

  return val
}

Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 1, this.length)
  return this[offset]
}

Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  return this[offset] | (this[offset + 1] << 8)
}

Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  return (this[offset] << 8) | this[offset + 1]
}

Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return ((this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16)) +
      (this[offset + 3] * 0x1000000)
}

Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset] * 0x1000000) +
    ((this[offset + 1] << 16) |
    (this[offset + 2] << 8) |
    this[offset + 3])
}

Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var val = this[offset]
  var mul = 1
  var i = 0
  while (++i < byteLength && (mul *= 0x100)) {
    val += this[offset + i] * mul
  }
  mul *= 0x80

  if (val >= mul) val -= Math.pow(2, 8 * byteLength)

  return val
}

Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) checkOffset(offset, byteLength, this.length)

  var i = byteLength
  var mul = 1
  var val = this[offset + --i]
  while (i > 0 && (mul *= 0x100)) {
    val += this[offset + --i] * mul
  }
  mul *= 0x80

  if (val >= mul) val -= Math.pow(2, 8 * byteLength)

  return val
}

Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 1, this.length)
  if (!(this[offset] & 0x80)) return (this[offset])
  return ((0xff - this[offset] + 1) * -1)
}

Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  var val = this[offset] | (this[offset + 1] << 8)
  return (val & 0x8000) ? val | 0xFFFF0000 : val
}

Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 2, this.length)
  var val = this[offset + 1] | (this[offset] << 8)
  return (val & 0x8000) ? val | 0xFFFF0000 : val
}

Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset]) |
    (this[offset + 1] << 8) |
    (this[offset + 2] << 16) |
    (this[offset + 3] << 24)
}

Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)

  return (this[offset] << 24) |
    (this[offset + 1] << 16) |
    (this[offset + 2] << 8) |
    (this[offset + 3])
}

Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)
  return ieee754.read(this, offset, true, 23, 4)
}

Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 4, this.length)
  return ieee754.read(this, offset, false, 23, 4)
}

Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 8, this.length)
  return ieee754.read(this, offset, true, 52, 8)
}

Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
  if (!noAssert) checkOffset(offset, 8, this.length)
  return ieee754.read(this, offset, false, 52, 8)
}

function checkInt (buf, value, offset, ext, max, min) {
  if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
  if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
  if (offset + ext > buf.length) throw new RangeError('Index out of range')
}

Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) {
    var maxBytes = Math.pow(2, 8 * byteLength) - 1
    checkInt(this, value, offset, byteLength, maxBytes, 0)
  }

  var mul = 1
  var i = 0
  this[offset] = value & 0xFF
  while (++i < byteLength && (mul *= 0x100)) {
    this[offset + i] = (value / mul) & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  byteLength = byteLength | 0
  if (!noAssert) {
    var maxBytes = Math.pow(2, 8 * byteLength) - 1
    checkInt(this, value, offset, byteLength, maxBytes, 0)
  }

  var i = byteLength - 1
  var mul = 1
  this[offset + i] = value & 0xFF
  while (--i >= 0 && (mul *= 0x100)) {
    this[offset + i] = (value / mul) & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  this[offset] = (value & 0xff)
  return offset + 1
}

function objectWriteUInt16 (buf, value, offset, littleEndian) {
  if (value < 0) value = 0xffff + value + 1
  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
      (littleEndian ? i : 1 - i) * 8
  }
}

Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
  } else {
    objectWriteUInt16(this, value, offset, true)
  }
  return offset + 2
}

Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
  } else {
    objectWriteUInt16(this, value, offset, false)
  }
  return offset + 2
}

function objectWriteUInt32 (buf, value, offset, littleEndian) {
  if (value < 0) value = 0xffffffff + value + 1
  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
  }
}

Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset + 3] = (value >>> 24)
    this[offset + 2] = (value >>> 16)
    this[offset + 1] = (value >>> 8)
    this[offset] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, true)
  }
  return offset + 4
}

Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, false)
  }
  return offset + 4
}

Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) {
    var limit = Math.pow(2, 8 * byteLength - 1)

    checkInt(this, value, offset, byteLength, limit - 1, -limit)
  }

  var i = 0
  var mul = 1
  var sub = 0
  this[offset] = value & 0xFF
  while (++i < byteLength && (mul *= 0x100)) {
    if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
      sub = 1
    }
    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) {
    var limit = Math.pow(2, 8 * byteLength - 1)

    checkInt(this, value, offset, byteLength, limit - 1, -limit)
  }

  var i = byteLength - 1
  var mul = 1
  var sub = 0
  this[offset + i] = value & 0xFF
  while (--i >= 0 && (mul *= 0x100)) {
    if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
      sub = 1
    }
    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  }

  return offset + byteLength
}

Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
  if (value < 0) value = 0xff + value + 1
  this[offset] = (value & 0xff)
  return offset + 1
}

Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
  } else {
    objectWriteUInt16(this, value, offset, true)
  }
  return offset + 2
}

Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
  } else {
    objectWriteUInt16(this, value, offset, false)
  }
  return offset + 2
}

Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
    this[offset + 2] = (value >>> 16)
    this[offset + 3] = (value >>> 24)
  } else {
    objectWriteUInt32(this, value, offset, true)
  }
  return offset + 4
}

Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
  value = +value
  offset = offset | 0
  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
  if (value < 0) value = 0xffffffff + value + 1
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
  } else {
    objectWriteUInt32(this, value, offset, false)
  }
  return offset + 4
}

function checkIEEE754 (buf, value, offset, ext, max, min) {
  if (offset + ext > buf.length) throw new RangeError('Index out of range')
  if (offset < 0) throw new RangeError('Index out of range')
}

function writeFloat (buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
  }
  ieee754.write(buf, value, offset, littleEndian, 23, 4)
  return offset + 4
}

Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
  return writeFloat(this, value, offset, true, noAssert)
}

Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
  return writeFloat(this, value, offset, false, noAssert)
}

function writeDouble (buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
  }
  ieee754.write(buf, value, offset, littleEndian, 52, 8)
  return offset + 8
}

Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
  return writeDouble(this, value, offset, true, noAssert)
}

Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
  return writeDouble(this, value, offset, false, noAssert)
}

// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
  if (!start) start = 0
  if (!end && end !== 0) end = this.length
  if (targetStart >= target.length) targetStart = target.length
  if (!targetStart) targetStart = 0
  if (end > 0 && end < start) end = start

  // Copy 0 bytes; we're done
  if (end === start) return 0
  if (target.length === 0 || this.length === 0) return 0

  // Fatal error conditions
  if (targetStart < 0) {
    throw new RangeError('targetStart out of bounds')
  }
  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
  if (end < 0) throw new RangeError('sourceEnd out of bounds')

  // Are we oob?
  if (end > this.length) end = this.length
  if (target.length - targetStart < end - start) {
    end = target.length - targetStart + start
  }

  var len = end - start
  var i

  if (this === target && start < targetStart && targetStart < end) {
    // descending copy from end
    for (i = len - 1; i >= 0; --i) {
      target[i + targetStart] = this[i + start]
    }
  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
    // ascending copy from start
    for (i = 0; i < len; ++i) {
      target[i + targetStart] = this[i + start]
    }
  } else {
    Uint8Array.prototype.set.call(
      target,
      this.subarray(start, start + len),
      targetStart
    )
  }

  return len
}

// Usage:
//    buffer.fill(number[, offset[, end]])
//    buffer.fill(buffer[, offset[, end]])
//    buffer.fill(string[, offset[, end]][, encoding])
Buffer.prototype.fill = function fill (val, start, end, encoding) {
  // Handle string cases:
  if (typeof val === 'string') {
    if (typeof start === 'string') {
      encoding = start
      start = 0
      end = this.length
    } else if (typeof end === 'string') {
      encoding = end
      end = this.length
    }
    if (val.length === 1) {
      var code = val.charCodeAt(0)
      if (code < 256) {
        val = code
      }
    }
    if (encoding !== undefined && typeof encoding !== 'string') {
      throw new TypeError('encoding must be a string')
    }
    if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
      throw new TypeError('Unknown encoding: ' + encoding)
    }
  } else if (typeof val === 'number') {
    val = val & 255
  }

  // Invalid ranges are not set to a default, so can range check early.
  if (start < 0 || this.length < start || this.length < end) {
    throw new RangeError('Out of range index')
  }

  if (end <= start) {
    return this
  }

  start = start >>> 0
  end = end === undefined ? this.length : end >>> 0

  if (!val) val = 0

  var i
  if (typeof val === 'number') {
    for (i = start; i < end; ++i) {
      this[i] = val
    }
  } else {
    var bytes = Buffer.isBuffer(val)
      ? val
      : utf8ToBytes(new Buffer(val, encoding).toString())
    var len = bytes.length
    for (i = 0; i < end - start; ++i) {
      this[i + start] = bytes[i % len]
    }
  }

  return this
}

// HELPER FUNCTIONS
// ================

var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g

function base64clean (str) {
  // Node strips out invalid characters like \n and \t from the string, base64-js does not
  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
  // Node converts strings with length < 2 to ''
  if (str.length < 2) return ''
  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
  while (str.length % 4 !== 0) {
    str = str + '='
  }
  return str
}

function stringtrim (str) {
  if (str.trim) return str.trim()
  return str.replace(/^\s+|\s+$/g, '')
}

function toHex (n) {
  if (n < 16) return '0' + n.toString(16)
  return n.toString(16)
}

function utf8ToBytes (string, units) {
  units = units || Infinity
  var codePoint
  var length = string.length
  var leadSurrogate = null
  var bytes = []

  for (var i = 0; i < length; ++i) {
    codePoint = string.charCodeAt(i)

    // is surrogate component
    if (codePoint > 0xD7FF && codePoint < 0xE000) {
      // last char was a lead
      if (!leadSurrogate) {
        // no lead yet
        if (codePoint > 0xDBFF) {
          // unexpected trail
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          continue
        } else if (i + 1 === length) {
          // unpaired lead
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          continue
        }

        // valid lead
        leadSurrogate = codePoint

        continue
      }

      // 2 leads in a row
      if (codePoint < 0xDC00) {
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
        leadSurrogate = codePoint
        continue
      }

      // valid surrogate pair
      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
    } else if (leadSurrogate) {
      // valid bmp char, but last char was a lead
      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
    }

    leadSurrogate = null

    // encode utf8
    if (codePoint < 0x80) {
      if ((units -= 1) < 0) break
      bytes.push(codePoint)
    } else if (codePoint < 0x800) {
      if ((units -= 2) < 0) break
      bytes.push(
        codePoint >> 0x6 | 0xC0,
        codePoint & 0x3F | 0x80
      )
    } else if (codePoint < 0x10000) {
      if ((units -= 3) < 0) break
      bytes.push(
        codePoint >> 0xC | 0xE0,
        codePoint >> 0x6 & 0x3F | 0x80,
        codePoint & 0x3F | 0x80
      )
    } else if (codePoint < 0x110000) {
      if ((units -= 4) < 0) break
      bytes.push(
        codePoint >> 0x12 | 0xF0,
        codePoint >> 0xC & 0x3F | 0x80,
        codePoint >> 0x6 & 0x3F | 0x80,
        codePoint & 0x3F | 0x80
      )
    } else {
      throw new Error('Invalid code point')
    }
  }

  return bytes
}

function asciiToBytes (str) {
  var byteArray = []
  for (var i = 0; i < str.length; ++i) {
    // Node's code seems to be doing this and not & 0x7F..
    byteArray.push(str.charCodeAt(i) & 0xFF)
  }
  return byteArray
}

function utf16leToBytes (str, units) {
  var c, hi, lo
  var byteArray = []
  for (var i = 0; i < str.length; ++i) {
    if ((units -= 2) < 0) break

    c = str.charCodeAt(i)
    hi = c >> 8
    lo = c % 256
    byteArray.push(lo)
    byteArray.push(hi)
  }

  return byteArray
}

function base64ToBytes (str) {
  return base64.toByteArray(base64clean(str))
}

function blitBuffer (src, dst, offset, length) {
  for (var i = 0; i < length; ++i) {
    if ((i + offset >= dst.length) || (i >= src.length)) break
    dst[i + offset] = src[i]
  }
  return i
}

function isnan (val) {
  return val !== val // eslint-disable-line no-self-compare
}

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(48)))

exports.byteLength = byteLength
exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray

var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array

var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for (var i = 0, len = code.length; i < len; ++i) {
  lookup[i] = code[i]
  revLookup[code.charCodeAt(i)] = i
}

// Support decoding URL-safe base64 strings, as Node.js does.
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63

function getLens (b64) {
  var len = b64.length

  if (len % 4 > 0) {
    throw new Error('Invalid string. Length must be a multiple of 4')
  }

  // Trim off extra bytes after placeholder bytes are found
  // See: https://github.com/beatgammit/base64-js/issues/42
  var validLen = b64.indexOf('=')
  if (validLen === -1) validLen = len

  var placeHoldersLen = validLen === len
    ? 0
    : 4 - (validLen % 4)

  return [validLen, placeHoldersLen]
}

// base64 is 4/3 + up to two characters of the original data
function byteLength (b64) {
  var lens = getLens(b64)
  var validLen = lens[0]
  var placeHoldersLen = lens[1]
  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}

function _byteLength (b64, validLen, placeHoldersLen) {
  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}

function toByteArray (b64) {
  var tmp
  var lens = getLens(b64)
  var validLen = lens[0]
  var placeHoldersLen = lens[1]

  var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))

  var curByte = 0

  // if there are placeholders, only get up to the last complete 4 chars
  var len = placeHoldersLen > 0
    ? validLen - 4
    : validLen

  var i
  for (i = 0; i < len; i += 4) {
    tmp =
      (revLookup[b64.charCodeAt(i)] << 18) |
      (revLookup[b64.charCodeAt(i + 1)] << 12) |
      (revLookup[b64.charCodeAt(i + 2)] << 6) |
      revLookup[b64.charCodeAt(i + 3)]
    arr[curByte++] = (tmp >> 16) & 0xFF
    arr[curByte++] = (tmp >> 8) & 0xFF
    arr[curByte++] = tmp & 0xFF
  }

  if (placeHoldersLen === 2) {
    tmp =
      (revLookup[b64.charCodeAt(i)] << 2) |
      (revLookup[b64.charCodeAt(i + 1)] >> 4)
    arr[curByte++] = tmp & 0xFF
  }

  if (placeHoldersLen === 1) {
    tmp =
      (revLookup[b64.charCodeAt(i)] << 10) |
      (revLookup[b64.charCodeAt(i + 1)] << 4) |
      (revLookup[b64.charCodeAt(i + 2)] >> 2)
    arr[curByte++] = (tmp >> 8) & 0xFF
    arr[curByte++] = tmp & 0xFF
  }

  return arr
}

function tripletToBase64 (num) {
  return lookup[num >> 18 & 0x3F] +
    lookup[num >> 12 & 0x3F] +
    lookup[num >> 6 & 0x3F] +
    lookup[num & 0x3F]
}

function encodeChunk (uint8, start, end) {
  var tmp
  var output = []
  for (var i = start; i < end; i += 3) {
    tmp =
      ((uint8[i] << 16) & 0xFF0000) +
      ((uint8[i + 1] << 8) & 0xFF00) +
      (uint8[i + 2] & 0xFF)
    output.push(tripletToBase64(tmp))
  }
  return output.join('')
}

function fromByteArray (uint8) {
  var tmp
  var len = uint8.length
  var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
  var parts = []
  var maxChunkLength = 16383 // must be multiple of 3

  // go through the array every three bytes, we'll deal with trailing stuff later
  for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
    parts.push(encodeChunk(
      uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
    ))
  }

  // pad the end with zeros, but make sure to not forget the extra bytes
  if (extraBytes === 1) {
    tmp = uint8[len - 1]
    parts.push(
      lookup[tmp >> 2] +
      lookup[(tmp << 4) & 0x3F] +
      '=='
    )
  } else if (extraBytes === 2) {
    tmp = (uint8[len - 2] << 8) + uint8[len - 1]
    parts.push(
      lookup[tmp >> 10] +
      lookup[(tmp >> 4) & 0x3F] +
      lookup[(tmp << 2) & 0x3F] +
      '='
    )
  }

  return parts.join('')
}
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
  var e, m
  var eLen = (nBytes * 8) - mLen - 1
  var eMax = (1 << eLen) - 1
  var eBias = eMax >> 1
  var nBits = -7
  var i = isLE ? (nBytes - 1) : 0
  var d = isLE ? -1 : 1
  var s = buffer[offset + i]

  i += d

  e = s & ((1 << (-nBits)) - 1)
  s >>= (-nBits)
  nBits += eLen
  for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}

  m = e & ((1 << (-nBits)) - 1)
  e >>= (-nBits)
  nBits += mLen
  for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}

  if (e === 0) {
    e = 1 - eBias
  } else if (e === eMax) {
    return m ? NaN : ((s ? -1 : 1) * Infinity)
  } else {
    m = m + Math.pow(2, mLen)
    e = e - eBias
  }
  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
}

exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
  var e, m, c
  var eLen = (nBytes * 8) - mLen - 1
  var eMax = (1 << eLen) - 1
  var eBias = eMax >> 1
  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
  var i = isLE ? 0 : (nBytes - 1)
  var d = isLE ? 1 : -1
  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0

  value = Math.abs(value)

  if (isNaN(value) || value === Infinity) {
    m = isNaN(value) ? 1 : 0
    e = eMax
  } else {
    e = Math.floor(Math.log(value) / Math.LN2)
    if (value * (c = Math.pow(2, -e)) < 1) {
      e--
      c *= 2
    }
    if (e + eBias >= 1) {
      value += rt / c
    } else {
      value += rt * Math.pow(2, 1 - eBias)
    }
    if (value * c >= 2) {
      e++
      c /= 2
    }

    if (e + eBias >= eMax) {
      m = 0
      e = eMax
    } else if (e + eBias >= 1) {
      m = ((value * c) - 1) * Math.pow(2, mLen)
      e = e + eBias
    } else {
      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
      e = 0
    }
  }

  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}

  e = (e << mLen) | m
  eLen += mLen
  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}

  buffer[offset + i - d] |= s * 128
}
module.exports = Array.isArray || function (arr) {
  return Object.prototype.toString.call(arr) == '[object Array]';
};
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return LogLevel; });
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// These values are designed to match the ASP.NET Log Levels since that's the pattern we're emulating here.
/** Indicates the severity of a log message.
 *
 * Log Levels are ordered in increasing severity. So `Debug` is more severe than `Trace`, etc.
 */
var LogLevel;
(function (LogLevel) {
    /** Log level for very low severity diagnostic messages. */
    LogLevel[LogLevel["Trace"] = 0] = "Trace";
    /** Log level for low severity diagnostic messages. */
    LogLevel[LogLevel["Debug"] = 1] = "Debug";
    /** Log level for informational diagnostic messages. */
    LogLevel[LogLevel["Information"] = 2] = "Information";
    /** Log level for diagnostic messages that indicate a non-fatal problem. */
    LogLevel[LogLevel["Warning"] = 3] = "Warning";
    /** Log level for diagnostic messages that indicate a failure in the current operation. */
    LogLevel[LogLevel["Error"] = 4] = "Error";
    /** Log level for diagnostic messages that indicate a failure that will terminate the entire application. */
    LogLevel[LogLevel["Critical"] = 5] = "Critical";
    /** The highest possible log level. Used when configuring logging to indicate that no log messages should be emitted. */
    LogLevel[LogLevel["None"] = 6] = "None";
})(LogLevel || (LogLevel = {}));
//# sourceMappingURL=ILogger.js.map/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Arg; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return Platform; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return getDataDetail; });
/* unused harmony export formatArrayBuffer */
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return isArrayBuffer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return sendMessage; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return createLogger; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return SubjectSubscription; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return ConsoleLogger; });
/* harmony import */ var _ILogger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
/* harmony import */ var _Loggers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(156);
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (undefined && undefined.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};


/** @private */
var Arg = /** @class */ (function () {
    function Arg() {
    }
    Arg.isRequired = function (val, name) {
        if (val === null || val === undefined) {
            throw new Error("The '" + name + "' argument is required.");
        }
    };
    Arg.isIn = function (val, values, name) {
        // TypeScript enums have keys for **both** the name and the value of each enum member on the type itself.
        if (!(val in values)) {
            throw new Error("Unknown " + name + " value: " + val + ".");
        }
    };
    return Arg;
}());

/** @private */
var Platform = /** @class */ (function () {
    function Platform() {
    }
    Object.defineProperty(Platform, "isBrowser", {
        get: function () {
            return typeof window === "object";
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform, "isWebWorker", {
        get: function () {
            return typeof self === "object" && "importScripts" in self;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform, "isNode", {
        get: function () {
            return !this.isBrowser && !this.isWebWorker;
        },
        enumerable: true,
        configurable: true
    });
    return Platform;
}());

/** @private */
function getDataDetail(data, includeContent) {
    var detail = "";
    if (isArrayBuffer(data)) {
        detail = "Binary data of length " + data.byteLength;
        if (includeContent) {
            detail += ". Content: '" + formatArrayBuffer(data) + "'";
        }
    }
    else if (typeof data === "string") {
        detail = "String data of length " + data.length;
        if (includeContent) {
            detail += ". Content: '" + data + "'";
        }
    }
    return detail;
}
/** @private */
function formatArrayBuffer(data) {
    var view = new Uint8Array(data);
    // Uint8Array.map only supports returning another Uint8Array?
    var str = "";
    view.forEach(function (num) {
        var pad = num < 16 ? "0" : "";
        str += "0x" + pad + num.toString(16) + " ";
    });
    // Trim of trailing space.
    return str.substr(0, str.length - 1);
}
// Also in signalr-protocol-msgpack/Utils.ts
/** @private */
function isArrayBuffer(val) {
    return val && typeof ArrayBuffer !== "undefined" &&
        (val instanceof ArrayBuffer ||
            // Sometimes we get an ArrayBuffer that doesn't satisfy instanceof
            (val.constructor && val.constructor.name === "ArrayBuffer"));
}
/** @private */
function sendMessage(logger, transportName, httpClient, url, accessTokenFactory, content, logMessageContent) {
    return __awaiter(this, void 0, void 0, function () {
        var _a, headers, token, responseType, response;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    if (!accessTokenFactory) return [3 /*break*/, 2];
                    return [4 /*yield*/, accessTokenFactory()];
                case 1:
                    token = _b.sent();
                    if (token) {
                        headers = (_a = {},
                            _a["Authorization"] = "Bearer " + token,
                            _a);
                    }
                    _b.label = 2;
                case 2:
                    logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"].Trace, "(" + transportName + " transport) sending data. " + getDataDetail(content, logMessageContent) + ".");
                    responseType = isArrayBuffer(content) ? "arraybuffer" : "text";
                    return [4 /*yield*/, httpClient.post(url, {
                            content: content,
                            headers: headers,
                            responseType: responseType,
                        })];
                case 3:
                    response = _b.sent();
                    logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"].Trace, "(" + transportName + " transport) request complete. Response status: " + response.statusCode + ".");
                    return [2 /*return*/];
            }
        });
    });
}
/** @private */
function createLogger(logger) {
    if (logger === undefined) {
        return new ConsoleLogger(_ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"].Information);
    }
    if (logger === null) {
        return _Loggers__WEBPACK_IMPORTED_MODULE_1__[/* NullLogger */ "a"].instance;
    }
    if (logger.log) {
        return logger;
    }
    return new ConsoleLogger(logger);
}
/** @private */
var SubjectSubscription = /** @class */ (function () {
    function SubjectSubscription(subject, observer) {
        this.subject = subject;
        this.observer = observer;
    }
    SubjectSubscription.prototype.dispose = function () {
        var index = this.subject.observers.indexOf(this.observer);
        if (index > -1) {
            this.subject.observers.splice(index, 1);
        }
        if (this.subject.observers.length === 0 && this.subject.cancelCallback) {
            this.subject.cancelCallback().catch(function (_) { });
        }
    };
    return SubjectSubscription;
}());

/** @private */
var ConsoleLogger = /** @class */ (function () {
    function ConsoleLogger(minimumLogLevel) {
        this.minimumLogLevel = minimumLogLevel;
        this.outputConsole = console;
    }
    ConsoleLogger.prototype.log = function (logLevel, message) {
        if (logLevel >= this.minimumLogLevel) {
            switch (logLevel) {
                case _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"].Critical:
                case _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"].Error:
                    this.outputConsole.error("[" + new Date().toISOString() + "] " + _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"][logLevel] + ": " + message);
                    break;
                case _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"].Warning:
                    this.outputConsole.warn("[" + new Date().toISOString() + "] " + _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"][logLevel] + ": " + message);
                    break;
                case _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"].Information:
                    this.outputConsole.info("[" + new Date().toISOString() + "] " + _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"][logLevel] + ": " + message);
                    break;
                default:
                    // console.debug only goes to attached debuggers in Node, so we use console.log for Trace and Debug
                    this.outputConsole.log("[" + new Date().toISOString() + "] " + _ILogger__WEBPACK_IMPORTED_MODULE_0__[/* LogLevel */ "a"][logLevel] + ": " + message);
                    break;
            }
        }
    };
    return ConsoleLogger;
}());

//# sourceMappingURL=Utils.js.map/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return NullLogger; });
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
/** A logger that does nothing when log messages are sent to it. */
var NullLogger = /** @class */ (function () {
    function NullLogger() {
    }
    /** @inheritDoc */
    // tslint:disable-next-line
    NullLogger.prototype.log = function (_logLevel, _message) {
    };
    /** The singleton instance of the {@link @microsoft/signalr.NullLogger}. */
    NullLogger.instance = new NullLogger();
    return NullLogger;
}());

//# sourceMappingURL=Loggers.js.map/* WEBPACK VAR INJECTION */(function(Buffer) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return HandshakeProtocol; });
/* harmony import */ var _TextMessageFormat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(160);
/* harmony import */ var _Utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(29);
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.


/** @private */
var HandshakeProtocol = /** @class */ (function () {
    function HandshakeProtocol() {
    }
    // Handshake request is always JSON
    HandshakeProtocol.prototype.writeHandshakeRequest = function (handshakeRequest) {
        return _TextMessageFormat__WEBPACK_IMPORTED_MODULE_0__[/* TextMessageFormat */ "a"].write(JSON.stringify(handshakeRequest));
    };
    HandshakeProtocol.prototype.parseHandshakeResponse = function (data) {
        var responseMessage;
        var messageData;
        var remainingData;
        if (Object(_Utils__WEBPACK_IMPORTED_MODULE_1__[/* isArrayBuffer */ "g"])(data) || (typeof Buffer !== "undefined" && data instanceof Buffer)) {
            // Format is binary but still need to read JSON text from handshake response
            var binaryData = new Uint8Array(data);
            var separatorIndex = binaryData.indexOf(_TextMessageFormat__WEBPACK_IMPORTED_MODULE_0__[/* TextMessageFormat */ "a"].RecordSeparatorCode);
            if (separatorIndex === -1) {
                throw new Error("Message is incomplete.");
            }
            // content before separator is handshake response
            // optional content after is additional messages
            var responseLength = separatorIndex + 1;
            messageData = String.fromCharCode.apply(null, binaryData.slice(0, responseLength));
            remainingData = (binaryData.byteLength > responseLength) ? binaryData.slice(responseLength).buffer : null;
        }
        else {
            var textData = data;
            var separatorIndex = textData.indexOf(_TextMessageFormat__WEBPACK_IMPORTED_MODULE_0__[/* TextMessageFormat */ "a"].RecordSeparator);
            if (separatorIndex === -1) {
                throw new Error("Message is incomplete.");
            }
            // content before separator is handshake response
            // optional content after is additional messages
            var responseLength = separatorIndex + 1;
            messageData = textData.substring(0, responseLength);
            remainingData = (textData.length > responseLength) ? textData.substring(responseLength) : null;
        }
        // At this point we should have just the single handshake message
        var messages = _TextMessageFormat__WEBPACK_IMPORTED_MODULE_0__[/* TextMessageFormat */ "a"].parse(messageData);
        var response = JSON.parse(messages[0]);
        if (response.type) {
            throw new Error("Expected a handshake response from the server.");
        }
        responseMessage = response;
        // multiple messages could have arrived with handshake
        // return additional data to be parsed as usual, or null if all parsed
        return [remainingData, responseMessage];
    };
    return HandshakeProtocol;
}());

//# sourceMappingURL=HandshakeProtocol.js.map
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(626).Buffer))/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return TextMessageFormat; });
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Not exported from index
/** @private */
var TextMessageFormat = /** @class */ (function () {
    function TextMessageFormat() {
    }
    TextMessageFormat.write = function (output) {
        return "" + output + TextMessageFormat.RecordSeparator;
    };
    TextMessageFormat.parse = function (input) {
        if (input[input.length - 1] !== TextMessageFormat.RecordSeparator) {
            throw new Error("Message is incomplete.");
        }
        var messages = input.split(TextMessageFormat.RecordSeparator);
        messages.pop();
        return messages;
    };
    TextMessageFormat.RecordSeparatorCode = 0x1e;
    TextMessageFormat.RecordSeparator = String.fromCharCode(TextMessageFormat.RecordSeparatorCode);
    return TextMessageFormat;
}());

//# sourceMappingURL=TextMessageFormat.js.map
/**
 * Module dependencies.
 */

var url = __webpack_require__(754);
var parser = __webpack_require__(564);
var Manager = __webpack_require__(629);
var debug = __webpack_require__(148)('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__(629);
exports.Socket = __webpack_require__(635);
/* WEBPACK VAR INJECTION */(function(global) {
/**
 * Module dependencies.
 */

var parseuri = __webpack_require__(627);
var debug = __webpack_require__(148)('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(this, __webpack_require__(48)))/**
 * 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;
};
/* WEBPACK VAR INJECTION */(function(process) {
/**
 * This is the web browser implementation of `debug()`.
 *
 * Expose `debug()` as the module.
 */

exports = module.exports = __webpack_require__(756);
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(this, __webpack_require__(755)))// 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.prependListener = noop;
process.prependOnceListener = noop;

process.listeners = function (name) { return [] }

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; };

/**
 * 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__(757);

/**
 * 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;
}
/**
 * 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'
}

/**
 * Module dependencies.
 */

var debug = __webpack_require__(148)('socket.io-parser');
var json = __webpack_require__(758);
var Emitter = __webpack_require__(213);
var binary = __webpack_require__(760);
var isBuf = __webpack_require__(628);

/**
 * 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'
  };
}
/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! 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 =  true && __webpack_require__(759);

  // 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(this, __webpack_require__(212)(module), __webpack_require__(48)))/* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {/* globals __webpack_amd_options__ */
module.exports = __webpack_amd_options__;

/* WEBPACK VAR INJECTION */}.call(this, {}))
/**
 * 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;
};
/* WEBPACK VAR INJECTION */(function(global) {/*global Blob,File*/

/**
 * Module requirements
 */

var isArray = __webpack_require__(338);
var isBuf = __webpack_require__(628);

/**
 * 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(this, __webpack_require__(48)))/* 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(this, __webpack_require__(48)))
/**
 * Module dependencies.
 */

var eio = __webpack_require__(761);
var Socket = __webpack_require__(635);
var Emitter = __webpack_require__(213);
var parser = __webpack_require__(564);
var on = __webpack_require__(636);
var bind = __webpack_require__(637);
var debug = __webpack_require__(148)('socket.io-client:manager');
var indexOf = __webpack_require__(634);
var Backoff = __webpack_require__(777);

/**
 * 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);
};

module.exports = __webpack_require__(762);

module.exports = __webpack_require__(763);

/**
 * Exports parser
 *
 * @api public
 *
 */
module.exports.parser = __webpack_require__(214);
/* WEBPACK VAR INJECTION */(function(global) {/**
 * Module dependencies.
 */

var transports = __webpack_require__(630);
var Emitter = __webpack_require__(213);
var debug = __webpack_require__(148)('engine.io-client:socket');
var index = __webpack_require__(634);
var parser = __webpack_require__(214);
var parseuri = __webpack_require__(627);
var parsejson = __webpack_require__(775);
var parseqs = __webpack_require__(567);

/**
 * 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__(566);
Socket.transports = __webpack_require__(630);
Socket.parser = __webpack_require__(214);

/**
 * 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(this, __webpack_require__(48)))/* WEBPACK VAR INJECTION */(function(global) {/**
 * Module dependencies
 */

var XMLHttpRequest = __webpack_require__(565);
var XHR = __webpack_require__(765);
var JSONP = __webpack_require__(772);
var websocket = __webpack_require__(773);

/**
 * 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(this, __webpack_require__(48)))/* WEBPACK VAR INJECTION */(function(global) {// browser shim for xmlhttprequest module

var hasCORS = __webpack_require__(764);

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(this, __webpack_require__(48)))
/**
 * 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;
}
/* WEBPACK VAR INJECTION */(function(global) {/**
 * Module requirements.
 */

var XMLHttpRequest = __webpack_require__(565);
var Polling = __webpack_require__(631);
var Emitter = __webpack_require__(213);
var inherit = __webpack_require__(315);
var debug = __webpack_require__(148)('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(this, __webpack_require__(48)))/**
 * Module dependencies.
 */

var Transport = __webpack_require__(566);
var parseqs = __webpack_require__(567);
var parser = __webpack_require__(214);
var inherit = __webpack_require__(315);
var yeast = __webpack_require__(633);
var debug = __webpack_require__(148)('engine.io-client:polling');

/**
 * Module exports.
 */

module.exports = Polling;

/**
 * Is XHR2 supported?
 */

var hasXHR2 = (function () {
  var XMLHttpRequest = __webpack_require__(565);
  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;
};
/**
 * Module dependencies.
 */

var parser = __webpack_require__(214);
var Emitter = __webpack_require__(213);

/**
 * 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');
};
/* WEBPACK VAR INJECTION */(function(global) {/**
 * Module dependencies.
 */

var keys = __webpack_require__(766);
var hasBinary = __webpack_require__(632);
var sliceBuffer = __webpack_require__(767);
var after = __webpack_require__(768);
var utf8 = __webpack_require__(769);

var base64encoder;
if (global && global.ArrayBuffer) {
  base64encoder = __webpack_require__(770);
}

/**
 * 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__(771);

/**
 * 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(this, __webpack_require__(48)))
/**
 * 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;
};
/* WEBPACK VAR INJECTION */(function(global) {
/*
 * Module requirements.
 */

var isArray = __webpack_require__(338);

/**
 * 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(this, __webpack_require__(48)))/**
 * 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;
};
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() {}
/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/wtf8 v1.0.0 by @mathias */
;(function(root) {

	// Detect free variables `exports`
	var freeExports =  true && exports;

	// Detect free variable `module`
	var freeModule =  true && 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 { var key, hasOwnProperty, object; }

}(this));

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(212)(module), __webpack_require__(48)))/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getJSONP; });
var JSONP_TIMEOUT = 20000;
var jsonpTimeouts = {};
var callbackCounter = 0;
function getJSONP(url) {
  var callbackNameOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  var onSuccess = arguments.length > 2 ? arguments[2] : undefined;
  var onError = arguments.length > 3 ? arguments[3] : undefined;
  var callbackFnName = callbackNameOverride || "_WidgetJPCB".concat(callbackCounter); // Before, these global JSONP functions were deleted from the window when the script would
  // load. Unfortunately due to Cloudflare's Rocket Wordpress plugin, it was calling the `onload`
  // function before the script was applied to the page causing the wigdet to not load. This is
  // a temporary fix to handle that until these requests can be made into CORS requests.

  window[callbackFnName] = function windowCallback() {
    onSuccess.apply(void 0, arguments);

    window[callbackFnName] = function () {};
  };

  var script = document.createElement('script');
  script.setAttribute('data-cfasync', false);
  script.setAttribute('async', true);
  script.setAttribute('type', 'text/javascript');
  callbackCounter += 1;
  var src = url;
  if (src.indexOf('?') < 0) src += '?_=_';
  src += "&callback=".concat(callbackFnName);
  var scriptReady = false;

  function readyFn() {
    if (!scriptReady && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) {
      scriptReady = true;
      clearTimeout(jsonpTimeouts["JSONPTimeout".concat(callbackFnName)]);
      delete jsonpTimeouts["JSONPTimeout".concat(callbackFnName)];
    }
  }

  script.onload = readyFn;
  script.onreadystatechange = readyFn;
  if (window.location.search.indexOf('pcforcemobile') >= 0) src += '&forceMobile=true';
  script.setAttribute('src', src);
  document.getElementsByTagName('HEAD')[0].appendChild(script);
  jsonpTimeouts["JSONPTimeout".concat(callbackFnName)] = setTimeout(function () {
    return onError();
  }, JSONP_TIMEOUT);
}/* 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(this, __webpack_require__(48)))/**
 * 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;
};

module.exports = function(a, b){
  var fn = function(){};
  fn.prototype = b.prototype;
  a.prototype = new fn;
  a.prototype.constructor = a;
};

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;
/* WEBPACK VAR INJECTION */(function(global) {
/**
 * Module requirements.
 */

var Polling = __webpack_require__(631);
var inherit = __webpack_require__(315);

/**
 * 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(this, __webpack_require__(48)))/* WEBPACK VAR INJECTION */(function(global) {/**
 * Module dependencies.
 */

var Transport = __webpack_require__(566);
var parser = __webpack_require__(214);
var parseqs = __webpack_require__(567);
var inherit = __webpack_require__(315);
var yeast = __webpack_require__(633);
var debug = __webpack_require__(148)('engine.io-client:websocket');
var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
var NodeWebSocket;
if (typeof window === 'undefined') {
  try {
    NodeWebSocket = __webpack_require__(774);
  } 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(this, __webpack_require__(48)))
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;
};/* 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(this, __webpack_require__(48)))
/**
 * Module dependencies.
 */

var parser = __webpack_require__(564);
var Emitter = __webpack_require__(213);
var toArray = __webpack_require__(776);
var on = __webpack_require__(636);
var bind = __webpack_require__(637);
var debug = __webpack_require__(148)('socket.io-client:socket');
var hasBin = __webpack_require__(632);

/**
 * 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;
};
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
}

/**
 * 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);
    }
  };
}
/**
 * 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)));
  }
};

/**
 * 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;
};

var __WEBPACK_AMD_DEFINE_RESULT__;// TinyColor v1.4.1
// https://github.com/bgrins/TinyColor
// Brian Grinstead, MIT License

(function(Math) {

var trimLeft = /^\s+/,
    trimRight = /\s+$/,
    tinyCounter = 0,
    mathRound = Math.round,
    mathMin = Math.min,
    mathMax = Math.max,
    mathRandom = Math.random;

function tinycolor (color, opts) {

    color = (color) ? color : '';
    opts = opts || { };

    // If input is already a tinycolor, return itself
    if (color instanceof tinycolor) {
       return color;
    }
    // If we are called as a function, call using new instead
    if (!(this instanceof tinycolor)) {
        return new tinycolor(color, opts);
    }

    var rgb = inputToRGB(color);
    this._originalInput = color,
    this._r = rgb.r,
    this._g = rgb.g,
    this._b = rgb.b,
    this._a = rgb.a,
    this._roundA = mathRound(100*this._a) / 100,
    this._format = opts.format || rgb.format;
    this._gradientType = opts.gradientType;

    // Don't let the range of [0,255] come back in [0,1].
    // Potentially lose a little bit of precision here, but will fix issues where
    // .5 gets interpreted as half of the total, instead of half of 1
    // If it was supposed to be 128, this was already taken care of by `inputToRgb`
    if (this._r < 1) { this._r = mathRound(this._r); }
    if (this._g < 1) { this._g = mathRound(this._g); }
    if (this._b < 1) { this._b = mathRound(this._b); }

    this._ok = rgb.ok;
    this._tc_id = tinyCounter++;
}

tinycolor.prototype = {
    isDark: function() {
        return this.getBrightness() < 128;
    },
    isLight: function() {
        return !this.isDark();
    },
    isValid: function() {
        return this._ok;
    },
    getOriginalInput: function() {
      return this._originalInput;
    },
    getFormat: function() {
        return this._format;
    },
    getAlpha: function() {
        return this._a;
    },
    getBrightness: function() {
        //http://www.w3.org/TR/AERT#color-contrast
        var rgb = this.toRgb();
        return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
    },
    getLuminance: function() {
        //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
        var rgb = this.toRgb();
        var RsRGB, GsRGB, BsRGB, R, G, B;
        RsRGB = rgb.r/255;
        GsRGB = rgb.g/255;
        BsRGB = rgb.b/255;

        if (RsRGB <= 0.03928) {R = RsRGB / 12.92;} else {R = Math.pow(((RsRGB + 0.055) / 1.055), 2.4);}
        if (GsRGB <= 0.03928) {G = GsRGB / 12.92;} else {G = Math.pow(((GsRGB + 0.055) / 1.055), 2.4);}
        if (BsRGB <= 0.03928) {B = BsRGB / 12.92;} else {B = Math.pow(((BsRGB + 0.055) / 1.055), 2.4);}
        return (0.2126 * R) + (0.7152 * G) + (0.0722 * B);
    },
    setAlpha: function(value) {
        this._a = boundAlpha(value);
        this._roundA = mathRound(100*this._a) / 100;
        return this;
    },
    toHsv: function() {
        var hsv = rgbToHsv(this._r, this._g, this._b);
        return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
    },
    toHsvString: function() {
        var hsv = rgbToHsv(this._r, this._g, this._b);
        var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
        return (this._a == 1) ?
          "hsv("  + h + ", " + s + "%, " + v + "%)" :
          "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
    },
    toHsl: function() {
        var hsl = rgbToHsl(this._r, this._g, this._b);
        return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
    },
    toHslString: function() {
        var hsl = rgbToHsl(this._r, this._g, this._b);
        var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
        return (this._a == 1) ?
          "hsl("  + h + ", " + s + "%, " + l + "%)" :
          "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
    },
    toHex: function(allow3Char) {
        return rgbToHex(this._r, this._g, this._b, allow3Char);
    },
    toHexString: function(allow3Char) {
        return '#' + this.toHex(allow3Char);
    },
    toHex8: function(allow4Char) {
        return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);
    },
    toHex8String: function(allow4Char) {
        return '#' + this.toHex8(allow4Char);
    },
    toRgb: function() {
        return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
    },
    toRgbString: function() {
        return (this._a == 1) ?
          "rgb("  + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
          "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
    },
    toPercentageRgb: function() {
        return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
    },
    toPercentageRgbString: function() {
        return (this._a == 1) ?
          "rgb("  + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
          "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
    },
    toName: function() {
        if (this._a === 0) {
            return "transparent";
        }

        if (this._a < 1) {
            return false;
        }

        return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
    },
    toFilter: function(secondColor) {
        var hex8String = '#' + rgbaToArgbHex(this._r, this._g, this._b, this._a);
        var secondHex8String = hex8String;
        var gradientType = this._gradientType ? "GradientType = 1, " : "";

        if (secondColor) {
            var s = tinycolor(secondColor);
            secondHex8String = '#' + rgbaToArgbHex(s._r, s._g, s._b, s._a);
        }

        return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
    },
    toString: function(format) {
        var formatSet = !!format;
        format = format || this._format;

        var formattedString = false;
        var hasAlpha = this._a < 1 && this._a >= 0;
        var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name");

        if (needsAlphaFormat) {
            // Special case for "transparent", all other non-alpha formats
            // will return rgba when there is transparency.
            if (format === "name" && this._a === 0) {
                return this.toName();
            }
            return this.toRgbString();
        }
        if (format === "rgb") {
            formattedString = this.toRgbString();
        }
        if (format === "prgb") {
            formattedString = this.toPercentageRgbString();
        }
        if (format === "hex" || format === "hex6") {
            formattedString = this.toHexString();
        }
        if (format === "hex3") {
            formattedString = this.toHexString(true);
        }
        if (format === "hex4") {
            formattedString = this.toHex8String(true);
        }
        if (format === "hex8") {
            formattedString = this.toHex8String();
        }
        if (format === "name") {
            formattedString = this.toName();
        }
        if (format === "hsl") {
            formattedString = this.toHslString();
        }
        if (format === "hsv") {
            formattedString = this.toHsvString();
        }

        return formattedString || this.toHexString();
    },
    clone: function() {
        return tinycolor(this.toString());
    },

    _applyModification: function(fn, args) {
        var color = fn.apply(null, [this].concat([].slice.call(args)));
        this._r = color._r;
        this._g = color._g;
        this._b = color._b;
        this.setAlpha(color._a);
        return this;
    },
    lighten: function() {
        return this._applyModification(lighten, arguments);
    },
    brighten: function() {
        return this._applyModification(brighten, arguments);
    },
    darken: function() {
        return this._applyModification(darken, arguments);
    },
    desaturate: function() {
        return this._applyModification(desaturate, arguments);
    },
    saturate: function() {
        return this._applyModification(saturate, arguments);
    },
    greyscale: function() {
        return this._applyModification(greyscale, arguments);
    },
    spin: function() {
        return this._applyModification(spin, arguments);
    },

    _applyCombination: function(fn, args) {
        return fn.apply(null, [this].concat([].slice.call(args)));
    },
    analogous: function() {
        return this._applyCombination(analogous, arguments);
    },
    complement: function() {
        return this._applyCombination(complement, arguments);
    },
    monochromatic: function() {
        return this._applyCombination(monochromatic, arguments);
    },
    splitcomplement: function() {
        return this._applyCombination(splitcomplement, arguments);
    },
    triad: function() {
        return this._applyCombination(triad, arguments);
    },
    tetrad: function() {
        return this._applyCombination(tetrad, arguments);
    }
};

// If input is an object, force 1 into "1.0" to handle ratios properly
// String input requires "1.0" as input, so 1 will be treated as 1
tinycolor.fromRatio = function(color, opts) {
    if (typeof color == "object") {
        var newColor = {};
        for (var i in color) {
            if (color.hasOwnProperty(i)) {
                if (i === "a") {
                    newColor[i] = color[i];
                }
                else {
                    newColor[i] = convertToPercentage(color[i]);
                }
            }
        }
        color = newColor;
    }

    return tinycolor(color, opts);
};

// Given a string or object, convert that input to RGB
// Possible string inputs:
//
//     "red"
//     "#f00" or "f00"
//     "#ff0000" or "ff0000"
//     "#ff000000" or "ff000000"
//     "rgb 255 0 0" or "rgb (255, 0, 0)"
//     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
//     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
//     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
//     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
//     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
//     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
//
function inputToRGB(color) {

    var rgb = { r: 0, g: 0, b: 0 };
    var a = 1;
    var s = null;
    var v = null;
    var l = null;
    var ok = false;
    var format = false;

    if (typeof color == "string") {
        color = stringInputToObject(color);
    }

    if (typeof color == "object") {
        if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
            rgb = rgbToRgb(color.r, color.g, color.b);
            ok = true;
            format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
        }
        else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
            s = convertToPercentage(color.s);
            v = convertToPercentage(color.v);
            rgb = hsvToRgb(color.h, s, v);
            ok = true;
            format = "hsv";
        }
        else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
            s = convertToPercentage(color.s);
            l = convertToPercentage(color.l);
            rgb = hslToRgb(color.h, s, l);
            ok = true;
            format = "hsl";
        }

        if (color.hasOwnProperty("a")) {
            a = color.a;
        }
    }

    a = boundAlpha(a);

    return {
        ok: ok,
        format: color.format || format,
        r: mathMin(255, mathMax(rgb.r, 0)),
        g: mathMin(255, mathMax(rgb.g, 0)),
        b: mathMin(255, mathMax(rgb.b, 0)),
        a: a
    };
}


// Conversion Functions
// --------------------

// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>

// `rgbToRgb`
// Handle bounds / percentage checking to conform to CSS color spec
// <http://www.w3.org/TR/css3-color/>
// *Assumes:* r, g, b in [0, 255] or [0, 1]
// *Returns:* { r, g, b } in [0, 255]
function rgbToRgb(r, g, b){
    return {
        r: bound01(r, 255) * 255,
        g: bound01(g, 255) * 255,
        b: bound01(b, 255) * 255
    };
}

// `rgbToHsl`
// Converts an RGB color value to HSL.
// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
// *Returns:* { h, s, l } in [0,1]
function rgbToHsl(r, g, b) {

    r = bound01(r, 255);
    g = bound01(g, 255);
    b = bound01(b, 255);

    var max = mathMax(r, g, b), min = mathMin(r, g, b);
    var h, s, l = (max + min) / 2;

    if(max == min) {
        h = s = 0; // achromatic
    }
    else {
        var d = max - min;
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
        switch(max) {
            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
            case g: h = (b - r) / d + 2; break;
            case b: h = (r - g) / d + 4; break;
        }

        h /= 6;
    }

    return { h: h, s: s, l: l };
}

// `hslToRgb`
// Converts an HSL color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function hslToRgb(h, s, l) {
    var r, g, b;

    h = bound01(h, 360);
    s = bound01(s, 100);
    l = bound01(l, 100);

    function hue2rgb(p, q, t) {
        if(t < 0) t += 1;
        if(t > 1) t -= 1;
        if(t < 1/6) return p + (q - p) * 6 * t;
        if(t < 1/2) return q;
        if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
        return p;
    }

    if(s === 0) {
        r = g = b = l; // achromatic
    }
    else {
        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
        var p = 2 * l - q;
        r = hue2rgb(p, q, h + 1/3);
        g = hue2rgb(p, q, h);
        b = hue2rgb(p, q, h - 1/3);
    }

    return { r: r * 255, g: g * 255, b: b * 255 };
}

// `rgbToHsv`
// Converts an RGB color value to HSV
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
// *Returns:* { h, s, v } in [0,1]
function rgbToHsv(r, g, b) {

    r = bound01(r, 255);
    g = bound01(g, 255);
    b = bound01(b, 255);

    var max = mathMax(r, g, b), min = mathMin(r, g, b);
    var h, s, v = max;

    var d = max - min;
    s = max === 0 ? 0 : d / max;

    if(max == min) {
        h = 0; // achromatic
    }
    else {
        switch(max) {
            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
            case g: h = (b - r) / d + 2; break;
            case b: h = (r - g) / d + 4; break;
        }
        h /= 6;
    }
    return { h: h, s: s, v: v };
}

// `hsvToRgb`
// Converts an HSV color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
 function hsvToRgb(h, s, v) {

    h = bound01(h, 360) * 6;
    s = bound01(s, 100);
    v = bound01(v, 100);

    var i = Math.floor(h),
        f = h - i,
        p = v * (1 - s),
        q = v * (1 - f * s),
        t = v * (1 - (1 - f) * s),
        mod = i % 6,
        r = [v, q, p, p, t, v][mod],
        g = [t, v, v, q, p, p][mod],
        b = [p, p, t, v, v, q][mod];

    return { r: r * 255, g: g * 255, b: b * 255 };
}

// `rgbToHex`
// Converts an RGB color to hex
// Assumes r, g, and b are contained in the set [0, 255]
// Returns a 3 or 6 character hex
function rgbToHex(r, g, b, allow3Char) {

    var hex = [
        pad2(mathRound(r).toString(16)),
        pad2(mathRound(g).toString(16)),
        pad2(mathRound(b).toString(16))
    ];

    // Return a 3 character hex if possible
    if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
        return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
    }

    return hex.join("");
}

// `rgbaToHex`
// Converts an RGBA color plus alpha transparency to hex
// Assumes r, g, b are contained in the set [0, 255] and
// a in [0, 1]. Returns a 4 or 8 character rgba hex
function rgbaToHex(r, g, b, a, allow4Char) {

    var hex = [
        pad2(mathRound(r).toString(16)),
        pad2(mathRound(g).toString(16)),
        pad2(mathRound(b).toString(16)),
        pad2(convertDecimalToHex(a))
    ];

    // Return a 4 character hex if possible
    if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) {
        return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
    }

    return hex.join("");
}

// `rgbaToArgbHex`
// Converts an RGBA color to an ARGB Hex8 string
// Rarely used, but required for "toFilter()"
function rgbaToArgbHex(r, g, b, a) {

    var hex = [
        pad2(convertDecimalToHex(a)),
        pad2(mathRound(r).toString(16)),
        pad2(mathRound(g).toString(16)),
        pad2(mathRound(b).toString(16))
    ];

    return hex.join("");
}

// `equals`
// Can be called with any tinycolor input
tinycolor.equals = function (color1, color2) {
    if (!color1 || !color2) { return false; }
    return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
};

tinycolor.random = function() {
    return tinycolor.fromRatio({
        r: mathRandom(),
        g: mathRandom(),
        b: mathRandom()
    });
};


// Modification Functions
// ----------------------
// Thanks to less.js for some of the basics here
// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>

function desaturate(color, amount) {
    amount = (amount === 0) ? 0 : (amount || 10);
    var hsl = tinycolor(color).toHsl();
    hsl.s -= amount / 100;
    hsl.s = clamp01(hsl.s);
    return tinycolor(hsl);
}

function saturate(color, amount) {
    amount = (amount === 0) ? 0 : (amount || 10);
    var hsl = tinycolor(color).toHsl();
    hsl.s += amount / 100;
    hsl.s = clamp01(hsl.s);
    return tinycolor(hsl);
}

function greyscale(color) {
    return tinycolor(color).desaturate(100);
}

function lighten (color, amount) {
    amount = (amount === 0) ? 0 : (amount || 10);
    var hsl = tinycolor(color).toHsl();
    hsl.l += amount / 100;
    hsl.l = clamp01(hsl.l);
    return tinycolor(hsl);
}

function brighten(color, amount) {
    amount = (amount === 0) ? 0 : (amount || 10);
    var rgb = tinycolor(color).toRgb();
    rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
    rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
    rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
    return tinycolor(rgb);
}

function darken (color, amount) {
    amount = (amount === 0) ? 0 : (amount || 10);
    var hsl = tinycolor(color).toHsl();
    hsl.l -= amount / 100;
    hsl.l = clamp01(hsl.l);
    return tinycolor(hsl);
}

// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
// Values outside of this range will be wrapped into this range.
function spin(color, amount) {
    var hsl = tinycolor(color).toHsl();
    var hue = (hsl.h + amount) % 360;
    hsl.h = hue < 0 ? 360 + hue : hue;
    return tinycolor(hsl);
}

// Combination Functions
// ---------------------
// Thanks to jQuery xColor for some of the ideas behind these
// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>

function complement(color) {
    var hsl = tinycolor(color).toHsl();
    hsl.h = (hsl.h + 180) % 360;
    return tinycolor(hsl);
}

function triad(color) {
    var hsl = tinycolor(color).toHsl();
    var h = hsl.h;
    return [
        tinycolor(color),
        tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
        tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
    ];
}

function tetrad(color) {
    var hsl = tinycolor(color).toHsl();
    var h = hsl.h;
    return [
        tinycolor(color),
        tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
        tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
        tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
    ];
}

function splitcomplement(color) {
    var hsl = tinycolor(color).toHsl();
    var h = hsl.h;
    return [
        tinycolor(color),
        tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
        tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
    ];
}

function analogous(color, results, slices) {
    results = results || 6;
    slices = slices || 30;

    var hsl = tinycolor(color).toHsl();
    var part = 360 / slices;
    var ret = [tinycolor(color)];

    for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
        hsl.h = (hsl.h + part) % 360;
        ret.push(tinycolor(hsl));
    }
    return ret;
}

function monochromatic(color, results) {
    results = results || 6;
    var hsv = tinycolor(color).toHsv();
    var h = hsv.h, s = hsv.s, v = hsv.v;
    var ret = [];
    var modification = 1 / results;

    while (results--) {
        ret.push(tinycolor({ h: h, s: s, v: v}));
        v = (v + modification) % 1;
    }

    return ret;
}

// Utility Functions
// ---------------------

tinycolor.mix = function(color1, color2, amount) {
    amount = (amount === 0) ? 0 : (amount || 50);

    var rgb1 = tinycolor(color1).toRgb();
    var rgb2 = tinycolor(color2).toRgb();

    var p = amount / 100;

    var rgba = {
        r: ((rgb2.r - rgb1.r) * p) + rgb1.r,
        g: ((rgb2.g - rgb1.g) * p) + rgb1.g,
        b: ((rgb2.b - rgb1.b) * p) + rgb1.b,
        a: ((rgb2.a - rgb1.a) * p) + rgb1.a
    };

    return tinycolor(rgba);
};


// Readability Functions
// ---------------------
// <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)

// `contrast`
// Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
tinycolor.readability = function(color1, color2) {
    var c1 = tinycolor(color1);
    var c2 = tinycolor(color2);
    return (Math.max(c1.getLuminance(),c2.getLuminance())+0.05) / (Math.min(c1.getLuminance(),c2.getLuminance())+0.05);
};

// `isReadable`
// Ensure that foreground and background color combinations meet WCAG2 guidelines.
// The third argument is an optional Object.
//      the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
//      the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
// If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.

// *Example*
//    tinycolor.isReadable("#000", "#111") => false
//    tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false
tinycolor.isReadable = function(color1, color2, wcag2) {
    var readability = tinycolor.readability(color1, color2);
    var wcag2Parms, out;

    out = false;

    wcag2Parms = validateWCAG2Parms(wcag2);
    switch (wcag2Parms.level + wcag2Parms.size) {
        case "AAsmall":
        case "AAAlarge":
            out = readability >= 4.5;
            break;
        case "AAlarge":
            out = readability >= 3;
            break;
        case "AAAsmall":
            out = readability >= 7;
            break;
    }
    return out;

};

// `mostReadable`
// Given a base color and a list of possible foreground or background
// colors for that base, returns the most readable color.
// Optionally returns Black or White if the most readable color is unreadable.
// *Example*
//    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255"
//    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString();  // "#ffffff"
//    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3"
//    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff"
tinycolor.mostReadable = function(baseColor, colorList, args) {
    var bestColor = null;
    var bestScore = 0;
    var readability;
    var includeFallbackColors, level, size ;
    args = args || {};
    includeFallbackColors = args.includeFallbackColors ;
    level = args.level;
    size = args.size;

    for (var i= 0; i < colorList.length ; i++) {
        readability = tinycolor.readability(baseColor, colorList[i]);
        if (readability > bestScore) {
            bestScore = readability;
            bestColor = tinycolor(colorList[i]);
        }
    }

    if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) {
        return bestColor;
    }
    else {
        args.includeFallbackColors=false;
        return tinycolor.mostReadable(baseColor,["#fff", "#000"],args);
    }
};


// Big List of Colors
// ------------------
// <http://www.w3.org/TR/css3-color/#svg-color>
var names = tinycolor.names = {
    aliceblue: "f0f8ff",
    antiquewhite: "faebd7",
    aqua: "0ff",
    aquamarine: "7fffd4",
    azure: "f0ffff",
    beige: "f5f5dc",
    bisque: "ffe4c4",
    black: "000",
    blanchedalmond: "ffebcd",
    blue: "00f",
    blueviolet: "8a2be2",
    brown: "a52a2a",
    burlywood: "deb887",
    burntsienna: "ea7e5d",
    cadetblue: "5f9ea0",
    chartreuse: "7fff00",
    chocolate: "d2691e",
    coral: "ff7f50",
    cornflowerblue: "6495ed",
    cornsilk: "fff8dc",
    crimson: "dc143c",
    cyan: "0ff",
    darkblue: "00008b",
    darkcyan: "008b8b",
    darkgoldenrod: "b8860b",
    darkgray: "a9a9a9",
    darkgreen: "006400",
    darkgrey: "a9a9a9",
    darkkhaki: "bdb76b",
    darkmagenta: "8b008b",
    darkolivegreen: "556b2f",
    darkorange: "ff8c00",
    darkorchid: "9932cc",
    darkred: "8b0000",
    darksalmon: "e9967a",
    darkseagreen: "8fbc8f",
    darkslateblue: "483d8b",
    darkslategray: "2f4f4f",
    darkslategrey: "2f4f4f",
    darkturquoise: "00ced1",
    darkviolet: "9400d3",
    deeppink: "ff1493",
    deepskyblue: "00bfff",
    dimgray: "696969",
    dimgrey: "696969",
    dodgerblue: "1e90ff",
    firebrick: "b22222",
    floralwhite: "fffaf0",
    forestgreen: "228b22",
    fuchsia: "f0f",
    gainsboro: "dcdcdc",
    ghostwhite: "f8f8ff",
    gold: "ffd700",
    goldenrod: "daa520",
    gray: "808080",
    green: "008000",
    greenyellow: "adff2f",
    grey: "808080",
    honeydew: "f0fff0",
    hotpink: "ff69b4",
    indianred: "cd5c5c",
    indigo: "4b0082",
    ivory: "fffff0",
    khaki: "f0e68c",
    lavender: "e6e6fa",
    lavenderblush: "fff0f5",
    lawngreen: "7cfc00",
    lemonchiffon: "fffacd",
    lightblue: "add8e6",
    lightcoral: "f08080",
    lightcyan: "e0ffff",
    lightgoldenrodyellow: "fafad2",
    lightgray: "d3d3d3",
    lightgreen: "90ee90",
    lightgrey: "d3d3d3",
    lightpink: "ffb6c1",
    lightsalmon: "ffa07a",
    lightseagreen: "20b2aa",
    lightskyblue: "87cefa",
    lightslategray: "789",
    lightslategrey: "789",
    lightsteelblue: "b0c4de",
    lightyellow: "ffffe0",
    lime: "0f0",
    limegreen: "32cd32",
    linen: "faf0e6",
    magenta: "f0f",
    maroon: "800000",
    mediumaquamarine: "66cdaa",
    mediumblue: "0000cd",
    mediumorchid: "ba55d3",
    mediumpurple: "9370db",
    mediumseagreen: "3cb371",
    mediumslateblue: "7b68ee",
    mediumspringgreen: "00fa9a",
    mediumturquoise: "48d1cc",
    mediumvioletred: "c71585",
    midnightblue: "191970",
    mintcream: "f5fffa",
    mistyrose: "ffe4e1",
    moccasin: "ffe4b5",
    navajowhite: "ffdead",
    navy: "000080",
    oldlace: "fdf5e6",
    olive: "808000",
    olivedrab: "6b8e23",
    orange: "ffa500",
    orangered: "ff4500",
    orchid: "da70d6",
    palegoldenrod: "eee8aa",
    palegreen: "98fb98",
    paleturquoise: "afeeee",
    palevioletred: "db7093",
    papayawhip: "ffefd5",
    peachpuff: "ffdab9",
    peru: "cd853f",
    pink: "ffc0cb",
    plum: "dda0dd",
    powderblue: "b0e0e6",
    purple: "800080",
    rebeccapurple: "663399",
    red: "f00",
    rosybrown: "bc8f8f",
    royalblue: "4169e1",
    saddlebrown: "8b4513",
    salmon: "fa8072",
    sandybrown: "f4a460",
    seagreen: "2e8b57",
    seashell: "fff5ee",
    sienna: "a0522d",
    silver: "c0c0c0",
    skyblue: "87ceeb",
    slateblue: "6a5acd",
    slategray: "708090",
    slategrey: "708090",
    snow: "fffafa",
    springgreen: "00ff7f",
    steelblue: "4682b4",
    tan: "d2b48c",
    teal: "008080",
    thistle: "d8bfd8",
    tomato: "ff6347",
    turquoise: "40e0d0",
    violet: "ee82ee",
    wheat: "f5deb3",
    white: "fff",
    whitesmoke: "f5f5f5",
    yellow: "ff0",
    yellowgreen: "9acd32"
};

// Make it easy to access colors via `hexNames[hex]`
var hexNames = tinycolor.hexNames = flip(names);


// Utilities
// ---------

// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
function flip(o) {
    var flipped = { };
    for (var i in o) {
        if (o.hasOwnProperty(i)) {
            flipped[o[i]] = i;
        }
    }
    return flipped;
}

// Return a valid alpha value [0,1] with all invalid values being set to 1
function boundAlpha(a) {
    a = parseFloat(a);

    if (isNaN(a) || a < 0 || a > 1) {
        a = 1;
    }

    return a;
}

// Take input from [0, n] and return it as [0, 1]
function bound01(n, max) {
    if (isOnePointZero(n)) { n = "100%"; }

    var processPercent = isPercentage(n);
    n = mathMin(max, mathMax(0, parseFloat(n)));

    // Automatically convert percentage into number
    if (processPercent) {
        n = parseInt(n * max, 10) / 100;
    }

    // Handle floating point rounding errors
    if ((Math.abs(n - max) < 0.000001)) {
        return 1;
    }

    // Convert into [0, 1] range if it isn't already
    return (n % max) / parseFloat(max);
}

// Force a number between 0 and 1
function clamp01(val) {
    return mathMin(1, mathMax(0, val));
}

// Parse a base-16 hex value into a base-10 integer
function parseIntFromHex(val) {
    return parseInt(val, 16);
}

// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
function isOnePointZero(n) {
    return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
}

// Check to see if string passed in is a percentage
function isPercentage(n) {
    return typeof n === "string" && n.indexOf('%') != -1;
}

// Force a hex value to have 2 characters
function pad2(c) {
    return c.length == 1 ? '0' + c : '' + c;
}

// Replace a decimal with it's percentage value
function convertToPercentage(n) {
    if (n <= 1) {
        n = (n * 100) + "%";
    }

    return n;
}

// Converts a decimal to a hex value
function convertDecimalToHex(d) {
    return Math.round(parseFloat(d) * 255).toString(16);
}
// Converts a hex value to a decimal
function convertHexToDecimal(h) {
    return (parseIntFromHex(h) / 255);
}

var matchers = (function() {

    // <http://www.w3.org/TR/css3-values/#integers>
    var CSS_INTEGER = "[-\\+]?\\d+%?";

    // <http://www.w3.org/TR/css3-values/#number-value>
    var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";

    // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
    var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";

    // Actual matching.
    // Parentheses and commas are optional, but not required.
    // Whitespace can take the place of commas or opening paren
    var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
    var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";

    return {
        CSS_UNIT: new RegExp(CSS_UNIT),
        rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
        rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
        hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
        hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
        hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
        hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
        hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
        hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
        hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
        hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
    };
})();

// `isValidCSSUnit`
// Take in a single string / number and check to see if it looks like a CSS unit
// (see `matchers` above for definition).
function isValidCSSUnit(color) {
    return !!matchers.CSS_UNIT.exec(color);
}

// `stringInputToObject`
// Permissive string parsing.  Take in a number of formats, and output an object
// based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
function stringInputToObject(color) {

    color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
    var named = false;
    if (names[color]) {
        color = names[color];
        named = true;
    }
    else if (color == 'transparent') {
        return { r: 0, g: 0, b: 0, a: 0, format: "name" };
    }

    // Try to match string input using regular expressions.
    // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
    // Just return an object and let the conversion functions handle that.
    // This way the result will be the same whether the tinycolor is initialized with string or object.
    var match;
    if ((match = matchers.rgb.exec(color))) {
        return { r: match[1], g: match[2], b: match[3] };
    }
    if ((match = matchers.rgba.exec(color))) {
        return { r: match[1], g: match[2], b: match[3], a: match[4] };
    }
    if ((match = matchers.hsl.exec(color))) {
        return { h: match[1], s: match[2], l: match[3] };
    }
    if ((match = matchers.hsla.exec(color))) {
        return { h: match[1], s: match[2], l: match[3], a: match[4] };
    }
    if ((match = matchers.hsv.exec(color))) {
        return { h: match[1], s: match[2], v: match[3] };
    }
    if ((match = matchers.hsva.exec(color))) {
        return { h: match[1], s: match[2], v: match[3], a: match[4] };
    }
    if ((match = matchers.hex8.exec(color))) {
        return {
            r: parseIntFromHex(match[1]),
            g: parseIntFromHex(match[2]),
            b: parseIntFromHex(match[3]),
            a: convertHexToDecimal(match[4]),
            format: named ? "name" : "hex8"
        };
    }
    if ((match = matchers.hex6.exec(color))) {
        return {
            r: parseIntFromHex(match[1]),
            g: parseIntFromHex(match[2]),
            b: parseIntFromHex(match[3]),
            format: named ? "name" : "hex"
        };
    }
    if ((match = matchers.hex4.exec(color))) {
        return {
            r: parseIntFromHex(match[1] + '' + match[1]),
            g: parseIntFromHex(match[2] + '' + match[2]),
            b: parseIntFromHex(match[3] + '' + match[3]),
            a: convertHexToDecimal(match[4] + '' + match[4]),
            format: named ? "name" : "hex8"
        };
    }
    if ((match = matchers.hex3.exec(color))) {
        return {
            r: parseIntFromHex(match[1] + '' + match[1]),
            g: parseIntFromHex(match[2] + '' + match[2]),
            b: parseIntFromHex(match[3] + '' + match[3]),
            format: named ? "name" : "hex"
        };
    }

    return false;
}

function validateWCAG2Parms(parms) {
    // return valid WCAG2 parms for isReadable.
    // If input parms are invalid, return {"level":"AA", "size":"small"}
    var level, size;
    parms = parms || {"level":"AA", "size":"small"};
    level = (parms.level || "AA").toUpperCase();
    size = (parms.size || "small").toLowerCase();
    if (level !== "AA" && level !== "AAA") {
        level = "AA";
    }
    if (size !== "small" && size !== "large") {
        size = "small";
    }
    return {"level":level, "size":size};
}

// Node: Export function
if ( true && module.exports) {
    module.exports = tinycolor;
}
// AMD/requirejs: Define the module
else if (true) {
    !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () {return tinycolor;}).call(exports, __webpack_require__, exports, module),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
}
// Browser: Expose to window
else {}

})(Math);
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
 * Autolinker.js
 * 1.8.3
 *
 * Copyright(c) 2018 Gregory Jacobs <greg@greg-jacobs.com>
 * MIT License
 *
 * https://github.com/gregjacobs/Autolinker.js
 */
;(function(root, factory) {
  if (true) {
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  } else {}
}(this, function() {
/**
 * @class Autolinker
 * @extends Object
 *
 * Utility class used to process a given string of text, and wrap the matches in
 * the appropriate anchor (&lt;a&gt;) tags to turn them into links.
 *
 * Any of the configuration options may be provided in an Object (map) provided
 * to the Autolinker constructor, which will configure how the {@link #link link()}
 * method will process the links.
 *
 * For example:
 *
 *     var autolinker = new Autolinker( {
 *         newWindow : false,
 *         truncate  : 30
 *     } );
 *
 *     var html = autolinker.link( "Joe went to www.yahoo.com" );
 *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>'
 *
 *
 * The {@link #static-link static link()} method may also be used to inline
 * options into a single call, which may be more convenient for one-off uses.
 * For example:
 *
 *     var html = Autolinker.link( "Joe went to www.yahoo.com", {
 *         newWindow : false,
 *         truncate  : 30
 *     } );
 *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>'
 *
 *
 * ## Custom Replacements of Links
 *
 * If the configuration options do not provide enough flexibility, a {@link #replaceFn}
 * may be provided to fully customize the output of Autolinker. This function is
 * called once for each URL/Email/Phone#/Hashtag/Mention (Twitter, Instagram, Soundcloud)
 * match that is encountered.
 *
 * For example:
 *
 *     var input = "...";  // string with URLs, Email Addresses, Phone #s, Hashtags, and Mentions (Twitter, Instagram, Soundcloud)
 *
 *     var linkedText = Autolinker.link( input, {
 *         replaceFn : function( match ) {
 *             console.log( "href = ", match.getAnchorHref() );
 *             console.log( "text = ", match.getAnchorText() );
 *
 *             switch( match.getType() ) {
 *                 case 'url' :
 *                     console.log( "url: ", match.getUrl() );
 *
 *                     if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) {
 *                         var tag = match.buildTag();  // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes
 *                         tag.setAttr( 'rel', 'nofollow' );
 *                         tag.addClass( 'external-link' );
 *
 *                         return tag;
 *
 *                     } else {
 *                         return true;  // let Autolinker perform its normal anchor tag replacement
 *                     }
 *
 *                 case 'email' :
 *                     var email = match.getEmail();
 *                     console.log( "email: ", email );
 *
 *                     if( email === "my@own.address" ) {
 *                         return false;  // don't auto-link this particular email address; leave as-is
 *                     } else {
 *                         return;  // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`)
 *                     }
 *
 *                 case 'phone' :
 *                     var phoneNumber = match.getPhoneNumber();
 *                     console.log( phoneNumber );
 *
 *                     return '<a href="http://newplace.to.link.phone.numbers.to/">' + phoneNumber + '</a>';
 *
 *                 case 'hashtag' :
 *                     var hashtag = match.getHashtag();
 *                     console.log( hashtag );
 *
 *                     return '<a href="http://newplace.to.link.hashtag.handles.to/">' + hashtag + '</a>';
 *
 *                 case 'mention' :
 *                     var mention = match.getMention();
 *                     console.log( mention );
 *
 *                     return '<a href="http://newplace.to.link.mention.to/">' + mention + '</a>';
 *             }
 *         }
 *     } );
 *
 *
 * The function may return the following values:
 *
 * - `true` (Boolean): Allow Autolinker to replace the match as it normally
 *   would.
 * - `false` (Boolean): Do not replace the current match at all - leave as-is.
 * - Any String: If a string is returned from the function, the string will be
 *   used directly as the replacement HTML for the match.
 * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify
 *   an HTML tag before writing out its HTML text.
 *
 * @constructor
 * @param {Object} [cfg] The configuration options for the Autolinker instance,
 *   specified in an Object (map).
 */
var Autolinker = function( cfg ) {
	cfg = cfg || {};

	this.version = Autolinker.version;

	this.urls = this.normalizeUrlsCfg( cfg.urls );
	this.email = typeof cfg.email === 'boolean' ? cfg.email : true;
	this.phone = typeof cfg.phone === 'boolean' ? cfg.phone : true;
	this.hashtag = cfg.hashtag || false;
	this.mention = cfg.mention || false;
	this.newWindow = typeof cfg.newWindow === 'boolean' ? cfg.newWindow : true;
	this.stripPrefix = this.normalizeStripPrefixCfg( cfg.stripPrefix );
	this.stripTrailingSlash = typeof cfg.stripTrailingSlash === 'boolean' ? cfg.stripTrailingSlash : true;
	this.decodePercentEncoding = typeof cfg.decodePercentEncoding === 'boolean' ? cfg.decodePercentEncoding : true;

	// Validate the value of the `mention` cfg
	var mention = this.mention;
	if( mention !== false && mention !== 'twitter' && mention !== 'instagram'  && mention !== 'soundcloud' ) {
		throw new Error( "invalid `mention` cfg - see docs" );
	}

	// Validate the value of the `hashtag` cfg
	var hashtag = this.hashtag;
	if( hashtag !== false && hashtag !== 'twitter' && hashtag !== 'facebook' && hashtag !== 'instagram' ) {
		throw new Error( "invalid `hashtag` cfg - see docs" );
	}

	this.truncate = this.normalizeTruncateCfg( cfg.truncate );
	this.className = cfg.className || '';
	this.replaceFn = cfg.replaceFn || null;
	this.context = cfg.context || this;

	this.htmlParser = null;
	this.matchers = null;
	this.tagBuilder = null;
};



/**
 * Automatically links URLs, Email addresses, Phone Numbers, Twitter handles,
 * Hashtags, and Mentions found in the given chunk of HTML. Does not link URLs
 * found within HTML tags.
 *
 * For instance, if given the text: `You should go to http://www.yahoo.com`,
 * then the result will be `You should go to &lt;a href="http://www.yahoo.com"&gt;http://www.yahoo.com&lt;/a&gt;`
 *
 * Example:
 *
 *     var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } );
 *     // Produces: "Go to <a href="http://google.com">google.com</a>"
 *
 * @static
 * @param {String} textOrHtml The HTML or text to find matches within (depending
 *   on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #mention},
 *   {@link #hashtag}, and {@link #mention} options are enabled).
 * @param {Object} [options] Any of the configuration options for the Autolinker
 *   class, specified in an Object (map). See the class description for an
 *   example call.
 * @return {String} The HTML text, with matches automatically linked.
 */
Autolinker.link = function( textOrHtml, options ) {
	var autolinker = new Autolinker( options );
	return autolinker.link( textOrHtml );
};



/**
 * Parses the input `textOrHtml` looking for URLs, email addresses, phone
 * numbers, username handles, and hashtags (depending on the configuration
 * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match}
 * objects describing those matches (without making any replacements).
 *
 * Note that if parsing multiple pieces of text, it is slightly more efficient
 * to create an Autolinker instance, and use the instance-level {@link #parse}
 * method.
 *
 * Example:
 *
 *     var matches = Autolinker.parse( "Hello google.com, I am asdf@asdf.com", {
 *         urls: true,
 *         email: true
 *     } );
 *
 *     console.log( matches.length );           // 2
 *     console.log( matches[ 0 ].getType() );   // 'url'
 *     console.log( matches[ 0 ].getUrl() );    // 'google.com'
 *     console.log( matches[ 1 ].getType() );   // 'email'
 *     console.log( matches[ 1 ].getEmail() );  // 'asdf@asdf.com'
 *
 * @static
 * @param {String} textOrHtml The HTML or text to find matches within
 *   (depending on if the {@link #urls}, {@link #email}, {@link #phone},
 *   {@link #hashtag}, and {@link #mention} options are enabled).
 * @param {Object} [options] Any of the configuration options for the Autolinker
 *   class, specified in an Object (map). See the class description for an
 *   example call.
 * @return {Autolinker.match.Match[]} The array of Matches found in the
 *   given input `textOrHtml`.
 */
Autolinker.parse = function( textOrHtml, options ) {
	var autolinker = new Autolinker( options );
	return autolinker.parse( textOrHtml );
};


/**
 * @static
 * @property {String} version (readonly)
 *
 * The Autolinker version number in the form major.minor.patch
 *
 * Ex: 0.25.1
 */
Autolinker.version = '1.8.3';


Autolinker.prototype = {
	constructor : Autolinker,  // fix constructor property

	/**
	 * @cfg {Boolean/Object} [urls]
	 *
	 * `true` if URLs should be automatically linked, `false` if they should not
	 * be. Defaults to `true`.
	 *
	 * Examples:
	 *
	 *     urls: true
	 *
	 *     // or
	 *
	 *     urls: {
	 *         schemeMatches : true,
	 *         wwwMatches    : true,
	 *         tldMatches    : true
	 *     }
	 *
	 * As shown above, this option also accepts an Object form with 3 properties
	 * to allow for more customization of what exactly gets linked. All default
	 * to `true`:
	 *
	 * @cfg {Boolean} [urls.schemeMatches] `true` to match URLs found prefixed
	 *   with a scheme, i.e. `http://google.com`, or `other+scheme://google.com`,
	 *   `false` to prevent these types of matches.
	 * @cfg {Boolean} [urls.wwwMatches] `true` to match urls found prefixed with
	 *   `'www.'`, i.e. `www.google.com`. `false` to prevent these types of
	 *   matches. Note that if the URL had a prefixed scheme, and
	 *   `schemeMatches` is true, it will still be linked.
	 * @cfg {Boolean} [urls.tldMatches] `true` to match URLs with known top
	 *   level domains (.com, .net, etc.) that are not prefixed with a scheme or
	 *   `'www.'`. This option attempts to match anything that looks like a URL
	 *   in the given text. Ex: `google.com`, `asdf.org/?page=1`, etc. `false`
	 *   to prevent these types of matches.
	 */

	/**
	 * @cfg {Boolean} [email=true]
	 *
	 * `true` if email addresses should be automatically linked, `false` if they
	 * should not be.
	 */

	/**
	 * @cfg {Boolean} [phone=true]
	 *
	 * `true` if Phone numbers ("(555)555-5555") should be automatically linked,
	 * `false` if they should not be.
	 */

	/**
	 * @cfg {Boolean/String} [hashtag=false]
	 *
	 * A string for the service name to have hashtags (ex: "#myHashtag")
	 * auto-linked to. The currently-supported values are:
	 *
	 * - 'twitter'
	 * - 'facebook'
	 * - 'instagram'
	 *
	 * Pass `false` to skip auto-linking of hashtags.
	 */

	/**
	 * @cfg {String/Boolean} [mention=false]
	 *
	 * A string for the service name to have mentions (ex: "@myuser")
	 * auto-linked to. The currently supported values are:
	 *
	 * - 'twitter'
	 * - 'instagram'
	 * - 'soundcloud'
	 *
	 * Defaults to `false` to skip auto-linking of mentions.
	 */

	/**
	 * @cfg {Boolean} [newWindow=true]
	 *
	 * `true` if the links should open in a new window, `false` otherwise.
	 */

	/**
	 * @cfg {Boolean/Object} [stripPrefix]
	 *
	 * `true` if 'http://' (or 'https://') and/or the 'www.' should be stripped
	 * from the beginning of URL links' text, `false` otherwise. Defaults to
	 * `true`.
	 *
	 * Examples:
	 *
	 *     stripPrefix: true
	 *
	 *     // or
	 *
	 *     stripPrefix: {
	 *         scheme : true,
	 *         www    : true
	 *     }
	 *
	 * As shown above, this option also accepts an Object form with 2 properties
	 * to allow for more customization of what exactly is prevented from being
	 * displayed. Both default to `true`:
	 *
	 * @cfg {Boolean} [stripPrefix.scheme] `true` to prevent the scheme part of
	 *   a URL match from being displayed to the user. Example:
	 *   `'http://google.com'` will be displayed as `'google.com'`. `false` to
	 *   not strip the scheme. NOTE: Only an `'http://'` or `'https://'` scheme
	 *   will be removed, so as not to remove a potentially dangerous scheme
	 *   (such as `'file://'` or `'javascript:'`)
	 * @cfg {Boolean} [stripPrefix.www] www (Boolean): `true` to prevent the
	 *   `'www.'` part of a URL match from being displayed to the user. Ex:
	 *   `'www.google.com'` will be displayed as `'google.com'`. `false` to not
	 *   strip the `'www'`.
	 */

	/**
	 * @cfg {Boolean} [stripTrailingSlash=true]
	 *
	 * `true` to remove the trailing slash from URL matches, `false` to keep
	 *  the trailing slash.
	 *
	 *  Example when `true`: `http://google.com/` will be displayed as
	 *  `http://google.com`.
	 */

	/**
	 * @cfg {Boolean} [decodePercentEncoding=true]
	 *
	 * `true` to decode percent-encoded characters in URL matches, `false` to keep
	 *  the percent-encoded characters.
	 *
	 *  Example when `true`: `https://en.wikipedia.org/wiki/San_Jos%C3%A9` will
	 *  be displayed as `https://en.wikipedia.org/wiki/San_José`.
	 */

	/**
	 * @cfg {Number/Object} [truncate=0]
	 *
	 * ## Number Form
	 *
	 * A number for how many characters matched text should be truncated to
	 * inside the text of a link. If the matched text is over this number of
	 * characters, it will be truncated to this length by adding a two period
	 * ellipsis ('..') to the end of the string.
	 *
	 * For example: A url like 'http://www.yahoo.com/some/long/path/to/a/file'
	 * truncated to 25 characters might look something like this:
	 * 'yahoo.com/some/long/pat..'
	 *
	 * Example Usage:
	 *
	 *     truncate: 25
	 *
	 *
	 *  Defaults to `0` for "no truncation."
	 *
	 *
	 * ## Object Form
	 *
	 * An Object may also be provided with two properties: `length` (Number) and
	 * `location` (String). `location` may be one of the following: 'end'
	 * (default), 'middle', or 'smart'.
	 *
	 * Example Usage:
	 *
	 *     truncate: { length: 25, location: 'middle' }
	 *
	 * @cfg {Number} [truncate.length=0] How many characters to allow before
	 *   truncation will occur. Defaults to `0` for "no truncation."
	 * @cfg {"end"/"middle"/"smart"} [truncate.location="end"]
	 *
	 * - 'end' (default): will truncate up to the number of characters, and then
	 *   add an ellipsis at the end. Ex: 'yahoo.com/some/long/pat..'
	 * - 'middle': will truncate and add the ellipsis in the middle. Ex:
	 *   'yahoo.com/s..th/to/a/file'
	 * - 'smart': for URLs where the algorithm attempts to strip out unnecessary
	 *   parts first (such as the 'www.', then URL scheme, hash, etc.),
	 *   attempting to make the URL human-readable before looking for a good
	 *   point to insert the ellipsis if it is still too long. Ex:
	 *   'yahoo.com/some..to/a/file'. For more details, see
	 *   {@link Autolinker.truncate.TruncateSmart}.
	 */

	/**
	 * @cfg {String} className
	 *
	 * A CSS class name to add to the generated links. This class will be added
	 * to all links, as well as this class plus match suffixes for styling
	 * url/email/phone/hashtag/mention links differently.
	 *
	 * For example, if this config is provided as "myLink", then:
	 *
	 * - URL links will have the CSS classes: "myLink myLink-url"
	 * - Email links will have the CSS classes: "myLink myLink-email", and
	 * - Phone links will have the CSS classes: "myLink myLink-phone"
	 * - Hashtag links will have the CSS classes: "myLink myLink-hashtag"
	 * - Mention links will have the CSS classes: "myLink myLink-mention myLink-[type]"
	 *   where [type] is either "instagram", "twitter" or "soundcloud"
	 */

	/**
	 * @cfg {Function} replaceFn
	 *
	 * A function to individually process each match found in the input string.
	 *
	 * See the class's description for usage.
	 *
	 * The `replaceFn` can be called with a different context object (`this`
	 * reference) using the {@link #context} cfg.
	 *
	 * This function is called with the following parameter:
	 *
	 * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which
	 *   can be used to retrieve information about the match that the `replaceFn`
	 *   is currently processing. See {@link Autolinker.match.Match} subclasses
	 *   for details.
	 */

	/**
	 * @cfg {Object} context
	 *
	 * The context object (`this` reference) to call the `replaceFn` with.
	 *
	 * Defaults to this Autolinker instance.
	 */


	/**
	 * @property {String} version (readonly)
	 *
	 * The Autolinker version number in the form major.minor.patch
	 *
	 * Ex: 0.25.1
	 */

	/**
	 * @private
	 * @property {Autolinker.htmlParser.HtmlParser} htmlParser
	 *
	 * The HtmlParser instance used to skip over HTML tags, while finding text
	 * nodes to process. This is lazily instantiated in the {@link #getHtmlParser}
	 * method.
	 */

	/**
	 * @private
	 * @property {Autolinker.matcher.Matcher[]} matchers
	 *
	 * The {@link Autolinker.matcher.Matcher} instances for this Autolinker
	 * instance.
	 *
	 * This is lazily created in {@link #getMatchers}.
	 */

	/**
	 * @private
	 * @property {Autolinker.AnchorTagBuilder} tagBuilder
	 *
	 * The AnchorTagBuilder instance used to build match replacement anchor tags.
	 * Note: this is lazily instantiated in the {@link #getTagBuilder} method.
	 */


	/**
	 * Normalizes the {@link #urls} config into an Object with 3 properties:
	 * `schemeMatches`, `wwwMatches`, and `tldMatches`, all Booleans.
	 *
	 * See {@link #urls} config for details.
	 *
	 * @private
	 * @param {Boolean/Object} urls
	 * @return {Object}
	 */
	normalizeUrlsCfg : function( urls ) {
		if( urls == null ) urls = true;  // default to `true`

		if( typeof urls === 'boolean' ) {
			return { schemeMatches: urls, wwwMatches: urls, tldMatches: urls };

		} else {  // object form
			return {
				schemeMatches : typeof urls.schemeMatches === 'boolean' ? urls.schemeMatches : true,
				wwwMatches    : typeof urls.wwwMatches === 'boolean'    ? urls.wwwMatches    : true,
				tldMatches    : typeof urls.tldMatches === 'boolean'    ? urls.tldMatches    : true
			};
		}
	},


	/**
	 * Normalizes the {@link #stripPrefix} config into an Object with 2
	 * properties: `scheme`, and `www` - both Booleans.
	 *
	 * See {@link #stripPrefix} config for details.
	 *
	 * @private
	 * @param {Boolean/Object} stripPrefix
	 * @return {Object}
	 */
	normalizeStripPrefixCfg : function( stripPrefix ) {
		if( stripPrefix == null ) stripPrefix = true;  // default to `true`

		if( typeof stripPrefix === 'boolean' ) {
			return { scheme: stripPrefix, www: stripPrefix };

		} else {  // object form
			return {
				scheme : typeof stripPrefix.scheme === 'boolean' ? stripPrefix.scheme : true,
				www    : typeof stripPrefix.www === 'boolean'    ? stripPrefix.www    : true
			};
		}
	},


	/**
	 * Normalizes the {@link #truncate} config into an Object with 2 properties:
	 * `length` (Number), and `location` (String).
	 *
	 * See {@link #truncate} config for details.
	 *
	 * @private
	 * @param {Number/Object} truncate
	 * @return {Object}
	 */
	normalizeTruncateCfg : function( truncate ) {
		if( typeof truncate === 'number' ) {
			return { length: truncate, location: 'end' };

		} else {  // object, or undefined/null
			return Autolinker.Util.defaults( truncate || {}, {
				length   : Number.POSITIVE_INFINITY,
				location : 'end'
			} );
		}
	},


	/**
	 * Parses the input `textOrHtml` looking for URLs, email addresses, phone
	 * numbers, username handles, and hashtags (depending on the configuration
	 * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match}
	 * objects describing those matches (without making any replacements).
	 *
	 * This method is used by the {@link #link} method, but can also be used to
	 * simply do parsing of the input in order to discover what kinds of links
	 * there are and how many.
	 *
	 * Example usage:
	 *
	 *     var autolinker = new Autolinker( {
	 *         urls: true,
	 *         email: true
	 *     } );
	 *
	 *     var matches = autolinker.parse( "Hello google.com, I am asdf@asdf.com" );
	 *
	 *     console.log( matches.length );           // 2
	 *     console.log( matches[ 0 ].getType() );   // 'url'
	 *     console.log( matches[ 0 ].getUrl() );    // 'google.com'
	 *     console.log( matches[ 1 ].getType() );   // 'email'
	 *     console.log( matches[ 1 ].getEmail() );  // 'asdf@asdf.com'
	 *
	 * @param {String} textOrHtml The HTML or text to find matches within
	 *   (depending on if the {@link #urls}, {@link #email}, {@link #phone},
	 *   {@link #hashtag}, and {@link #mention} options are enabled).
	 * @return {Autolinker.match.Match[]} The array of Matches found in the
	 *   given input `textOrHtml`.
	 */
	parse : function( textOrHtml ) {
		var htmlParser = this.getHtmlParser(),
		    htmlNodes = htmlParser.parse( textOrHtml ),
		    anchorTagStackCount = 0,  // used to only process text around anchor tags, and any inner text/html they may have;
		    matches = [];

		// Find all matches within the `textOrHtml` (but not matches that are
		// already nested within <a>, <style> and <script> tags)
		for( var i = 0, len = htmlNodes.length; i < len; i++ ) {
			var node = htmlNodes[ i ],
			    nodeType = node.getType();

			if( nodeType === 'element' && ['a', 'style', 'script'].indexOf(node.getTagName()) !== -1 ) {  // Process HTML anchor, style and script element nodes in the input `textOrHtml` to find out when we're within an <a>, <style> or <script> tag
				if( !node.isClosing() ) {  // it's the start <a>, <style> or <script> tag
					anchorTagStackCount++;
				} else {  // it's the end </a>, </style> or </script> tag
					anchorTagStackCount = Math.max( anchorTagStackCount - 1, 0 );  // attempt to handle extraneous </a> tags by making sure the stack count never goes below 0
				}

			} else if( nodeType === 'text' && anchorTagStackCount === 0 ) {  // Process text nodes that are not within an <a>, <style> and <script> tag
				var textNodeMatches = this.parseText( node.getText(), node.getOffset() );

				matches.push.apply( matches, textNodeMatches );
			}
		}


		// After we have found all matches, remove subsequent matches that
		// overlap with a previous match. This can happen for instance with URLs,
		// where the url 'google.com/#link' would match '#link' as a hashtag.
		matches = this.compactMatches( matches );

		// And finally, remove matches for match types that have been turned
		// off. We needed to have all match types turned on initially so that
		// things like hashtags could be filtered out if they were really just
		// part of a URL match (for instance, as a named anchor).
		matches = this.removeUnwantedMatches( matches );

		return matches;
	},


	/**
	 * After we have found all matches, we need to remove subsequent matches
	 * that overlap with a previous match. This can happen for instance with
	 * URLs, where the url 'google.com/#link' would match '#link' as a hashtag.
	 *
	 * @private
	 * @param {Autolinker.match.Match[]} matches
	 * @return {Autolinker.match.Match[]}
	 */
	compactMatches : function( matches ) {
		// First, the matches need to be sorted in order of offset
		matches.sort( function( a, b ) { return a.getOffset() - b.getOffset(); } );

		for( var i = 0; i < matches.length - 1; i++ ) {
			var match = matches[ i ],
					offset = match.getOffset(),
					matchedTextLength = match.getMatchedText().length,
			    endIdx = offset + matchedTextLength;

			if( i + 1 < matches.length ) {
				// Remove subsequent matches that equal offset with current match
				if( matches[ i + 1 ].getOffset() === offset ) {
					var removeIdx = matches[ i + 1 ].getMatchedText().length > matchedTextLength ? i : i + 1;
					matches.splice( removeIdx, 1 );
					continue;
				}

				// Remove subsequent matches that overlap with the current match
				if( matches[ i + 1 ].getOffset() < endIdx ) {
					matches.splice( i + 1, 1 );
				}
			}
		}

		return matches;
	},


	/**
	 * Removes matches for matchers that were turned off in the options. For
	 * example, if {@link #hashtag hashtags} were not to be matched, we'll
	 * remove them from the `matches` array here.
	 *
	 * @private
	 * @param {Autolinker.match.Match[]} matches The array of matches to remove
	 *   the unwanted matches from. Note: this array is mutated for the
	 *   removals.
	 * @return {Autolinker.match.Match[]} The mutated input `matches` array.
	 */
	removeUnwantedMatches : function( matches ) {
		var remove = Autolinker.Util.remove;

		if( !this.hashtag ) remove( matches, function( match ) { return match.getType() === 'hashtag'; } );
		if( !this.email )   remove( matches, function( match ) { return match.getType() === 'email'; } );
		if( !this.phone )   remove( matches, function( match ) { return match.getType() === 'phone'; } );
		if( !this.mention ) remove( matches, function( match ) { return match.getType() === 'mention'; } );
		if( !this.urls.schemeMatches ) {
			remove( matches, function( m ) { return m.getType() === 'url' && m.getUrlMatchType() === 'scheme'; } );
		}
		if( !this.urls.wwwMatches ) {
			remove( matches, function( m ) { return m.getType() === 'url' && m.getUrlMatchType() === 'www'; } );
		}
		if( !this.urls.tldMatches ) {
			remove( matches, function( m ) { return m.getType() === 'url' && m.getUrlMatchType() === 'tld'; } );
		}

		return matches;
	},


	/**
	 * Parses the input `text` looking for URLs, email addresses, phone
	 * numbers, username handles, and hashtags (depending on the configuration
	 * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match}
	 * objects describing those matches.
	 *
	 * This method processes a **non-HTML string**, and is used to parse and
	 * match within the text nodes of an HTML string. This method is used
	 * internally by {@link #parse}.
	 *
	 * @private
	 * @param {String} text The text to find matches within (depending on if the
	 *   {@link #urls}, {@link #email}, {@link #phone},
	 *   {@link #hashtag}, and {@link #mention} options are enabled). This must be a non-HTML string.
	 * @param {Number} [offset=0] The offset of the text node within the
	 *   original string. This is used when parsing with the {@link #parse}
	 *   method to generate correct offsets within the {@link Autolinker.match.Match}
	 *   instances, but may be omitted if calling this method publicly.
	 * @return {Autolinker.match.Match[]} The array of Matches found in the
	 *   given input `text`.
	 */
	parseText : function( text, offset ) {
		offset = offset || 0;
		var matchers = this.getMatchers(),
		    matches = [];

		for( var i = 0, numMatchers = matchers.length; i < numMatchers; i++ ) {
			var textMatches = matchers[ i ].parseMatches( text );

			// Correct the offset of each of the matches. They are originally
			// the offset of the match within the provided text node, but we
			// need to correct them to be relative to the original HTML input
			// string (i.e. the one provided to #parse).
			for( var j = 0, numTextMatches = textMatches.length; j < numTextMatches; j++ ) {
				textMatches[ j ].setOffset( offset + textMatches[ j ].getOffset() );
			}

			matches.push.apply( matches, textMatches );
		}
		return matches;
	},


	/**
	 * Automatically links URLs, Email addresses, Phone numbers, Hashtags,
	 * and Mentions (Twitter, Instagram, Soundcloud) found in the given chunk of HTML. Does not link
	 * URLs found within HTML tags.
	 *
	 * For instance, if given the text: `You should go to http://www.yahoo.com`,
	 * then the result will be `You should go to
	 * &lt;a href="http://www.yahoo.com"&gt;http://www.yahoo.com&lt;/a&gt;`
	 *
	 * This method finds the text around any HTML elements in the input
	 * `textOrHtml`, which will be the text that is processed. Any original HTML
	 * elements will be left as-is, as well as the text that is already wrapped
	 * in anchor (&lt;a&gt;) tags.
	 *
	 * @param {String} textOrHtml The HTML or text to autolink matches within
	 *   (depending on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #hashtag}, and {@link #mention} options are enabled).
	 * @return {String} The HTML, with matches automatically linked.
	 */
	link : function( textOrHtml ) {
		if( !textOrHtml ) { return ""; }  // handle `null` and `undefined`

		var matches = this.parse( textOrHtml ),
			newHtml = [],
			lastIndex = 0;

		for( var i = 0, len = matches.length; i < len; i++ ) {
			var match = matches[ i ];

			newHtml.push( textOrHtml.substring( lastIndex, match.getOffset() ) );
			newHtml.push( this.createMatchReturnVal( match ) );

			lastIndex = match.getOffset() + match.getMatchedText().length;
		}
		newHtml.push( textOrHtml.substring( lastIndex ) );  // handle the text after the last match

		return newHtml.join( '' );
	},


	/**
	 * Creates the return string value for a given match in the input string.
	 *
	 * This method handles the {@link #replaceFn}, if one was provided.
	 *
	 * @private
	 * @param {Autolinker.match.Match} match The Match object that represents
	 *   the match.
	 * @return {String} The string that the `match` should be replaced with.
	 *   This is usually the anchor tag string, but may be the `matchStr` itself
	 *   if the match is not to be replaced.
	 */
	createMatchReturnVal : function( match ) {
		// Handle a custom `replaceFn` being provided
		var replaceFnResult;
		if( this.replaceFn ) {
			replaceFnResult = this.replaceFn.call( this.context, match );  // Autolinker instance is the context
		}

		if( typeof replaceFnResult === 'string' ) {
			return replaceFnResult;  // `replaceFn` returned a string, use that

		} else if( replaceFnResult === false ) {
			return match.getMatchedText();  // no replacement for the match

		} else if( replaceFnResult instanceof Autolinker.HtmlTag ) {
			return replaceFnResult.toAnchorString();

		} else {  // replaceFnResult === true, or no/unknown return value from function
			// Perform Autolinker's default anchor tag generation
			var anchorTag = match.buildTag();  // returns an Autolinker.HtmlTag instance

			return anchorTag.toAnchorString();
		}
	},


	/**
	 * Lazily instantiates and returns the {@link #htmlParser} instance for this
	 * Autolinker instance.
	 *
	 * @protected
	 * @return {Autolinker.htmlParser.HtmlParser}
	 */
	getHtmlParser : function() {
		var htmlParser = this.htmlParser;

		if( !htmlParser ) {
			htmlParser = this.htmlParser = new Autolinker.htmlParser.HtmlParser();
		}

		return htmlParser;
	},


	/**
	 * Lazily instantiates and returns the {@link Autolinker.matcher.Matcher}
	 * instances for this Autolinker instance.
	 *
	 * @protected
	 * @return {Autolinker.matcher.Matcher[]}
	 */
	getMatchers : function() {
		if( !this.matchers ) {
			var matchersNs = Autolinker.matcher,
			    tagBuilder = this.getTagBuilder();

			var matchers = [
				new matchersNs.Hashtag( { tagBuilder: tagBuilder, serviceName: this.hashtag } ),
				new matchersNs.Email( { tagBuilder: tagBuilder } ),
				new matchersNs.Phone( { tagBuilder: tagBuilder } ),
				new matchersNs.Mention( { tagBuilder: tagBuilder, serviceName: this.mention } ),
				new matchersNs.Url( { tagBuilder: tagBuilder, stripPrefix: this.stripPrefix, stripTrailingSlash: this.stripTrailingSlash, decodePercentEncoding: this.decodePercentEncoding } )
			];

			return ( this.matchers = matchers );

		} else {
			return this.matchers;
		}
	},


	/**
	 * Returns the {@link #tagBuilder} instance for this Autolinker instance, lazily instantiating it
	 * if it does not yet exist.
	 *
	 * This method may be used in a {@link #replaceFn} to generate the {@link Autolinker.HtmlTag HtmlTag} instance that
	 * Autolinker would normally generate, and then allow for modifications before returning it. For example:
	 *
	 *     var html = Autolinker.link( "Test google.com", {
	 *         replaceFn : function( match ) {
	 *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance
	 *             tag.setAttr( 'rel', 'nofollow' );
	 *
	 *             return tag;
	 *         }
	 *     } );
	 *
	 *     // generated html:
	 *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
	 *
	 * @return {Autolinker.AnchorTagBuilder}
	 */
	getTagBuilder : function() {
		var tagBuilder = this.tagBuilder;

		if( !tagBuilder ) {
			tagBuilder = this.tagBuilder = new Autolinker.AnchorTagBuilder( {
				newWindow   : this.newWindow,
				truncate    : this.truncate,
				className   : this.className
			} );
		}

		return tagBuilder;
	}

};


// Autolinker Namespaces

Autolinker.match = {};
Autolinker.matcher = {};
Autolinker.htmlParser = {};
Autolinker.truncate = {};

/*global Autolinker */
/*jshint eqnull:true, boss:true */
/**
 * @class Autolinker.Util
 * @singleton
 *
 * A few utility methods for Autolinker.
 */
Autolinker.Util = {

	/**
	 * @property {Function} abstractMethod
	 *
	 * A function object which represents an abstract method.
	 */
	abstractMethod : function() { throw "abstract"; },


	/**
	 * @private
	 * @property {RegExp} trimRegex
	 *
	 * The regular expression used to trim the leading and trailing whitespace
	 * from a string.
	 */
	trimRegex : /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,


	/**
	 * Assigns (shallow copies) the properties of `src` onto `dest`.
	 *
	 * @param {Object} dest The destination object.
	 * @param {Object} src The source object.
	 * @return {Object} The destination object (`dest`)
	 */
	assign : function( dest, src ) {
		for( var prop in src ) {
			if( src.hasOwnProperty( prop ) ) {
				dest[ prop ] = src[ prop ];
			}
		}

		return dest;
	},


	/**
	 * Assigns (shallow copies) the properties of `src` onto `dest`, if the
	 * corresponding property on `dest` === `undefined`.
	 *
	 * @param {Object} dest The destination object.
	 * @param {Object} src The source object.
	 * @return {Object} The destination object (`dest`)
	 */
	defaults : function( dest, src ) {
		for( var prop in src ) {
			if( src.hasOwnProperty( prop ) && dest[ prop ] === undefined ) {
				dest[ prop ] = src[ prop ];
			}
		}

		return dest;
	},


	/**
	 * Extends `superclass` to create a new subclass, adding the `protoProps` to the new subclass's prototype.
	 *
	 * @param {Function} superclass The constructor function for the superclass.
	 * @param {Object} protoProps The methods/properties to add to the subclass's prototype. This may contain the
	 *   special property `constructor`, which will be used as the new subclass's constructor function.
	 * @return {Function} The new subclass function.
	 */
	extend : function( superclass, protoProps ) {
		var superclassProto = superclass.prototype;

		var F = function() {};
		F.prototype = superclassProto;

		var subclass;
		if( protoProps.hasOwnProperty( 'constructor' ) ) {
			subclass = protoProps.constructor;
		} else {
			subclass = function() { superclassProto.constructor.apply( this, arguments ); };
		}

		var subclassProto = subclass.prototype = new F();  // set up prototype chain
		subclassProto.constructor = subclass;  // fix constructor property
		subclassProto.superclass = superclassProto;

		delete protoProps.constructor;  // don't re-assign constructor property to the prototype, since a new function may have been created (`subclass`), which is now already there
		Autolinker.Util.assign( subclassProto, protoProps );

		return subclass;
	},


	/**
	 * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the
	 * end of the string (by default, two periods: '..'). If the `str` length does not exceed
	 * `len`, the string will be returned unchanged.
	 *
	 * @param {String} str The string to truncate and add an ellipsis to.
	 * @param {Number} truncateLen The length to truncate the string at.
	 * @param {String} [ellipsisChars=...] The ellipsis character(s) to add to the end of `str`
	 *   when truncated. Defaults to '...'
	 */
	ellipsis : function( str, truncateLen, ellipsisChars ) {
		var ellipsisLength;

		if( str.length > truncateLen ) {
			if(ellipsisChars == null) {
			  ellipsisChars = '&hellip;';
			  ellipsisLength = 3;
			} else {
			  ellipsisLength = ellipsisChars.length;
			}

			str = str.substring( 0, truncateLen - ellipsisLength ) + ellipsisChars;
		}
		return str;
	},


	/**
	 * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below).
	 *
	 * @param {Array} arr The array to find an element of.
	 * @param {*} element The element to find in the array, and return the index of.
	 * @return {Number} The index of the `element`, or -1 if it was not found.
	 */
	indexOf : function( arr, element ) {
		if( Array.prototype.indexOf ) {
			return arr.indexOf( element );

		} else {
			for( var i = 0, len = arr.length; i < len; i++ ) {
				if( arr[ i ] === element ) return i;
			}
			return -1;
		}
	},


	/**
	 * Removes array elements based on a filtering function. Mutates the input
	 * array.
	 *
	 * Using this instead of the ES5 Array.prototype.filter() function, to allow
	 * Autolinker compatibility with IE8, and also to prevent creating many new
	 * arrays in memory for filtering.
	 *
	 * @param {Array} arr The array to remove elements from. This array is
	 *   mutated.
	 * @param {Function} fn A function which should return `true` to
	 *   remove an element.
	 * @return {Array} The mutated input `arr`.
	 */
	remove : function( arr, fn ) {
		for( var i = arr.length - 1; i >= 0; i-- ) {
			if( fn( arr[ i ] ) === true ) {
				arr.splice( i, 1 );
			}
		}
	},


	/**
	 * Performs the functionality of what modern browsers do when `String.prototype.split()` is called
	 * with a regular expression that contains capturing parenthesis.
	 *
	 * For example:
	 *
	 *     // Modern browsers:
	 *     "a,b,c".split( /(,)/ );  // --> [ 'a', ',', 'b', ',', 'c' ]
	 *
	 *     // Old IE (including IE8):
	 *     "a,b,c".split( /(,)/ );  // --> [ 'a', 'b', 'c' ]
	 *
	 * This method emulates the functionality of modern browsers for the old IE case.
	 *
	 * @param {String} str The string to split.
	 * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting
	 *   character(s) will be spliced into the array, as in the "modern browsers" example in the
	 *   description of this method.
	 *   Note #1: the supplied regular expression **must** have the 'g' flag specified.
	 *   Note #2: for simplicity's sake, the regular expression does not need
	 *   to contain capturing parenthesis - it will be assumed that any match has them.
	 * @return {String[]} The split array of strings, with the splitting character(s) included.
	 */
	splitAndCapture : function( str, splitRegex ) {
		if( !splitRegex.global ) throw new Error( "`splitRegex` must have the 'g' flag set" );

		var result = [],
		    lastIdx = 0,
		    match;

		while( match = splitRegex.exec( str ) ) {
			result.push( str.substring( lastIdx, match.index ) );
			result.push( match[ 0 ] );  // push the splitting char(s)

			lastIdx = match.index + match[ 0 ].length;
		}
		result.push( str.substring( lastIdx ) );

		return result;
	},


	/**
	 * Trims the leading and trailing whitespace from a string.
	 *
	 * @param {String} str The string to trim.
	 * @return {String}
	 */
	trim : function( str ) {
		return str.replace( this.trimRegex, '' );
	}

};

/*global Autolinker */
/*jshint boss:true */
/**
 * @class Autolinker.HtmlTag
 * @extends Object
 *
 * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically.
 *
 * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use
 * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}.
 *
 * ## Examples
 *
 * Example instantiation:
 *
 *     var tag = new Autolinker.HtmlTag( {
 *         tagName : 'a',
 *         attrs   : { 'href': 'http://google.com', 'class': 'external-link' },
 *         innerHtml : 'Google'
 *     } );
 *
 *     tag.toAnchorString();  // <a href="http://google.com" class="external-link">Google</a>
 *
 *     // Individual accessor methods
 *     tag.getTagName();                 // 'a'
 *     tag.getAttr( 'href' );            // 'http://google.com'
 *     tag.hasClass( 'external-link' );  // true
 *
 *
 * Using mutator methods (which may be used in combination with instantiation config properties):
 *
 *     var tag = new Autolinker.HtmlTag();
 *     tag.setTagName( 'a' );
 *     tag.setAttr( 'href', 'http://google.com' );
 *     tag.addClass( 'external-link' );
 *     tag.setInnerHtml( 'Google' );
 *
 *     tag.getTagName();                 // 'a'
 *     tag.getAttr( 'href' );            // 'http://google.com'
 *     tag.hasClass( 'external-link' );  // true
 *
 *     tag.toAnchorString();  // <a href="http://google.com" class="external-link">Google</a>
 *
 *
 * ## Example use within a {@link Autolinker#replaceFn replaceFn}
 *
 *     var html = Autolinker.link( "Test google.com", {
 *         replaceFn : function( match ) {
 *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text
 *             tag.setAttr( 'rel', 'nofollow' );
 *
 *             return tag;
 *         }
 *     } );
 *
 *     // generated html:
 *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
 *
 *
 * ## Example use with a new tag for the replacement
 *
 *     var html = Autolinker.link( "Test google.com", {
 *         replaceFn : function( match ) {
 *             var tag = new Autolinker.HtmlTag( {
 *                 tagName : 'button',
 *                 attrs   : { 'title': 'Load URL: ' + match.getAnchorHref() },
 *                 innerHtml : 'Load URL: ' + match.getAnchorText()
 *             } );
 *
 *             return tag;
 *         }
 *     } );
 *
 *     // generated html:
 *     //   Test <button title="Load URL: http://google.com">Load URL: google.com</button>
 */
Autolinker.HtmlTag = Autolinker.Util.extend( Object, {

	/**
	 * @cfg {String} tagName
	 *
	 * The tag name. Ex: 'a', 'button', etc.
	 *
	 * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString}
	 * is executed.
	 */

	/**
	 * @cfg {Object.<String, String>} attrs
	 *
	 * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the
	 * values are the attribute values.
	 */

	/**
	 * @cfg {String} innerHtml
	 *
	 * The inner HTML for the tag.
	 *
	 * Note the camel case name on `innerHtml`. Acronyms are camelCased in this utility (such as not to run into the acronym
	 * naming inconsistency that the DOM developers created with `XMLHttpRequest`). You may alternatively use {@link #innerHTML}
	 * if you prefer, but this one is recommended.
	 */

	/**
	 * @cfg {String} innerHTML
	 *
	 * Alias of {@link #innerHtml}, accepted for consistency with the browser DOM api, but prefer the camelCased version
	 * for acronym names.
	 */


	/**
	 * @protected
	 * @property {RegExp} whitespaceRegex
	 *
	 * Regular expression used to match whitespace in a string of CSS classes.
	 */
	whitespaceRegex : /\s+/,


	/**
	 * @constructor
	 * @param {Object} [cfg] The configuration properties for this class, in an Object (map)
	 */
	constructor : function( cfg ) {
		Autolinker.Util.assign( this, cfg );

		this.innerHtml = this.innerHtml || this.innerHTML;  // accept either the camelCased form or the fully capitalized acronym
	},


	/**
	 * Sets the tag name that will be used to generate the tag with.
	 *
	 * @param {String} tagName
	 * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
	 */
	setTagName : function( tagName ) {
		this.tagName = tagName;
		return this;
	},


	/**
	 * Retrieves the tag name.
	 *
	 * @return {String}
	 */
	getTagName : function() {
		return this.tagName || "";
	},


	/**
	 * Sets an attribute on the HtmlTag.
	 *
	 * @param {String} attrName The attribute name to set.
	 * @param {String} attrValue The attribute value to set.
	 * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
	 */
	setAttr : function( attrName, attrValue ) {
		var tagAttrs = this.getAttrs();
		tagAttrs[ attrName ] = attrValue;

		return this;
	},


	/**
	 * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`.
	 *
	 * @param {String} attrName The attribute name to retrieve.
	 * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag.
	 */
	getAttr : function( attrName ) {
		return this.getAttrs()[ attrName ];
	},


	/**
	 * Sets one or more attributes on the HtmlTag.
	 *
	 * @param {Object.<String, String>} attrs A key/value Object (map) of the attributes to set.
	 * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
	 */
	setAttrs : function( attrs ) {
		var tagAttrs = this.getAttrs();
		Autolinker.Util.assign( tagAttrs, attrs );

		return this;
	},


	/**
	 * Retrieves the attributes Object (map) for the HtmlTag.
	 *
	 * @return {Object.<String, String>} A key/value object of the attributes for the HtmlTag.
	 */
	getAttrs : function() {
		return this.attrs || ( this.attrs = {} );
	},


	/**
	 * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag.
	 *
	 * @param {String} cssClass One or more space-separated CSS classes to set (overwrite).
	 * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
	 */
	setClass : function( cssClass ) {
		return this.setAttr( 'class', cssClass );
	},


	/**
	 * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes.
	 *
	 * @param {String} cssClass One or more space-separated CSS classes to add.
	 * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
	 */
	addClass : function( cssClass ) {
		var classAttr = this.getClass(),
		    whitespaceRegex = this.whitespaceRegex,
		    indexOf = Autolinker.Util.indexOf,  // to support IE8 and below
		    classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ),
		    newClasses = cssClass.split( whitespaceRegex ),
		    newClass;

		while( newClass = newClasses.shift() ) {
			if( indexOf( classes, newClass ) === -1 ) {
				classes.push( newClass );
			}
		}

		this.getAttrs()[ 'class' ] = classes.join( " " );
		return this;
	},


	/**
	 * Convenience method to remove one or more CSS classes from the HtmlTag.
	 *
	 * @param {String} cssClass One or more space-separated CSS classes to remove.
	 * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
	 */
	removeClass : function( cssClass ) {
		var classAttr = this.getClass(),
		    whitespaceRegex = this.whitespaceRegex,
		    indexOf = Autolinker.Util.indexOf,  // to support IE8 and below
		    classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ),
		    removeClasses = cssClass.split( whitespaceRegex ),
		    removeClass;

		while( classes.length && ( removeClass = removeClasses.shift() ) ) {
			var idx = indexOf( classes, removeClass );
			if( idx !== -1 ) {
				classes.splice( idx, 1 );
			}
		}

		this.getAttrs()[ 'class' ] = classes.join( " " );
		return this;
	},


	/**
	 * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when
	 * there are multiple.
	 *
	 * @return {String}
	 */
	getClass : function() {
		return this.getAttrs()[ 'class' ] || "";
	},


	/**
	 * Convenience method to check if the tag has a CSS class or not.
	 *
	 * @param {String} cssClass The CSS class to check for.
	 * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise.
	 */
	hasClass : function( cssClass ) {
		return ( ' ' + this.getClass() + ' ' ).indexOf( ' ' + cssClass + ' ' ) !== -1;
	},


	/**
	 * Sets the inner HTML for the tag.
	 *
	 * @param {String} html The inner HTML to set.
	 * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
	 */
	setInnerHtml : function( html ) {
		this.innerHtml = html;

		return this;
	},


	/**
	 * Retrieves the inner HTML for the tag.
	 *
	 * @return {String}
	 */
	getInnerHtml : function() {
		return this.innerHtml || "";
	},


	/**
	 * Override of superclass method used to generate the HTML string for the tag.
	 *
	 * @return {String}
	 */
	toAnchorString : function() {
		var tagName = this.getTagName(),
		    attrsStr = this.buildAttrsStr();

		attrsStr = ( attrsStr ) ? ' ' + attrsStr : '';  // prepend a space if there are actually attributes

		return [ '<', tagName, attrsStr, '>', this.getInnerHtml(), '</', tagName, '>' ].join( "" );
	},


	/**
	 * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate
	 * the stringified HtmlTag.
	 *
	 * @protected
	 * @return {String} Example return: `attr1="value1" attr2="value2"`
	 */
	buildAttrsStr : function() {
		if( !this.attrs ) return "";  // no `attrs` Object (map) has been set, return empty string

		var attrs = this.getAttrs(),
		    attrsArr = [];

		for( var prop in attrs ) {
			if( attrs.hasOwnProperty( prop ) ) {
				attrsArr.push( prop + '="' + attrs[ prop ] + '"' );
			}
		}
		return attrsArr.join( " " );
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.RegexLib
 * @singleton
 *
 * Builds and stores a library of the common regular expressions used by the
 * Autolinker utility.
 *
 * Other regular expressions may exist ad-hoc, but these are generally the
 * regular expressions that are shared between source files.
 */
Autolinker.RegexLib = (function() {

	/**
	 * The string form of a regular expression that would match all of the
	 * alphabetic ("letter") chars in the unicode character set when placed in a
	 * RegExp character class (`[]`). This includes all international alphabetic
	 * characters.
	 *
	 * These would be the characters matched by unicode regex engines `\p{L}`
	 * escape ("all letters").
	 *
	 * Taken from the XRegExp library: http://xregexp.com/
	 * Specifically: http://xregexp.com/v/3.0.0/unicode-categories.js
	 *
	 * @private
	 * @type {String}
	 */
	var alphaCharsStr = 'A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC';

	/**
	 * The string form of a regular expression that would match all of the
	 * decimal number chars in the unicode character set when placed in a RegExp
	 * character class (`[]`).
	 *
	 * These would be the characters matched by unicode regex engines `\p{Nd}`
	 * escape ("all decimal numbers")
	 *
	 * Taken from the XRegExp library: http://xregexp.com/
	 * Specifically: http://xregexp.com/v/3.0.0/unicode-categories.js
	 *
	 * @private
	 * @type {String}
	 */
	var decimalNumbersStr = '0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19';


	// See documentation below
	var alphaNumericCharsStr = alphaCharsStr + decimalNumbersStr;

	// Simplified IP regular expression
	var ipStr = '(?:[' + decimalNumbersStr + ']{1,3}\\.){3}[' + decimalNumbersStr + ']{1,3}';

	// Protected domain label which do not allow "-" character on the beginning and the end of a single label
	var domainLabelStr = '[' + alphaNumericCharsStr + '](?:[' + alphaNumericCharsStr + '\\-]{0,61}[' + alphaNumericCharsStr + '])?';

	var getDomainLabelStr = function(group) {
		return '(?=(' + domainLabelStr + '))\\' + group;
	};

	// See documentation below
	var getDomainNameStr = function(group) {
		return '(?:' + getDomainLabelStr(group) + '(?:\\.' + getDomainLabelStr(group + 1) + '){0,126}|' + ipStr + ')';
	};

	return {

		/**
		 * The string form of a regular expression that would match all of the
		 * letters and decimal number chars in the unicode character set when placed
		 * in a RegExp character class (`[]`).
		 *
		 * These would be the characters matched by unicode regex engines `[\p{L}\p{Nd}]`
		 * escape ("all letters and decimal numbers")
		 *
		 * @property {String} alphaNumericCharsStr
		 */
		alphaNumericCharsStr : alphaNumericCharsStr,

		/**
		 * The string form of a regular expression that would match all of the
		 * letters and in the unicode character set when placed
		 * in a RegExp character class (`[]`).
		 *
		 * These would be the characters matched by unicode regex engines `[\p{L}]`
		 * escape ("all letters")
		 *
		 * @property {String} alphaCharsStr
		 */
		alphaCharsStr : alphaCharsStr,

		/**
		 * A regular expression to match domain names of a URL or email address.
		 * Ex: 'google', 'yahoo', 'some-other-company', etc.
		 *
		 * @property {RegExp} domainNameRegex
		 */
		getDomainNameStr : getDomainNameStr,

	};


}() );

/*global Autolinker */
/*jshint sub:true */
/**
 * @protected
 * @class Autolinker.AnchorTagBuilder
 * @extends Object
 *
 * Builds anchor (&lt;a&gt;) tags for the Autolinker utility when a match is
 * found.
 *
 * Normally this class is instantiated, configured, and used internally by an
 * {@link Autolinker} instance, but may actually be used indirectly in a
 * {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag}
 * instances which may be modified before returning from the
 * {@link Autolinker#replaceFn replaceFn}. For example:
 *
 *     var html = Autolinker.link( "Test google.com", {
 *         replaceFn : function( match ) {
 *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance
 *             tag.setAttr( 'rel', 'nofollow' );
 *
 *             return tag;
 *         }
 *     } );
 *
 *     // generated html:
 *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
 */
Autolinker.AnchorTagBuilder = Autolinker.Util.extend( Object, {

	/**
	 * @cfg {Boolean} newWindow
	 * @inheritdoc Autolinker#newWindow
	 */

	/**
	 * @cfg {Object} truncate
	 * @inheritdoc Autolinker#truncate
	 */

	/**
	 * @cfg {String} className
	 * @inheritdoc Autolinker#className
	 */


	/**
	 * @constructor
	 * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		cfg = cfg || {};

		this.newWindow = cfg.newWindow;
		this.truncate = cfg.truncate;
		this.className = cfg.className;
	},


	/**
	 * Generates the actual anchor (&lt;a&gt;) tag to use in place of the
	 * matched text, via its `match` object.
	 *
	 * @param {Autolinker.match.Match} match The Match instance to generate an
	 *   anchor tag from.
	 * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag.
	 */
	build : function( match ) {
		return new Autolinker.HtmlTag( {
			tagName   : 'a',
			attrs     : this.createAttrs( match ),
			innerHtml : this.processAnchorText( match.getAnchorText() )
		} );
	},


	/**
	 * Creates the Object (map) of the HTML attributes for the anchor (&lt;a&gt;)
	 *   tag being generated.
	 *
	 * @protected
	 * @param {Autolinker.match.Match} match The Match instance to generate an
	 *   anchor tag from.
	 * @return {Object} A key/value Object (map) of the anchor tag's attributes.
	 */
	createAttrs : function( match ) {
		var attrs = {
			'href' : match.getAnchorHref()  // we'll always have the `href` attribute
		};

		var cssClass = this.createCssClass( match );
		if( cssClass ) {
			attrs[ 'class' ] = cssClass;
		}
		if( this.newWindow ) {
			attrs[ 'target' ] = "_blank";
			attrs[ 'rel' ] = "noopener noreferrer";
		}

		if( this.truncate ) {
			if( this.truncate.length && this.truncate.length < match.getAnchorText().length ) {
				attrs[ 'title' ] = match.getAnchorHref();
			}
		}

		return attrs;
	},


	/**
	 * Creates the CSS class that will be used for a given anchor tag, based on
	 * the `matchType` and the {@link #className} config.
	 *
	 * Example returns:
	 *
	 * - ""                                      // no {@link #className}
	 * - "myLink myLink-url"                     // url match
	 * - "myLink myLink-email"                   // email match
	 * - "myLink myLink-phone"                   // phone match
	 * - "myLink myLink-hashtag"                 // hashtag match
	 * - "myLink myLink-mention myLink-twitter"  // mention match with Twitter service
	 *
	 * @private
	 * @param {Autolinker.match.Match} match The Match instance to generate an
	 *   anchor tag from.
	 * @return {String} The CSS class string for the link. Example return:
	 *   "myLink myLink-url". If no {@link #className} was configured, returns
	 *   an empty string.
	 */
	createCssClass : function( match ) {
		var className = this.className;

		if( !className ) {
			return "";

		} else {
			var returnClasses = [ className ],
				cssClassSuffixes = match.getCssClassSuffixes();

			for( var i = 0, len = cssClassSuffixes.length; i < len; i++ ) {
				returnClasses.push( className + '-' + cssClassSuffixes[ i ] );
			}
			return returnClasses.join( ' ' );
		}
	},


	/**
	 * Processes the `anchorText` by truncating the text according to the
	 * {@link #truncate} config.
	 *
	 * @private
	 * @param {String} anchorText The anchor tag's text (i.e. what will be
	 *   displayed).
	 * @return {String} The processed `anchorText`.
	 */
	processAnchorText : function( anchorText ) {
		anchorText = this.doTruncate( anchorText );

		return anchorText;
	},


	/**
	 * Performs the truncation of the `anchorText` based on the {@link #truncate}
	 * option. If the `anchorText` is longer than the length specified by the
	 * {@link #truncate} option, the truncation is performed based on the
	 * `location` property. See {@link #truncate} for details.
	 *
	 * @private
	 * @param {String} anchorText The anchor tag's text (i.e. what will be
	 *   displayed).
	 * @return {String} The truncated anchor text.
	 */
	doTruncate : function( anchorText ) {
		var truncate = this.truncate;
		if( !truncate || !truncate.length ) return anchorText;

		var truncateLength = truncate.length,
			truncateLocation = truncate.location;

		if( truncateLocation === 'smart' ) {
			return Autolinker.truncate.TruncateSmart( anchorText, truncateLength );

		} else if( truncateLocation === 'middle' ) {
			return Autolinker.truncate.TruncateMiddle( anchorText, truncateLength );

		} else {
			return Autolinker.truncate.TruncateEnd( anchorText, truncateLength );
		}
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.htmlParser.HtmlParser
 * @extends Object
 *
 * An HTML parser implementation which simply walks an HTML string and returns an array of
 * {@link Autolinker.htmlParser.HtmlNode HtmlNodes} that represent the basic HTML structure of the input string.
 *
 * Autolinker uses this to only link URLs/emails/mentions within text nodes, effectively ignoring / "walking
 * around" HTML tags.
 */
Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, {

	/**
	 * @private
	 * @property {RegExp} htmlRegex
	 *
	 * The regular expression used to pull out HTML tags from a string. Handles namespaced HTML tags and
	 * attribute names, as specified by http://www.w3.org/TR/html-markup/syntax.html.
	 *
	 * Capturing groups:
	 *
	 * 1. The "!DOCTYPE" tag name, if a tag is a &lt;!DOCTYPE&gt; tag.
	 * 2. If it is an end tag, this group will have the '/'.
	 * 3. If it is a comment tag, this group will hold the comment text (i.e.
	 *    the text inside the `&lt;!--` and `--&gt;`.
	 * 4. The tag name for a tag without attributes (other than the &lt;!DOCTYPE&gt; tag)
	 * 5. The tag name for a tag with attributes (other than the &lt;!DOCTYPE&gt; tag)
	 */
	htmlRegex : (function() {
		var commentTagRegex = /!--([\s\S]+?)--/,
		    tagNameRegex = /[0-9a-zA-Z][0-9a-zA-Z:]*/,
		    attrNameRegex = /[^\s"'>\/=\x00-\x1F\x7F]+/,   // the unicode range accounts for excluding control chars, and the delete char
		    attrValueRegex = /(?:"[^"]*?"|'[^']*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values
		    optionalAttrValueRegex = '(?:\\s*?=\\s*?' + attrValueRegex.source + ')?'; // optional '=[value]'

		var getNameEqualsValueRegex = function(group) {
			return '(?=(' + attrNameRegex.source + '))\\' + group + optionalAttrValueRegex;
		};

		return new RegExp( [
			// for <!DOCTYPE> tag. Ex: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
			'(?:',
				'<(!DOCTYPE)',  // *** Capturing Group 1 - If it's a doctype tag

					// Zero or more attributes following the tag name
					'(?:',
						'\\s+',  // one or more whitespace chars before an attribute

						// Either:
						// A. attr="value", or
						// B. "value" alone (To cover example doctype tag: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
						// *** Capturing Group 2 - Pseudo-atomic group for attrNameRegex
						'(?:', getNameEqualsValueRegex(2), '|', attrValueRegex.source + ')',
					')*',
				'>',
			')',

			'|',

			// All other HTML tags (i.e. tags that are not <!DOCTYPE>)
			'(?:',
				'<(/)?',  // Beginning of a tag or comment. Either '<' for a start tag, or '</' for an end tag.
				          // *** Capturing Group 3: The slash or an empty string. Slash ('/') for end tag, empty string for start or self-closing tag.

					'(?:',
						commentTagRegex.source,  // *** Capturing Group 4 - A Comment Tag's Text

						'|',

						// Handle tag without attributes.
						// Doing this separately from a tag that has attributes
						// to fix a regex time complexity issue seen with the
						// example in https://github.com/gregjacobs/Autolinker.js/issues/172
						'(?:',
							// *** Capturing Group 5 - The tag name for a tag without attributes
							'(' + tagNameRegex.source + ')',

							'\\s*/?',  // any trailing spaces and optional '/' before the closing '>'
						')',

						'|',

						// Handle tag with attributes
						// Doing this separately from a tag with no attributes
						// to fix a regex time complexity issue seen with the
						// example in https://github.com/gregjacobs/Autolinker.js/issues/172
						'(?:',
							// *** Capturing Group 6 - The tag name for a tag with attributes
							'(' + tagNameRegex.source + ')',

							'\\s+',  // must have at least one space after the tag name to prevent ReDoS issue (issue #172)

							// Zero or more attributes following the tag name
							'(?:',
								'(?:\\s+|\\b)',        // any number of whitespace chars before an attribute. NOTE: Using \s* here throws Chrome into an infinite loop for some reason, so using \s+|\b instead
								// *** Capturing Group 7 - Pseudo-atomic group for attrNameRegex
								getNameEqualsValueRegex(7),  // attr="value" (with optional ="value" part)
							')*',

							'\\s*/?',  // any trailing spaces and optional '/' before the closing '>'
						')',
					')',
				'>',
			')'
		].join( "" ), 'gi' );
	} )(),

	/**
	 * @private
	 * @property {RegExp} htmlCharacterEntitiesRegex
	 *
	 * The regular expression that matches common HTML character entities.
	 *
	 * Ignoring &amp; as it could be part of a query string -- handling it separately.
	 */
	htmlCharacterEntitiesRegex: /(&nbsp;|&#160;|&lt;|&#60;|&gt;|&#62;|&quot;|&#34;|&#39;)/gi,


	/**
	 * Parses an HTML string and returns a simple array of {@link Autolinker.htmlParser.HtmlNode HtmlNodes}
	 * to represent the HTML structure of the input string.
	 *
	 * @param {String} html The HTML to parse.
	 * @return {Autolinker.htmlParser.HtmlNode[]}
	 */
	parse : function( html ) {
		var htmlRegex = this.htmlRegex,
		    currentResult,
		    lastIndex = 0,
		    textAndEntityNodes,
		    nodes = [];  // will be the result of the method

		while( ( currentResult = htmlRegex.exec( html ) ) !== null ) {
			var tagText = currentResult[ 0 ],
			    commentText = currentResult[ 4 ], // if we've matched a comment
			    tagName = currentResult[ 1 ] || currentResult[ 5 ] || currentResult[ 6 ],  // The <!DOCTYPE> tag (ex: "!DOCTYPE"), or another tag (ex: "a" or "img")
			    isClosingTag = !!currentResult[ 3 ],
			    offset = currentResult.index,
			    inBetweenTagsText = html.substring( lastIndex, offset );

			// Push TextNodes and EntityNodes for any text found between tags
			if( inBetweenTagsText ) {
				textAndEntityNodes = this.parseTextAndEntityNodes( lastIndex, inBetweenTagsText );
				nodes.push.apply( nodes, textAndEntityNodes );
			}

			// Push the CommentNode or ElementNode
			if( commentText ) {
				nodes.push( this.createCommentNode( offset, tagText, commentText ) );
			} else {
				nodes.push( this.createElementNode( offset, tagText, tagName, isClosingTag ) );
			}

			lastIndex = offset + tagText.length;
		}

		// Process any remaining text after the last HTML element. Will process all of the text if there were no HTML elements.
		if( lastIndex < html.length ) {
			var text = html.substring( lastIndex );

			// Push TextNodes and EntityNodes for any text found between tags
			if( text ) {
				textAndEntityNodes = this.parseTextAndEntityNodes( lastIndex, text );

				// Note: the following 3 lines were previously:
				//   nodes.push.apply( nodes, textAndEntityNodes );
				// but this was causing a "Maximum Call Stack Size Exceeded"
				// error on inputs with a large number of html entities.
				textAndEntityNodes.forEach( function( node ) {
					nodes.push( node );
				} );
			}
		}

		return nodes;
	},


	/**
	 * Parses text and HTML entity nodes from a given string. The input string
	 * should not have any HTML tags (elements) within it.
	 *
	 * @private
	 * @param {Number} offset The offset of the text node match within the
	 *   original HTML string.
	 * @param {String} text The string of text to parse. This is from an HTML
	 *   text node.
	 * @return {Autolinker.htmlParser.HtmlNode[]} An array of HtmlNodes to
	 *   represent the {@link Autolinker.htmlParser.TextNode TextNodes} and
	 *   {@link Autolinker.htmlParser.EntityNode EntityNodes} found.
	 */
	parseTextAndEntityNodes : function( offset, text ) {
		var nodes = [],
		    textAndEntityTokens = Autolinker.Util.splitAndCapture( text, this.htmlCharacterEntitiesRegex );  // split at HTML entities, but include the HTML entities in the results array

		// Every even numbered token is a TextNode, and every odd numbered token is an EntityNode
		// For example: an input `text` of "Test &quot;this&quot; today" would turn into the
		//   `textAndEntityTokens`: [ 'Test ', '&quot;', 'this', '&quot;', ' today' ]
		for( var i = 0, len = textAndEntityTokens.length; i < len; i += 2 ) {
			var textToken = textAndEntityTokens[ i ],
			    entityToken = textAndEntityTokens[ i + 1 ];

			if( textToken ) {
				nodes.push( this.createTextNode( offset, textToken ) );
				offset += textToken.length;
			}
			if( entityToken ) {
				nodes.push( this.createEntityNode( offset, entityToken ) );
				offset += entityToken.length;
			}
		}
		return nodes;
	},


	/**
	 * Factory method to create an {@link Autolinker.htmlParser.CommentNode CommentNode}.
	 *
	 * @private
	 * @param {Number} offset The offset of the match within the original HTML
	 *   string.
	 * @param {String} tagText The full text of the tag (comment) that was
	 *   matched, including its &lt;!-- and --&gt;.
	 * @param {String} commentText The full text of the comment that was matched.
	 */
	createCommentNode : function( offset, tagText, commentText ) {
		return new Autolinker.htmlParser.CommentNode( {
			offset : offset,
			text   : tagText,
			comment: Autolinker.Util.trim( commentText )
		} );
	},


	/**
	 * Factory method to create an {@link Autolinker.htmlParser.ElementNode ElementNode}.
	 *
	 * @private
	 * @param {Number} offset The offset of the match within the original HTML
	 *   string.
	 * @param {String} tagText The full text of the tag (element) that was
	 *   matched, including its attributes.
	 * @param {String} tagName The name of the tag. Ex: An &lt;img&gt; tag would
	 *   be passed to this method as "img".
	 * @param {Boolean} isClosingTag `true` if it's a closing tag, false
	 *   otherwise.
	 * @return {Autolinker.htmlParser.ElementNode}
	 */
	createElementNode : function( offset, tagText, tagName, isClosingTag ) {
		return new Autolinker.htmlParser.ElementNode( {
			offset  : offset,
			text    : tagText,
			tagName : tagName.toLowerCase(),
			closing : isClosingTag
		} );
	},


	/**
	 * Factory method to create a {@link Autolinker.htmlParser.EntityNode EntityNode}.
	 *
	 * @private
	 * @param {Number} offset The offset of the match within the original HTML
	 *   string.
	 * @param {String} text The text that was matched for the HTML entity (such
	 *   as '&amp;nbsp;').
	 * @return {Autolinker.htmlParser.EntityNode}
	 */
	createEntityNode : function( offset, text ) {
		return new Autolinker.htmlParser.EntityNode( { offset: offset, text: text } );
	},


	/**
	 * Factory method to create a {@link Autolinker.htmlParser.TextNode TextNode}.
	 *
	 * @private
	 * @param {Number} offset The offset of the match within the original HTML
	 *   string.
	 * @param {String} text The text that was matched.
	 * @return {Autolinker.htmlParser.TextNode}
	 */
	createTextNode : function( offset, text ) {
		return new Autolinker.htmlParser.TextNode( { offset: offset, text: text } );
	}

} );

/*global Autolinker */
/**
 * @abstract
 * @class Autolinker.htmlParser.HtmlNode
 *
 * Represents an HTML node found in an input string. An HTML node is one of the
 * following:
 *
 * 1. An {@link Autolinker.htmlParser.ElementNode ElementNode}, which represents
 *    HTML tags.
 * 2. A {@link Autolinker.htmlParser.CommentNode CommentNode}, which represents
 *    HTML comments.
 * 3. A {@link Autolinker.htmlParser.TextNode TextNode}, which represents text
 *    outside or within HTML tags.
 * 4. A {@link Autolinker.htmlParser.EntityNode EntityNode}, which represents
 *    one of the known HTML entities that Autolinker looks for. This includes
 *    common ones such as &amp;quot; and &amp;nbsp;
 */
Autolinker.htmlParser.HtmlNode = Autolinker.Util.extend( Object, {

	/**
	 * @cfg {Number} offset (required)
	 *
	 * The offset of the HTML node in the original text that was parsed.
	 */
	offset : undefined,

	/**
	 * @cfg {String} text (required)
	 *
	 * The text that was matched for the HtmlNode.
	 *
	 * - In the case of an {@link Autolinker.htmlParser.ElementNode ElementNode},
	 *   this will be the tag's text.
	 * - In the case of an {@link Autolinker.htmlParser.CommentNode CommentNode},
	 *   this will be the comment's text.
	 * - In the case of a {@link Autolinker.htmlParser.TextNode TextNode}, this
	 *   will be the text itself.
	 * - In the case of a {@link Autolinker.htmlParser.EntityNode EntityNode},
	 *   this will be the text of the HTML entity.
	 */
	text : undefined,


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match instance,
	 * specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.Util.assign( this, cfg );

		if( this.offset == null ) throw new Error( '`offset` cfg required' );
		if( this.text == null ) throw new Error( '`text` cfg required' );
	},


	/**
	 * Returns a string name for the type of node that this class represents.
	 *
	 * @abstract
	 * @return {String}
	 */
	getType : Autolinker.Util.abstractMethod,


	/**
	 * Retrieves the {@link #offset} of the HtmlNode. This is the offset of the
	 * HTML node in the original string that was parsed.
	 *
	 * @return {Number}
	 */
	getOffset : function() {
		return this.offset;
	},


	/**
	 * Retrieves the {@link #text} for the HtmlNode.
	 *
	 * @return {String}
	 */
	getText : function() {
		return this.text;
	}

} );
/*global Autolinker */
/**
 * @class Autolinker.htmlParser.CommentNode
 * @extends Autolinker.htmlParser.HtmlNode
 *
 * Represents an HTML comment node that has been parsed by the
 * {@link Autolinker.htmlParser.HtmlParser}.
 *
 * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more
 * details.
 */
Autolinker.htmlParser.CommentNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, {

	/**
	 * @cfg {String} comment (required)
	 *
	 * The text inside the comment tag. This text is stripped of any leading or
	 * trailing whitespace.
	 */
	comment : '',


	/**
	 * Returns a string name for the type of node that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'comment';
	},


	/**
	 * Returns the comment inside the comment tag.
	 *
	 * @return {String}
	 */
	getComment : function() {
		return this.comment;
	}

} );
/*global Autolinker */
/**
 * @class Autolinker.htmlParser.ElementNode
 * @extends Autolinker.htmlParser.HtmlNode
 *
 * Represents an HTML element node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}.
 *
 * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more
 * details.
 */
Autolinker.htmlParser.ElementNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, {

	/**
	 * @cfg {String} tagName (required)
	 *
	 * The name of the tag that was matched.
	 */
	tagName : '',

	/**
	 * @cfg {Boolean} closing (required)
	 *
	 * `true` if the element (tag) is a closing tag, `false` if its an opening
	 * tag.
	 */
	closing : false,


	/**
	 * Returns a string name for the type of node that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'element';
	},


	/**
	 * Returns the HTML element's (tag's) name. Ex: for an &lt;img&gt; tag,
	 * returns "img".
	 *
	 * @return {String}
	 */
	getTagName : function() {
		return this.tagName;
	},


	/**
	 * Determines if the HTML element (tag) is a closing tag. Ex: &lt;div&gt;
	 * returns `false`, while &lt;/div&gt; returns `true`.
	 *
	 * @return {Boolean}
	 */
	isClosing : function() {
		return this.closing;
	}

} );
/*global Autolinker */
/**
 * @class Autolinker.htmlParser.EntityNode
 * @extends Autolinker.htmlParser.HtmlNode
 *
 * Represents a known HTML entity node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}.
 * Ex: '&amp;nbsp;', or '&amp#160;' (which will be retrievable from the {@link #getText}
 * method.
 *
 * Note that this class will only be returned from the HtmlParser for the set of
 * checked HTML entity nodes  defined by the {@link Autolinker.htmlParser.HtmlParser#htmlCharacterEntitiesRegex}.
 *
 * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more
 * details.
 */
Autolinker.htmlParser.EntityNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, {

	/**
	 * Returns a string name for the type of node that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'entity';
	}

} );
/*global Autolinker */
/**
 * @class Autolinker.htmlParser.TextNode
 * @extends Autolinker.htmlParser.HtmlNode
 *
 * Represents a text node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}.
 *
 * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more
 * details.
 */
Autolinker.htmlParser.TextNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, {

	/**
	 * Returns a string name for the type of node that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'text';
	}

} );
/*global Autolinker */
/**
 * @abstract
 * @class Autolinker.match.Match
 *
 * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a
 * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match.
 *
 * For example:
 *
 *     var input = "...";  // string with URLs, Email Addresses, and Mentions (Twitter, Instagram, Soundcloud)
 *
 *     var linkedText = Autolinker.link( input, {
 *         replaceFn : function( match ) {
 *             console.log( "href = ", match.getAnchorHref() );
 *             console.log( "text = ", match.getAnchorText() );
 *
 *             switch( match.getType() ) {
 *                 case 'url' :
 *                     console.log( "url: ", match.getUrl() );
 *
 *                 case 'email' :
 *                     console.log( "email: ", match.getEmail() );
 *
 *                 case 'mention' :
 *                     console.log( "mention: ", match.getMention() );
 *             }
 *         }
 *     } );
 *
 * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}.
 */
Autolinker.match.Match = Autolinker.Util.extend( Object, {

	/**
	 * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required)
	 *
	 * Reference to the AnchorTagBuilder instance to use to generate an anchor
	 * tag for the Match.
	 */

	/**
	 * @cfg {String} matchedText (required)
	 *
	 * The original text that was matched by the {@link Autolinker.matcher.Matcher}.
	 */

	/**
	 * @cfg {Number} offset (required)
	 *
	 * The offset of where the match was made in the input string.
	 */


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match
	 *   instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		if( cfg.tagBuilder == null ) throw new Error( '`tagBuilder` cfg required' );
		if( cfg.matchedText == null ) throw new Error( '`matchedText` cfg required' );
		if( cfg.offset == null ) throw new Error( '`offset` cfg required' );

		this.tagBuilder = cfg.tagBuilder;
		this.matchedText = cfg.matchedText;
		this.offset = cfg.offset;
	},


	/**
	 * Returns a string name for the type of match that this class represents.
	 *
	 * @abstract
	 * @return {String}
	 */
	getType : Autolinker.Util.abstractMethod,


	/**
	 * Returns the original text that was matched.
	 *
	 * @return {String}
	 */
	getMatchedText : function() {
		return this.matchedText;
	},


	/**
	 * Sets the {@link #offset} of where the match was made in the input string.
	 *
	 * A {@link Autolinker.matcher.Matcher} will be fed only HTML text nodes,
	 * and will therefore set an original offset that is relative to the HTML
	 * text node itself. However, we want this offset to be relative to the full
	 * HTML input string, and thus if using {@link Autolinker#parse} (rather
	 * than calling a {@link Autolinker.matcher.Matcher} directly), then this
	 * offset is corrected after the Matcher itself has done its job.
	 *
	 * @param {Number} offset
	 */
	setOffset : function( offset ) {
		this.offset = offset;
	},


	/**
	 * Returns the offset of where the match was made in the input string. This
	 * is the 0-based index of the match.
	 *
	 * @return {Number}
	 */
	getOffset : function() {
		return this.offset;
	},


	/**
	 * Returns the anchor href that should be generated for the match.
	 *
	 * @abstract
	 * @return {String}
	 */
	getAnchorHref : Autolinker.Util.abstractMethod,


	/**
	 * Returns the anchor text that should be generated for the match.
	 *
	 * @abstract
	 * @return {String}
	 */
	getAnchorText : Autolinker.Util.abstractMethod,


	/**
	 * Returns the CSS class suffix(es) for this match.
	 *
	 * A CSS class suffix is appended to the {@link Autolinker#className} in
	 * the {@link Autolinker.AnchorTagBuilder} when a match is translated into
	 * an anchor tag.
	 *
	 * For example, if {@link Autolinker#className} was configured as 'myLink',
	 * and this method returns `[ 'url' ]`, the final class name of the element
	 * will become: 'myLink myLink-url'.
	 *
	 * The match may provide multiple CSS class suffixes to be appended to the
	 * {@link Autolinker#className} in order to facilitate better styling
	 * options for different match criteria. See {@link Autolinker.match.Mention}
	 * for an example.
	 *
	 * By default, this method returns a single array with the match's
	 * {@link #getType type} name, but may be overridden by subclasses.
	 *
	 * @return {String[]}
	 */
	getCssClassSuffixes : function() {
		return [ this.getType() ];
	},


	/**
	 * Builds and returns an {@link Autolinker.HtmlTag} instance based on the
	 * Match.
	 *
	 * This can be used to easily generate anchor tags from matches, and either
	 * return their HTML string, or modify them before doing so.
	 *
	 * Example Usage:
	 *
	 *     var tag = match.buildTag();
	 *     tag.addClass( 'cordova-link' );
	 *     tag.setAttr( 'target', '_system' );
	 *
	 *     tag.toAnchorString();  // <a href="http://google.com" class="cordova-link" target="_system">Google</a>
	 */
	buildTag : function() {
		return this.tagBuilder.build( this );
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.match.Email
 * @extends Autolinker.match.Match
 *
 * Represents a Email match found in an input string which should be Autolinked.
 *
 * See this class's superclass ({@link Autolinker.match.Match}) for more details.
 */
Autolinker.match.Email = Autolinker.Util.extend( Autolinker.match.Match, {

	/**
	 * @cfg {String} email (required)
	 *
	 * The email address that was matched.
	 */


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match
	 *   instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.match.Match.prototype.constructor.call( this, cfg );

		if( !cfg.email ) throw new Error( '`email` cfg required' );

		this.email = cfg.email;
	},


	/**
	 * Returns a string name for the type of match that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'email';
	},


	/**
	 * Returns the email address that was matched.
	 *
	 * @return {String}
	 */
	getEmail : function() {
		return this.email;
	},


	/**
	 * Returns the anchor href that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorHref : function() {
		return 'mailto:' + this.email;
	},


	/**
	 * Returns the anchor text that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorText : function() {
		return this.email;
	}

} );
/*global Autolinker */
/**
 * @class Autolinker.match.Hashtag
 * @extends Autolinker.match.Match
 *
 * Represents a Hashtag match found in an input string which should be
 * Autolinked.
 *
 * See this class's superclass ({@link Autolinker.match.Match}) for more
 * details.
 */
Autolinker.match.Hashtag = Autolinker.Util.extend( Autolinker.match.Match, {

	/**
	 * @cfg {String} serviceName
	 *
	 * The service to point hashtag matches to. See {@link Autolinker#hashtag}
	 * for available values.
	 */

	/**
	 * @cfg {String} hashtag (required)
	 *
	 * The Hashtag that was matched, without the '#'.
	 */


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match
	 *   instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.match.Match.prototype.constructor.call( this, cfg );

		// TODO: if( !serviceName ) throw new Error( '`serviceName` cfg required' );
		if( !cfg.hashtag ) throw new Error( '`hashtag` cfg required' );

		this.serviceName = cfg.serviceName;
		this.hashtag = cfg.hashtag;
	},


	/**
	 * Returns the type of match that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'hashtag';
	},


	/**
	 * Returns the configured {@link #serviceName} to point the Hashtag to.
	 * Ex: 'facebook', 'twitter'.
	 *
	 * @return {String}
	 */
	getServiceName : function() {
		return this.serviceName;
	},


	/**
	 * Returns the matched hashtag, without the '#' character.
	 *
	 * @return {String}
	 */
	getHashtag : function() {
		return this.hashtag;
	},


	/**
	 * Returns the anchor href that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorHref : function() {
		var serviceName = this.serviceName,
		    hashtag = this.hashtag;

		switch( serviceName ) {
			case 'twitter' :
				return 'https://twitter.com/hashtag/' + hashtag;
			case 'facebook' :
				return 'https://www.facebook.com/hashtag/' + hashtag;
			case 'instagram' :
				return 'https://instagram.com/explore/tags/' + hashtag;

			default :  // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case.
				throw new Error( 'Unknown service name to point hashtag to: ', serviceName );
		}
	},


	/**
	 * Returns the anchor text that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorText : function() {
		return '#' + this.hashtag;
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.match.Phone
 * @extends Autolinker.match.Match
 *
 * Represents a Phone number match found in an input string which should be
 * Autolinked.
 *
 * See this class's superclass ({@link Autolinker.match.Match}) for more
 * details.
 */
Autolinker.match.Phone = Autolinker.Util.extend( Autolinker.match.Match, {

	/**
	 * @protected
	 * @property {String} number (required)
	 *
	 * The phone number that was matched, without any delimiter characters.
	 *
	 * Note: This is a string to allow for prefixed 0's.
	 */

	/**
	 * @protected
	 * @property  {Boolean} plusSign (required)
	 *
	 * `true` if the matched phone number started with a '+' sign. We'll include
	 * it in the `tel:` URL if so, as this is needed for international numbers.
	 *
	 * Ex: '+1 (123) 456 7879'
	 */


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match
	 *   instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.match.Match.prototype.constructor.call( this, cfg );

		if( !cfg.number ) throw new Error( '`number` cfg required' );
		if( cfg.plusSign == null ) throw new Error( '`plusSign` cfg required' );

		this.number = cfg.number;
		this.plusSign = cfg.plusSign;
	},


	/**
	 * Returns a string name for the type of match that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'phone';
	},


	/**
	 * Returns the phone number that was matched as a string, without any
	 * delimiter characters.
	 *
	 * Note: This is a string to allow for prefixed 0's.
	 *
	 * @return {String}
	 */
	getNumber: function() {
		return this.number;
	},


	/**
	 * Returns the anchor href that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorHref : function() {
		return 'tel:' + ( this.plusSign ? '+' : '' ) + this.number;
	},


	/**
	 * Returns the anchor text that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorText : function() {
		return this.matchedText;
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.match.Mention
 * @extends Autolinker.match.Match
 *
 * Represents a Mention match found in an input string which should be Autolinked.
 *
 * See this class's superclass ({@link Autolinker.match.Match}) for more details.
 */
Autolinker.match.Mention = Autolinker.Util.extend( Autolinker.match.Match, {

	/**
	 * @cfg {String} serviceName
	 *
	 * The service to point mention matches to. See {@link Autolinker#mention}
	 * for available values.
	 */

	/**
	 * @cfg {String} mention (required)
	 *
	 * The Mention that was matched, without the '@' character.
	 */


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match
	 *   instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.match.Match.prototype.constructor.call( this, cfg );

		if( !cfg.serviceName ) throw new Error( '`serviceName` cfg required' );
		if( !cfg.mention ) throw new Error( '`mention` cfg required' );

		this.mention = cfg.mention;
		this.serviceName = cfg.serviceName;
	},


	/**
	 * Returns the type of match that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'mention';
	},


	/**
	 * Returns the mention, without the '@' character.
	 *
	 * @return {String}
	 */
	getMention : function() {
		return this.mention;
	},


	/**
	 * Returns the configured {@link #serviceName} to point the mention to.
	 * Ex: 'instagram', 'twitter', 'soundcloud'.
	 *
	 * @return {String}
	 */
	getServiceName : function() {
		return this.serviceName;
	},


	/**
	 * Returns the anchor href that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorHref : function() {
		switch( this.serviceName ) {
			case 'twitter' :
				return 'https://twitter.com/' + this.mention;
			case 'instagram' :
				return 'https://instagram.com/' + this.mention;
			case 'soundcloud' :
				return 'https://soundcloud.com/' + this.mention;

			default :  // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case.
				throw new Error( 'Unknown service name to point mention to: ', this.serviceName );
		}
	},


	/**
	 * Returns the anchor text that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorText : function() {
		return '@' + this.mention;
	},


	/**
	 * Returns the CSS class suffixes that should be used on a tag built with
	 * the match. See {@link Autolinker.match.Match#getCssClassSuffixes} for
	 * details.
	 *
	 * @return {String[]}
	 */
	getCssClassSuffixes : function() {
		var cssClassSuffixes = Autolinker.match.Match.prototype.getCssClassSuffixes.call( this ),
		    serviceName = this.getServiceName();

		if( serviceName ) {
			cssClassSuffixes.push( serviceName );
		}
		return cssClassSuffixes;
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.match.Url
 * @extends Autolinker.match.Match
 *
 * Represents a Url match found in an input string which should be Autolinked.
 *
 * See this class's superclass ({@link Autolinker.match.Match}) for more details.
 */
Autolinker.match.Url = Autolinker.Util.extend( Autolinker.match.Match, {

	/**
	 * @cfg {String} url (required)
	 *
	 * The url that was matched.
	 */

	/**
	 * @cfg {"scheme"/"www"/"tld"} urlMatchType (required)
	 *
	 * The type of URL match that this class represents. This helps to determine
	 * if the match was made in the original text with a prefixed scheme (ex:
	 * 'http://www.google.com'), a prefixed 'www' (ex: 'www.google.com'), or
	 * was matched by a known top-level domain (ex: 'google.com').
	 */

	/**
	 * @cfg {Boolean} protocolUrlMatch (required)
	 *
	 * `true` if the URL is a match which already has a protocol (i.e.
	 * 'http://'), `false` if the match was from a 'www' or known TLD match.
	 */

	/**
	 * @cfg {Boolean} protocolRelativeMatch (required)
	 *
	 * `true` if the URL is a protocol-relative match. A protocol-relative match
	 * is a URL that starts with '//', and will be either http:// or https://
	 * based on the protocol that the site is loaded under.
	 */

	/**
	 * @cfg {Object} stripPrefix (required)
	 *
	 * The Object form of {@link Autolinker#cfg-stripPrefix}.
	 */

	/**
	 * @cfg {Boolean} stripTrailingSlash (required)
	 * @inheritdoc Autolinker#cfg-stripTrailingSlash
	 */

	/**
	 * @cfg {Boolean} decodePercentEncoding (required)
	 * @inheritdoc Autolinker#cfg-decodePercentEncoding
	 */

	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match
	 *   instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.match.Match.prototype.constructor.call( this, cfg );

		if( cfg.urlMatchType !== 'scheme' && cfg.urlMatchType !== 'www' && cfg.urlMatchType !== 'tld' ) throw new Error( '`urlMatchType` cfg must be one of: "scheme", "www", or "tld"' );
		if( !cfg.url ) throw new Error( '`url` cfg required' );
		if( cfg.protocolUrlMatch == null ) throw new Error( '`protocolUrlMatch` cfg required' );
		if( cfg.protocolRelativeMatch == null ) throw new Error( '`protocolRelativeMatch` cfg required' );
		if( cfg.stripPrefix == null ) throw new Error( '`stripPrefix` cfg required' );
		if( cfg.stripTrailingSlash == null ) throw new Error( '`stripTrailingSlash` cfg required' );
		if( cfg.decodePercentEncoding == null ) throw new Error( '`decodePercentEncoding` cfg required' );

		this.urlMatchType = cfg.urlMatchType;
		this.url = cfg.url;
		this.protocolUrlMatch = cfg.protocolUrlMatch;
		this.protocolRelativeMatch = cfg.protocolRelativeMatch;
		this.stripPrefix = cfg.stripPrefix;
		this.stripTrailingSlash = cfg.stripTrailingSlash;
		this.decodePercentEncoding = cfg.decodePercentEncoding;
	},


	/**
	 * @private
	 * @property {RegExp} schemePrefixRegex
	 *
	 * A regular expression used to remove the 'http://' or 'https://' from
	 * URLs.
	 */
	schemePrefixRegex: /^(https?:\/\/)?/i,

	/**
	 * @private
	 * @property {RegExp} wwwPrefixRegex
	 *
	 * A regular expression used to remove the 'www.' from URLs.
	 */
	wwwPrefixRegex: /^(https?:\/\/)?(www\.)?/i,

	/**
	 * @private
	 * @property {RegExp} protocolRelativeRegex
	 *
	 * The regular expression used to remove the protocol-relative '//' from the {@link #url} string, for purposes
	 * of {@link #getAnchorText}. A protocol-relative URL is, for example, "//yahoo.com"
	 */
	protocolRelativeRegex : /^\/\//,

	/**
	 * @private
	 * @property {Boolean} protocolPrepended
	 *
	 * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the
	 * {@link #url} did not have a protocol)
	 */
	protocolPrepended : false,


	/**
	 * Returns a string name for the type of match that this class represents.
	 *
	 * @return {String}
	 */
	getType : function() {
		return 'url';
	},


	/**
	 * Returns a string name for the type of URL match that this class
	 * represents.
	 *
	 * This helps to determine if the match was made in the original text with a
	 * prefixed scheme (ex: 'http://www.google.com'), a prefixed 'www' (ex:
	 * 'www.google.com'), or was matched by a known top-level domain (ex:
	 * 'google.com').
	 *
	 * @return {"scheme"/"www"/"tld"}
	 */
	getUrlMatchType : function() {
		return this.urlMatchType;
	},


	/**
	 * Returns the url that was matched, assuming the protocol to be 'http://' if the original
	 * match was missing a protocol.
	 *
	 * @return {String}
	 */
	getUrl : function() {
		var url = this.url;

		// if the url string doesn't begin with a protocol, assume 'http://'
		if( !this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended ) {
			url = this.url = 'http://' + url;

			this.protocolPrepended = true;
		}

		return url;
	},


	/**
	 * Returns the anchor href that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorHref : function() {
		var url = this.getUrl();

		return url.replace( /&amp;/g, '&' );  // any &amp;'s in the URL should be converted back to '&' if they were displayed as &amp; in the source html
	},


	/**
	 * Returns the anchor text that should be generated for the match.
	 *
	 * @return {String}
	 */
	getAnchorText : function() {
		var anchorText = this.getMatchedText();

		if( this.protocolRelativeMatch ) {
			// Strip off any protocol-relative '//' from the anchor text
			anchorText = this.stripProtocolRelativePrefix( anchorText );
		}
		if( this.stripPrefix.scheme ) {
			anchorText = this.stripSchemePrefix( anchorText );
		}
		if( this.stripPrefix.www ) {
			anchorText = this.stripWwwPrefix( anchorText );
		}
		if( this.stripTrailingSlash ) {
			anchorText = this.removeTrailingSlash( anchorText );  // remove trailing slash, if there is one
		}
		if( this.decodePercentEncoding ) {
			anchorText = this.removePercentEncoding( anchorText);
		}

		return anchorText;
	},


	// ---------------------------------------

	// Utility Functionality

	/**
	 * Strips the scheme prefix (such as "http://" or "https://") from the given
	 * `url`.
	 *
	 * @private
	 * @param {String} url The text of the anchor that is being generated, for
	 *   which to strip off the url scheme.
	 * @return {String} The `url`, with the scheme stripped.
	 */
	stripSchemePrefix : function( url ) {
		return url.replace( this.schemePrefixRegex, '' );
	},


	/**
	 * Strips the 'www' prefix from the given `url`.
	 *
	 * @private
	 * @param {String} url The text of the anchor that is being generated, for
	 *   which to strip off the 'www' if it exists.
	 * @return {String} The `url`, with the 'www' stripped.
	 */
	stripWwwPrefix : function( url ) {
		return url.replace( this.wwwPrefixRegex, '$1' );  // leave any scheme ($1), it one exists
	},


	/**
	 * Strips any protocol-relative '//' from the anchor text.
	 *
	 * @private
	 * @param {String} text The text of the anchor that is being generated, for which to strip off the
	 *   protocol-relative prefix (such as stripping off "//")
	 * @return {String} The `anchorText`, with the protocol-relative prefix stripped.
	 */
	stripProtocolRelativePrefix : function( text ) {
		return text.replace( this.protocolRelativeRegex, '' );
	},


	/**
	 * Removes any trailing slash from the given `anchorText`, in preparation for the text to be displayed.
	 *
	 * @private
	 * @param {String} anchorText The text of the anchor that is being generated, for which to remove any trailing
	 *   slash ('/') that may exist.
	 * @return {String} The `anchorText`, with the trailing slash removed.
	 */
	removeTrailingSlash : function( anchorText ) {
		if( anchorText.charAt( anchorText.length - 1 ) === '/' ) {
			anchorText = anchorText.slice( 0, -1 );
		}
		return anchorText;
	},

	/**
	 * Decodes percent-encoded characters from the given `anchorText`, in preparation for the text to be displayed.
	 *
	 * @private
	 * @param {String} anchorText The text of the anchor that is being generated, for which to decode any percent-encoded characters.
	 * @return {String} The `anchorText`, with the percent-encoded characters decoded.
	 */
	removePercentEncoding : function( anchorText ) {
		try {
			return decodeURIComponent( anchorText
				.replace( /%22/gi, '&quot;' )
				.replace( /%26/gi, '&amp;' )
				.replace( /%27/gi, '&#39;')
				.replace( /%3C/gi, '&lt;' )
				.replace( /%3E/gi, '&gt;' )
			 );
		} catch (e) {
			// Invalid escape sequence.
			return anchorText;
		}
	}

} );
// NOTE: THIS IS A GENERATED FILE
// To update with the latest TLD list, run `gulp update-tld-list`

/*global Autolinker */
Autolinker.tldRegex = /(?:xn--vermgensberatung-pwb|xn--vermgensberater-ctb|xn--clchc0ea0b2g2a9gcd|xn--w4r85el8fhu5dnra|northwesternmutual|travelersinsurance|vermögensberatung|xn--3oq18vl8pn36a|xn--5su34j936bgsg|xn--bck1b9a5dre4c|xn--mgbai9azgqp6j|xn--mgberp4a5d4ar|xn--xkc2dl3a5ee0h|vermögensberater|xn--fzys8d69uvgm|xn--mgba7c0bbn0a|xn--xkc2al3hye2a|americanexpress|kerryproperties|sandvikcoromant|xn--i1b6b1a6a2e|xn--kcrx77d1x4a|xn--lgbbat1ad8j|xn--mgba3a4f16a|xn--mgbc0a9azcg|xn--nqv7fs00ema|afamilycompany|americanfamily|bananarepublic|cancerresearch|cookingchannel|kerrylogistics|weatherchannel|xn--54b7fta0cc|xn--6qq986b3xl|xn--80aqecdr1a|xn--b4w605ferd|xn--fiq228c5hs|xn--jlq61u9w7b|xn--mgba3a3ejt|xn--mgbaam7a8h|xn--mgbayh7gpa|xn--mgbb9fbpob|xn--mgbbh1a71e|xn--mgbca7dzdo|xn--mgbi4ecexp|xn--mgbx4cd0ab|international|lifeinsurance|orientexpress|spreadbetting|travelchannel|wolterskluwer|xn--eckvdtc9d|xn--fpcrj9c3d|xn--fzc2c9e2c|xn--tiq49xqyj|xn--yfro4i67o|xn--ygbi2ammx|construction|lplfinancial|pamperedchef|scholarships|versicherung|xn--3e0b707e|xn--80adxhks|xn--80asehdb|xn--8y0a063a|xn--gckr3f0f|xn--mgb9awbf|xn--mgbab2bd|xn--mgbpl2fh|xn--mgbt3dhd|xn--mk1bu44c|xn--ngbc5azd|xn--ngbe9e0a|xn--ogbpf8fl|xn--qcka1pmc|accountants|barclaycard|blackfriday|blockbuster|bridgestone|calvinklein|contractors|creditunion|engineering|enterprises|foodnetwork|investments|kerryhotels|lamborghini|motorcycles|olayangroup|photography|playstation|productions|progressive|redumbrella|rightathome|williamhill|xn--11b4c3d|xn--1ck2e1b|xn--1qqw23a|xn--3bst00m|xn--3ds443g|xn--42c2d9a|xn--45brj9c|xn--55qw42g|xn--6frz82g|xn--80ao21a|xn--9krt00a|xn--cck2b3b|xn--czr694b|xn--d1acj3b|xn--efvy88h|xn--estv75g|xn--fct429k|xn--fjq720a|xn--flw351e|xn--g2xx48c|xn--gecrj9c|xn--gk3at1e|xn--h2brj9c|xn--hxt814e|xn--imr513n|xn--j6w193g|xn--jvr189m|xn--kprw13d|xn--kpry57d|xn--kpu716f|xn--mgbtx2b|xn--mix891f|xn--nyqy26a|xn--pbt977c|xn--pgbs0dh|xn--q9jyb4c|xn--rhqv96g|xn--rovu88b|xn--s9brj9c|xn--ses554g|xn--t60b56a|xn--vuq861b|xn--w4rs40l|xn--xhq521b|xn--zfr164b|சிங்கப்பூர்|accountant|apartments|associates|basketball|bnpparibas|boehringer|capitalone|consulting|creditcard|cuisinella|eurovision|extraspace|foundation|healthcare|immobilien|industries|management|mitsubishi|nationwide|newholland|nextdirect|onyourside|properties|protection|prudential|realestate|republican|restaurant|schaeffler|swiftcover|tatamotors|technology|telefonica|university|vistaprint|vlaanderen|volkswagen|xn--30rr7y|xn--3pxu8k|xn--45q11c|xn--4gbrim|xn--55qx5d|xn--5tzm5g|xn--80aswg|xn--90a3ac|xn--9dbq2a|xn--9et52u|xn--c2br7g|xn--cg4bki|xn--czrs0t|xn--czru2d|xn--fiq64b|xn--fiqs8s|xn--fiqz9s|xn--io0a7i|xn--kput3i|xn--mxtq1m|xn--o3cw4h|xn--pssy2u|xn--unup4y|xn--wgbh1c|xn--wgbl6a|xn--y9a3aq|accenture|alfaromeo|allfinanz|amsterdam|analytics|aquarelle|barcelona|bloomberg|christmas|community|directory|education|equipment|fairwinds|financial|firestone|fresenius|frontdoor|fujixerox|furniture|goldpoint|goodhands|hisamitsu|homedepot|homegoods|homesense|honeywell|institute|insurance|kuokgroup|ladbrokes|lancaster|landrover|lifestyle|marketing|marshalls|mcdonalds|melbourne|microsoft|montblanc|panasonic|passagens|pramerica|richardli|scjohnson|shangrila|solutions|statebank|statefarm|stockholm|travelers|vacations|xn--90ais|xn--c1avg|xn--d1alf|xn--e1a4c|xn--fhbei|xn--j1aef|xn--j1amh|xn--l1acc|xn--nqv7f|xn--p1acf|xn--tckwe|xn--vhquv|yodobashi|abudhabi|airforce|allstate|attorney|barclays|barefoot|bargains|baseball|boutique|bradesco|broadway|brussels|budapest|builders|business|capetown|catering|catholic|chrysler|cipriani|cityeats|cleaning|clinique|clothing|commbank|computer|delivery|deloitte|democrat|diamonds|discount|discover|download|engineer|ericsson|esurance|everbank|exchange|feedback|fidelity|firmdale|football|frontier|goodyear|grainger|graphics|guardian|hdfcbank|helsinki|holdings|hospital|infiniti|ipiranga|istanbul|jpmorgan|lighting|lundbeck|marriott|maserati|mckinsey|memorial|mortgage|movistar|observer|partners|pharmacy|pictures|plumbing|property|redstone|reliance|saarland|samsclub|security|services|shopping|showtime|softbank|software|stcgroup|supplies|symantec|telecity|training|uconnect|vanguard|ventures|verisign|woodside|xn--90ae|xn--node|xn--p1ai|xn--qxam|yokohama|السعودية|abogado|academy|agakhan|alibaba|android|athleta|auction|audible|auspost|avianca|banamex|bauhaus|bentley|bestbuy|booking|brother|bugatti|capital|caravan|careers|cartier|channel|chintai|citadel|clubmed|college|cologne|comcast|company|compare|contact|cooking|corsica|country|coupons|courses|cricket|cruises|dentist|digital|domains|exposed|express|farmers|fashion|ferrari|ferrero|finance|fishing|fitness|flights|florist|flowers|forsale|frogans|fujitsu|gallery|genting|godaddy|guitars|hamburg|hangout|hitachi|holiday|hosting|hoteles|hotmail|hyundai|iselect|ismaili|jewelry|juniper|kitchen|komatsu|lacaixa|lancome|lanxess|lasalle|latrobe|leclerc|liaison|limited|lincoln|markets|metlife|monster|netbank|netflix|network|neustar|okinawa|oldnavy|organic|origins|panerai|philips|pioneer|politie|realtor|recipes|rentals|reviews|rexroth|samsung|sandvik|schmidt|schwarz|science|shiksha|shriram|singles|spiegel|staples|starhub|statoil|storage|support|surgery|systems|temasek|theater|theatre|tickets|tiffany|toshiba|trading|walmart|wanggou|watches|weather|website|wedding|whoswho|windows|winners|xfinity|yamaxun|youtube|zuerich|католик|الجزائر|العليان|پاکستان|كاثوليك|موبايلي|இந்தியா|abarth|abbott|abbvie|active|africa|agency|airbus|airtel|alipay|alsace|alstom|anquan|aramco|author|bayern|beauty|berlin|bharti|blanco|bostik|boston|broker|camera|career|caseih|casino|center|chanel|chrome|church|circle|claims|clinic|coffee|comsec|condos|coupon|credit|cruise|dating|datsun|dealer|degree|dental|design|direct|doctor|dunlop|dupont|durban|emerck|energy|estate|events|expert|family|flickr|futbol|gallup|garden|george|giving|global|google|gratis|health|hermes|hiphop|hockey|hughes|imamat|insure|intuit|jaguar|joburg|juegos|kaufen|kinder|kindle|kosher|lancia|latino|lawyer|lefrak|living|locker|london|luxury|madrid|maison|makeup|market|mattel|mobile|mobily|monash|mormon|moscow|museum|mutual|nagoya|natura|nissan|nissay|norton|nowruz|office|olayan|online|oracle|orange|otsuka|pfizer|photos|physio|piaget|pictet|quebec|racing|realty|reisen|repair|report|review|rocher|rogers|ryukyu|safety|sakura|sanofi|school|schule|secure|select|shouji|soccer|social|stream|studio|supply|suzuki|swatch|sydney|taipei|taobao|target|tattoo|tennis|tienda|tjmaxx|tkmaxx|toyota|travel|unicom|viajes|viking|villas|virgin|vision|voting|voyage|vuelos|walter|warman|webcam|xihuan|xperia|yachts|yandex|zappos|москва|онлайн|ابوظبي|ارامكو|الاردن|المغرب|امارات|فلسطين|مليسيا|இலங்கை|ファッション|actor|adult|aetna|amfam|amica|apple|archi|audio|autos|azure|baidu|beats|bible|bingo|black|boats|boots|bosch|build|canon|cards|chase|cheap|chloe|cisco|citic|click|cloud|coach|codes|crown|cymru|dabur|dance|deals|delta|dodge|drive|dubai|earth|edeka|email|epost|epson|faith|fedex|final|forex|forum|gallo|games|gifts|gives|glade|glass|globo|gmail|green|gripe|group|gucci|guide|homes|honda|horse|house|hyatt|ikano|intel|irish|iveco|jetzt|koeln|kyoto|lamer|lease|legal|lexus|lilly|linde|lipsy|lixil|loans|locus|lotte|lotto|lupin|macys|mango|media|miami|money|mopar|movie|nadex|nexus|nikon|ninja|nokia|nowtv|omega|osaka|paris|parts|party|phone|photo|pizza|place|poker|praxi|press|prime|promo|quest|radio|rehab|reise|ricoh|rocks|rodeo|salon|sener|seven|sharp|shell|shoes|skype|sling|smart|smile|solar|space|stada|store|study|style|sucks|swiss|tatar|tires|tirol|tmall|today|tokyo|tools|toray|total|tours|trade|trust|tunes|tushu|ubank|vegas|video|vista|vodka|volvo|wales|watch|weber|weibo|works|world|xerox|yahoo|zippo|ایران|بازار|بھارت|سودان|سورية|همراه|संगठन|বাংলা|భారత్|嘉里大酒店|aarp|able|adac|aero|aigo|akdn|ally|amex|army|arpa|arte|asda|asia|audi|auto|baby|band|bank|bbva|beer|best|bike|bing|blog|blue|bofa|bond|book|buzz|cafe|call|camp|care|cars|casa|case|cash|cbre|cern|chat|citi|city|club|cool|coop|cyou|data|date|dclk|deal|dell|desi|diet|dish|docs|doha|duck|duns|dvag|erni|fage|fail|fans|farm|fast|fiat|fido|film|fire|fish|flir|food|ford|free|fund|game|gbiz|gent|ggee|gift|gmbh|gold|golf|goog|guge|guru|hair|haus|hdfc|help|here|hgtv|host|hsbc|icbc|ieee|imdb|immo|info|itau|java|jeep|jobs|jprs|kddi|kiwi|kpmg|kred|land|lego|lgbt|lidl|life|like|limo|link|live|loan|loft|love|ltda|luxe|maif|meet|meme|menu|mini|mint|mobi|moda|moto|mtpc|name|navy|news|next|nico|nike|ollo|open|page|pars|pccw|pics|ping|pink|play|plus|pohl|porn|post|prod|prof|qpon|raid|read|reit|rent|rest|rich|rmit|room|rsvp|ruhr|safe|sale|sapo|sarl|save|saxo|scor|scot|seat|seek|sexy|shaw|shia|shop|show|silk|sina|site|skin|sncf|sohu|song|sony|spot|star|surf|talk|taxi|team|tech|teva|tiaa|tips|town|toys|tube|vana|visa|viva|vivo|vote|voto|wang|weir|wien|wiki|wine|work|xbox|yoga|zara|zero|zone|дети|сайт|بيتك|تونس|شبكة|عراق|عمان|موقع|भारत|ভারত|ਭਾਰਤ|ભારત|ලංකා|グーグル|クラウド|ポイント|大众汽车|组织机构|電訊盈科|香格里拉|aaa|abb|abc|aco|ads|aeg|afl|aig|anz|aol|app|art|aws|axa|bar|bbc|bbt|bcg|bcn|bet|bid|bio|biz|bms|bmw|bnl|bom|boo|bot|box|buy|bzh|cab|cal|cam|car|cat|cba|cbn|cbs|ceb|ceo|cfa|cfd|com|crs|csc|dad|day|dds|dev|dhl|diy|dnp|dog|dot|dtv|dvr|eat|eco|edu|esq|eus|fan|fit|fly|foo|fox|frl|ftr|fun|fyi|gal|gap|gdn|gea|gle|gmo|gmx|goo|gop|got|gov|hbo|hiv|hkt|hot|how|htc|ibm|ice|icu|ifm|ing|ink|int|ist|itv|iwc|jcb|jcp|jio|jlc|jll|jmp|jnj|jot|joy|kfh|kia|kim|kpn|krd|lat|law|lds|lol|lpl|ltd|man|mba|mcd|med|men|meo|mil|mit|mlb|mls|mma|moe|moi|mom|mov|msd|mtn|mtr|nab|nba|nec|net|new|nfl|ngo|nhk|now|nra|nrw|ntt|nyc|obi|off|one|ong|onl|ooo|org|ott|ovh|pay|pet|pid|pin|pnc|pro|pru|pub|pwc|qvc|red|ren|ril|rio|rip|run|rwe|sap|sas|sbi|sbs|sca|scb|ses|sew|sex|sfr|ski|sky|soy|srl|srt|stc|tab|tax|tci|tdk|tel|thd|tjx|top|trv|tui|tvs|ubs|uno|uol|ups|vet|vig|vin|vip|wed|win|wme|wow|wtc|wtf|xin|xxx|xyz|you|yun|zip|бел|ком|қаз|мкд|мон|орг|рус|срб|укр|հայ|קום|قطر|كوم|مصر|कॉम|नेट|คอม|ไทย|ストア|セール|みんな|中文网|天主教|我爱你|新加坡|淡马锡|诺基亚|飞利浦|ac|ad|ae|af|ag|ai|al|am|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|ελ|бг|ею|рф|გე|닷넷|닷컴|삼성|한국|コム|世界|中信|中国|中國|企业|佛山|信息|健康|八卦|公司|公益|台湾|台灣|商城|商店|商标|嘉里|在线|大拿|娱乐|家電|工行|广东|微博|慈善|手机|手表|政务|政府|新闻|时尚|書籍|机构|游戏|澳門|点看|珠宝|移动|网址|网店|网站|网络|联通|谷歌|购物|通販|集团|食品|餐厅|香港)/;

/*global Autolinker */
/**
 * @abstract
 * @class Autolinker.matcher.Matcher
 *
 * An abstract class and interface for individual matchers to find matches in
 * an input string with linkified versions of them.
 *
 * Note that Matchers do not take HTML into account - they must be fed the text
 * nodes of any HTML string, which is handled by {@link Autolinker#parse}.
 */
Autolinker.matcher.Matcher = Autolinker.Util.extend( Object, {

	/**
	 * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required)
	 *
	 * Reference to the AnchorTagBuilder instance to use to generate HTML tags
	 * for {@link Autolinker.match.Match Matches}.
	 */


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Matcher
	 *   instance, specified in an Object (map).
	 */
	constructor : function( cfg ) {
		if( !cfg.tagBuilder ) throw new Error( '`tagBuilder` cfg required' );

		this.tagBuilder = cfg.tagBuilder;
	},


	/**
	 * Parses the input `text` and returns the array of {@link Autolinker.match.Match Matches}
	 * for the matcher.
	 *
	 * @abstract
	 * @param {String} text The text to scan and replace matches in.
	 * @return {Autolinker.match.Match[]}
	 */
	parseMatches : Autolinker.Util.abstractMethod

} );
/*global Autolinker */
/**
 * @class Autolinker.matcher.Email
 * @extends Autolinker.matcher.Matcher
 *
 * Matcher to find email matches in an input string.
 *
 * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details.
 */
Autolinker.matcher.Email = Autolinker.Util.extend( Autolinker.matcher.Matcher, {

	/**
	 * The regular expression to match email addresses. Example match:
	 *
	 *     person@place.com
	 *
	 * @private
	 * @property {RegExp} matcherRegex
	 */
	matcherRegex : (function() {
		var alphaNumericChars = Autolinker.RegexLib.alphaNumericCharsStr,
			specialCharacters = '!#$%&\'*+\\-\\/=?^_`{|}~',
			restrictedSpecialCharacters = '\\s"(),:;<>@\\[\\]',
			validCharacters = alphaNumericChars + specialCharacters,
			validRestrictedCharacters = validCharacters + restrictedSpecialCharacters,
		    emailRegex = new RegExp( '(?:[' + validCharacters + '](?:[' + validCharacters + ']|\\.(?!\\.|@))*|\\"[' + validRestrictedCharacters + '.]+\\")@'),
			getDomainNameStr = Autolinker.RegexLib.getDomainNameStr,
			tldRegex = Autolinker.tldRegex;  // match our known top level domains (TLDs)

		return new RegExp( [
			emailRegex.source,
			getDomainNameStr(1),
			'\\.', tldRegex.source   // '.com', '.net', etc
		].join( "" ), 'gi' );
	} )(),


	/**
	 * @inheritdoc
	 */
	parseMatches : function( text ) {
		var matcherRegex = this.matcherRegex,
		    tagBuilder = this.tagBuilder,
		    matches = [],
		    match;

		while( ( match = matcherRegex.exec( text ) ) !== null ) {
			var matchedText = match[ 0 ];

			matches.push( new Autolinker.match.Email( {
				tagBuilder  : tagBuilder,
				matchedText : matchedText,
				offset      : match.index,
				email       : matchedText
			} ) );
		}

		return matches;
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.matcher.Hashtag
 * @extends Autolinker.matcher.Matcher
 *
 * Matcher to find Hashtag matches in an input string.
 */
Autolinker.matcher.Hashtag = Autolinker.Util.extend( Autolinker.matcher.Matcher, {

	/**
	 * @cfg {String} serviceName
	 *
	 * The service to point hashtag matches to. See {@link Autolinker#hashtag}
	 * for available values.
	 */


	/**
	 * The regular expression to match Hashtags. Example match:
	 *
	 *     #asdf
	 *
	 * @private
	 * @property {RegExp} matcherRegex
	 */
	matcherRegex : new RegExp( '#[_' + Autolinker.RegexLib.alphaNumericCharsStr + ']{1,139}', 'g' ),

	/**
	 * The regular expression to use to check the character before a username match to
	 * make sure we didn't accidentally match an email address.
	 *
	 * For example, the string "asdf@asdf.com" should not match "@asdf" as a username.
	 *
	 * @private
	 * @property {RegExp} nonWordCharRegex
	 */
	nonWordCharRegex : new RegExp( '[^' + Autolinker.RegexLib.alphaNumericCharsStr + ']' ),


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match instance,
	 *   specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.matcher.Matcher.prototype.constructor.call( this, cfg );

		this.serviceName = cfg.serviceName;
	},


	/**
	 * @inheritdoc
	 */
	parseMatches : function( text ) {
		var matcherRegex = this.matcherRegex,
		    nonWordCharRegex = this.nonWordCharRegex,
		    serviceName = this.serviceName,
		    tagBuilder = this.tagBuilder,
		    matches = [],
		    match;

		while( ( match = matcherRegex.exec( text ) ) !== null ) {
			var offset = match.index,
			    prevChar = text.charAt( offset - 1 );

			// If we found the match at the beginning of the string, or we found the match
			// and there is a whitespace char in front of it (meaning it is not a '#' char
			// in the middle of a word), then it is a hashtag match.
			if( offset === 0 || nonWordCharRegex.test( prevChar ) ) {
				var matchedText = match[ 0 ],
				    hashtag = match[ 0 ].slice( 1 );  // strip off the '#' character at the beginning

				matches.push( new Autolinker.match.Hashtag( {
					tagBuilder  : tagBuilder,
					matchedText : matchedText,
					offset      : offset,
					serviceName : serviceName,
					hashtag     : hashtag
				} ) );
			}
		}

		return matches;
	}

} );
/*global Autolinker */
/**
 * @class Autolinker.matcher.Phone
 * @extends Autolinker.matcher.Matcher
 *
 * Matcher to find Phone number matches in an input string.
 *
 * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more
 * details.
 */
Autolinker.matcher.Phone = Autolinker.Util.extend( Autolinker.matcher.Matcher, {

	/**
	 * The regular expression to match Phone numbers. Example match:
	 *
	 *     (123) 456-7890
	 *
	 * This regular expression has the following capturing groups:
	 *
	 * 1 or 2. The prefixed '+' sign, if there is one.
	 *
	 * @private
	 * @property {RegExp} matcherRegex
	 */
	matcherRegex : /(?:(?:(?:(\+)?\d{1,3}[-\040.]?)?\(?\d{3}\)?[-\040.]?\d{3}[-\040.]?\d{4})|(?:(\+)(?:9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)[-\040.]?(?:\d[-\040.]?){6,12}\d+))([,;]+[0-9]+#?)*/g,

	// ex: (123) 456-7890, 123 456 7890, 123-456-7890, +18004441234,,;,10226420346#,
	// +1 (800) 444 1234, 10226420346#, 1-800-444-1234,1022,64,20346#

	/**
	 * @inheritdoc
	 */
	parseMatches: function(text) {
		var matcherRegex = this.matcherRegex,
			tagBuilder = this.tagBuilder,
			matches = [],
			match;

		while ((match = matcherRegex.exec(text)) !== null) {
			// Remove non-numeric values from phone number string
			var matchedText = match[0],
				cleanNumber = matchedText.replace(/[^0-9,;#]/g, ''), // strip out non-digit characters exclude comma semicolon and #
				plusSign = !!(match[1] || match[2]), // match[ 1 ] or match[ 2 ] is the prefixed plus sign, if there is one
				before = match.index == 0 ? '' : text.substr(match.index - 1, 1),
				after = text.substr(match.index + matchedText.length, 1),
				contextClear = !before.match(/\d/) && !after.match(/\d/);

			if (this.testMatch(match[3]) && this.testMatch(matchedText) && contextClear) {
				matches.push(new Autolinker.match.Phone({
					tagBuilder: tagBuilder,
					matchedText: matchedText,
					offset: match.index,
					number: cleanNumber,
					plusSign: plusSign
				}));
			}
		}

		return matches;
	},

	testMatch: function(text) {
		return /\D/.test(text);
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.matcher.Mention
 * @extends Autolinker.matcher.Matcher
 *
 * Matcher to find/replace username matches in an input string.
 */
Autolinker.matcher.Mention = Autolinker.Util.extend( Autolinker.matcher.Matcher, {

	/**
	 * Hash of regular expression to match username handles. Example match:
	 *
	 *     @asdf
	 *
	 * @private
	 * @property {Object} matcherRegexes
	 */
	matcherRegexes : {
		"twitter": new RegExp( '@[_' + Autolinker.RegexLib.alphaNumericCharsStr + ']{1,20}', 'g' ),
		"instagram": new RegExp( '@[_.' + Autolinker.RegexLib.alphaNumericCharsStr + ']{1,50}', 'g' ),
		"soundcloud": new RegExp( '@[_.' + Autolinker.RegexLib.alphaNumericCharsStr + "\-" + ']{1,50}', 'g' )
	},

	/**
	 * The regular expression to use to check the character before a username match to
	 * make sure we didn't accidentally match an email address.
	 *
	 * For example, the string "asdf@asdf.com" should not match "@asdf" as a username.
	 *
	 * @private
	 * @property {RegExp} nonWordCharRegex
	 */
	nonWordCharRegex : new RegExp( '[^' + Autolinker.RegexLib.alphaNumericCharsStr + ']' ),


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match instance,
	 *   specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.matcher.Matcher.prototype.constructor.call( this, cfg );

		this.serviceName = cfg.serviceName;
	},


	/**
	 * @inheritdoc
	 */
	parseMatches : function( text ) {
		var matcherRegex = this.matcherRegexes[this.serviceName],
		    nonWordCharRegex = this.nonWordCharRegex,
		    serviceName = this.serviceName,
		    tagBuilder = this.tagBuilder,
		    matches = [],
		    match;

		if (!matcherRegex) {
			return matches;
		}

		while( ( match = matcherRegex.exec( text ) ) !== null ) {
			var offset = match.index,
			    prevChar = text.charAt( offset - 1 );

			// If we found the match at the beginning of the string, or we found the match
			// and there is a whitespace char in front of it (meaning it is not an email
			// address), then it is a username match.
			if( offset === 0 || nonWordCharRegex.test( prevChar ) ) {
				var matchedText = match[ 0 ].replace(/\.+$/g, ''), // strip off trailing .
				    mention = matchedText.slice( 1 );  // strip off the '@' character at the beginning

				matches.push( new Autolinker.match.Mention( {
					tagBuilder    : tagBuilder,
					matchedText   : matchedText,
					offset        : offset,
					serviceName   : serviceName,
					mention       : mention
				} ) );
			}
		}

		return matches;
	}

} );

/*global Autolinker */
/**
 * @class Autolinker.matcher.Url
 * @extends Autolinker.matcher.Matcher
 *
 * Matcher to find URL matches in an input string.
 *
 * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details.
 */
Autolinker.matcher.Url = Autolinker.Util.extend( Autolinker.matcher.Matcher, {

	/**
	 * @cfg {Object} stripPrefix (required)
	 *
	 * The Object form of {@link Autolinker#cfg-stripPrefix}.
	 */

	/**
	 * @cfg {Boolean} stripTrailingSlash (required)
	 * @inheritdoc Autolinker#stripTrailingSlash
	 */

	/**
	 * @cfg {Boolean} decodePercentEncoding (required)
	 * @inheritdoc Autolinker#decodePercentEncoding
	 */


	/**
	 * @private
	 * @property {RegExp} matcherRegex
	 *
	 * The regular expression to match URLs with an optional scheme, port
	 * number, path, query string, and hash anchor.
	 *
	 * Example matches:
	 *
	 *     http://google.com
	 *     www.google.com
	 *     google.com/path/to/file?q1=1&q2=2#myAnchor
	 *
	 *
	 * This regular expression will have the following capturing groups:
	 *
	 * 1.  Group that matches a scheme-prefixed URL (i.e. 'http://google.com').
	 *     This is used to match scheme URLs with just a single word, such as
	 *     'http://localhost', where we won't double check that the domain name
	 *     has at least one dot ('.') in it.
	 * 2.  Group that matches a 'www.' prefixed URL. This is only matched if the
	 *     'www.' text was not prefixed by a scheme (i.e.: not prefixed by
	 *     'http://', 'ftp:', etc.)
	 * 3.  A protocol-relative ('//') match for the case of a 'www.' prefixed
	 *     URL. Will be an empty string if it is not a protocol-relative match.
	 *     We need to know the character before the '//' in order to determine
	 *     if it is a valid match or the // was in a string we don't want to
	 *     auto-link.
	 * 4.  Group that matches a known TLD (top level domain), when a scheme
	 *     or 'www.'-prefixed domain is not matched.
	 * 5.  A protocol-relative ('//') match for the case of a known TLD prefixed
	 *     URL. Will be an empty string if it is not a protocol-relative match.
	 *     See #3 for more info.
	 */
	matcherRegex : (function() {
		var schemeRegex = /(?:[A-Za-z][-.+A-Za-z0-9]{0,63}:(?![A-Za-z][-.+A-Za-z0-9]{0,63}:\/\/)(?!\d+\/?)(?:\/\/)?)/,  // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex)
		    wwwRegex = /(?:www\.)/,                  // starting with 'www.'
		    getDomainNameStr = Autolinker.RegexLib.getDomainNameStr,
		    tldRegex = Autolinker.tldRegex,  // match our known top level domains (TLDs)
		    alphaNumericCharsStr = Autolinker.RegexLib.alphaNumericCharsStr,

		    // Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;"
		    // http://blog.codinghorror.com/the-problem-with-urls/
		    urlSuffixRegex = new RegExp( '[/?#](?:[' + alphaNumericCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]?!:,.;\u2713]*[' + alphaNumericCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]\u2713])?' );

		return new RegExp( [
			'(?:', // parens to cover match for scheme (optional), and domain
				'(',  // *** Capturing group $1, for a scheme-prefixed url (ex: http://google.com)
					schemeRegex.source,
					getDomainNameStr(2),
				')',

				'|',

				'(',  // *** Capturing group $4 for a 'www.' prefixed url (ex: www.google.com)
					'(//)?',  // *** Capturing group $5 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character (handled later)
					wwwRegex.source,
					getDomainNameStr(6),
				')',

				'|',

				'(',  // *** Capturing group $8, for known a TLD url (ex: google.com)
					'(//)?',  // *** Capturing group $9 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character (handled later)
					getDomainNameStr(10) + '\\.',
					tldRegex.source,
					'(?![-' + alphaNumericCharsStr + '])', // TLD not followed by a letter, behaves like unicode-aware \b
				')',
			')',

			'(?::[0-9]+)?', // port

			'(?:' + urlSuffixRegex.source + ')?'  // match for path, query string, and/or hash anchor - optional
		].join( "" ), 'gi' );
	} )(),


	/**
	 * A regular expression to use to check the character before a protocol-relative
	 * URL match. We don't want to match a protocol-relative URL if it is part
	 * of another word.
	 *
	 * For example, we want to match something like "Go to: //google.com",
	 * but we don't want to match something like "abc//google.com"
	 *
	 * This regular expression is used to test the character before the '//'.
	 *
	 * @private
	 * @type {RegExp} wordCharRegExp
	 */
	wordCharRegExp : new RegExp( '[' + Autolinker.RegexLib.alphaNumericCharsStr + ']' ),


	/**
	 * The regular expression to match opening parenthesis in a URL match.
	 *
	 * This is to determine if we have unbalanced parenthesis in the URL, and to
	 * drop the final parenthesis that was matched if so.
	 *
	 * Ex: The text "(check out: wikipedia.com/something_(disambiguation))"
	 * should only autolink the inner "wikipedia.com/something_(disambiguation)"
	 * part, so if we find that we have unbalanced parenthesis, we will drop the
	 * last one for the match.
	 *
	 * @private
	 * @property {RegExp}
	 */
	openParensRe : /\(/g,

	/**
	 * The regular expression to match closing parenthesis in a URL match. See
	 * {@link #openParensRe} for more information.
	 *
	 * @private
	 * @property {RegExp}
	 */
	closeParensRe : /\)/g,


	/**
	 * @constructor
	 * @param {Object} cfg The configuration properties for the Match instance,
	 *   specified in an Object (map).
	 */
	constructor : function( cfg ) {
		Autolinker.matcher.Matcher.prototype.constructor.call( this, cfg );

		if( cfg.stripPrefix == null ) throw new Error( '`stripPrefix` cfg required' );
		if( cfg.stripTrailingSlash == null ) throw new Error( '`stripTrailingSlash` cfg required' );

		this.stripPrefix = cfg.stripPrefix;
		this.stripTrailingSlash = cfg.stripTrailingSlash;
		this.decodePercentEncoding = cfg.decodePercentEncoding;
	},


	/**
	 * @inheritdoc
	 */
	parseMatches : function( text ) {
		var matcherRegex = this.matcherRegex,
		    stripPrefix = this.stripPrefix,
		    stripTrailingSlash = this.stripTrailingSlash,
		    decodePercentEncoding = this.decodePercentEncoding,
		    tagBuilder = this.tagBuilder,
		    matches = [],
		    match;

		while( ( match = matcherRegex.exec( text ) ) !== null ) {
			var matchStr = match[ 0 ],
			    schemeUrlMatch = match[ 1 ],
			    wwwUrlMatch = match[ 4 ],
			    wwwProtocolRelativeMatch = match[ 5 ],
			    //tldUrlMatch = match[ 8 ],  -- not needed at the moment
			    tldProtocolRelativeMatch = match[ 9 ],
			    offset = match.index,
			    protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch,
				prevChar = text.charAt( offset - 1 );

			if( !Autolinker.matcher.UrlMatchValidator.isValid( matchStr, schemeUrlMatch ) ) {
				continue;
			}

			// If the match is preceded by an '@' character, then it is either
			// an email address or a username. Skip these types of matches.
			if( offset > 0 && prevChar === '@' ) {
				continue;
			}

			// If it's a protocol-relative '//' match, but the character before the '//'
			// was a word character (i.e. a letter/number), then we found the '//' in the
			// middle of another word (such as "asdf//asdf.com"). In this case, skip the
			// match.
			if( offset > 0 && protocolRelativeMatch && this.wordCharRegExp.test( prevChar ) ) {
				continue;
			}

			if( /\?$/.test(matchStr) ) {
				matchStr = matchStr.substr(0, matchStr.length-1);
			}

			// Handle a closing parenthesis at the end of the match, and exclude
			// it if there is not a matching open parenthesis in the match
			// itself.
			if( this.matchHasUnbalancedClosingParen( matchStr ) ) {
				matchStr = matchStr.substr( 0, matchStr.length - 1 );  // remove the trailing ")"
			} else {
				// Handle an invalid character after the TLD
				var pos = this.matchHasInvalidCharAfterTld( matchStr, schemeUrlMatch );
				if( pos > -1 ) {
					matchStr = matchStr.substr( 0, pos ); // remove the trailing invalid chars
				}
			}

			var urlMatchType = schemeUrlMatch ? 'scheme' : ( wwwUrlMatch ? 'www' : 'tld' ),
			    protocolUrlMatch = !!schemeUrlMatch;

			matches.push( new Autolinker.match.Url( {
				tagBuilder            : tagBuilder,
				matchedText           : matchStr,
				offset                : offset,
				urlMatchType          : urlMatchType,
				url                   : matchStr,
				protocolUrlMatch      : protocolUrlMatch,
				protocolRelativeMatch : !!protocolRelativeMatch,
				stripPrefix           : stripPrefix,
				stripTrailingSlash    : stripTrailingSlash,
				decodePercentEncoding : decodePercentEncoding,
			} ) );
		}

		return matches;
	},


	/**
	 * Determines if a match found has an unmatched closing parenthesis. If so,
	 * this parenthesis will be removed from the match itself, and appended
	 * after the generated anchor tag.
	 *
	 * A match may have an extra closing parenthesis at the end of the match
	 * because the regular expression must include parenthesis for URLs such as
	 * "wikipedia.com/something_(disambiguation)", which should be auto-linked.
	 *
	 * However, an extra parenthesis *will* be included when the URL itself is
	 * wrapped in parenthesis, such as in the case of "(wikipedia.com/something_(disambiguation))".
	 * In this case, the last closing parenthesis should *not* be part of the
	 * URL itself, and this method will return `true`.
	 *
	 * @private
	 * @param {String} matchStr The full match string from the {@link #matcherRegex}.
	 * @return {Boolean} `true` if there is an unbalanced closing parenthesis at
	 *   the end of the `matchStr`, `false` otherwise.
	 */
	matchHasUnbalancedClosingParen : function( matchStr ) {
		var lastChar = matchStr.charAt( matchStr.length - 1 );

		if( lastChar === ')' ) {
			var openParensMatch = matchStr.match( this.openParensRe ),
			    closeParensMatch = matchStr.match( this.closeParensRe ),
			    numOpenParens = ( openParensMatch && openParensMatch.length ) || 0,
			    numCloseParens = ( closeParensMatch && closeParensMatch.length ) || 0;

			if( numOpenParens < numCloseParens ) {
				return true;
			}
		}

		return false;
	},


	/**
	 * Determine if there's an invalid character after the TLD in a URL. Valid
	 * characters after TLD are ':/?#'. Exclude scheme matched URLs from this
	 * check.
	 *
	 * @private
	 * @param {String} urlMatch The matched URL, if there was one. Will be an
	 *   empty string if the match is not a URL match.
	 * @param {String} schemeUrlMatch The match URL string for a scheme
	 *   match. Ex: 'http://yahoo.com'. This is used to match something like
	 *   'http://localhost', where we won't double check that the domain name
	 *   has at least one '.' in it.
	 * @return {Number} the position where the invalid character was found. If
	 *   no such character was found, returns -1
	 */
	matchHasInvalidCharAfterTld : function( urlMatch, schemeUrlMatch ) {
		if( !urlMatch ) {
			return -1;
		}

		var offset = 0;
		if ( schemeUrlMatch ) {
			offset = urlMatch.indexOf(':');
			urlMatch = urlMatch.slice(offset);
		}

		var alphaNumeric = Autolinker.RegexLib.alphaNumericCharsStr;

		var re = new RegExp("^((.?\/\/)?[-." + alphaNumeric + "]*[-" + alphaNumeric + "]\\.[-" + alphaNumeric + "]+)");
		var res = re.exec( urlMatch );
		if ( res === null ) {
			return -1;
		}

		offset += res[1].length;
		urlMatch = urlMatch.slice(res[1].length);
		if (/^[^-.A-Za-z0-9:\/?#]/.test(urlMatch)) {
			return offset;
		}

		return -1;
	}

} );

/*global Autolinker */
/*jshint scripturl:true */
/**
 * @private
 * @class Autolinker.matcher.UrlMatchValidator
 * @singleton
 *
 * Used by Autolinker to filter out false URL positives from the
 * {@link Autolinker.matcher.Url UrlMatcher}.
 *
 * Due to the limitations of regular expressions (including the missing feature
 * of look-behinds in JS regular expressions), we cannot always determine the
 * validity of a given match. This class applies a bit of additional logic to
 * filter out any false positives that have been matched by the
 * {@link Autolinker.matcher.Url UrlMatcher}.
 */
Autolinker.matcher.UrlMatchValidator = {

	/**
	 * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://'
	 *
	 * @private
	 * @property {RegExp} hasFullProtocolRegex
	 */
	hasFullProtocolRegex : /^[A-Za-z][-.+A-Za-z0-9]*:\/\//,

	/**
	 * Regex to find the URI scheme, such as 'mailto:'.
	 *
	 * This is used to filter out 'javascript:' and 'vbscript:' schemes.
	 *
	 * @private
	 * @property {RegExp} uriSchemeRegex
	 */
	uriSchemeRegex : /^[A-Za-z][-.+A-Za-z0-9]*:/,

	/**
	 * Regex to determine if at least one word char exists after the protocol (i.e. after the ':')
	 *
	 * @private
	 * @property {RegExp} hasWordCharAfterProtocolRegex
	 */
	hasWordCharAfterProtocolRegex : new RegExp(":[^\\s]*?[" + Autolinker.RegexLib.alphaCharsStr + "]"),

	/**
	 * Regex to determine if the string is a valid IP address
	 *
	 * @private
	 * @property {RegExp} ipRegex
	 */
	ipRegex: /[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?(:[0-9]*)?\/?$/,

	/**
	 * Determines if a given URL match found by the {@link Autolinker.matcher.Url UrlMatcher}
	 * is valid. Will return `false` for:
	 *
	 * 1) URL matches which do not have at least have one period ('.') in the
	 *    domain name (effectively skipping over matches like "abc:def").
	 *    However, URL matches with a protocol will be allowed (ex: 'http://localhost')
	 * 2) URL matches which do not have at least one word character in the
	 *    domain name (effectively skipping over matches like "git:1.0").
	 * 3) A protocol-relative url match (a URL beginning with '//') whose
	 *    previous character is a word character (effectively skipping over
	 *    strings like "abc//google.com")
	 *
	 * Otherwise, returns `true`.
	 *
	 * @param {String} urlMatch The matched URL, if there was one. Will be an
	 *   empty string if the match is not a URL match.
	 * @param {String} protocolUrlMatch The match URL string for a protocol
	 *   match. Ex: 'http://yahoo.com'. This is used to match something like
	 *   'http://localhost', where we won't double check that the domain name
	 *   has at least one '.' in it.
	 * @return {Boolean} `true` if the match given is valid and should be
	 *   processed, or `false` if the match is invalid and/or should just not be
	 *   processed.
	 */
	isValid : function( urlMatch, protocolUrlMatch ) {
		if(
			( protocolUrlMatch && !this.isValidUriScheme( protocolUrlMatch ) ) ||
			this.urlMatchDoesNotHaveProtocolOrDot( urlMatch, protocolUrlMatch ) ||    // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost')
			(this.urlMatchDoesNotHaveAtLeastOneWordChar( urlMatch, protocolUrlMatch ) && // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0"
			   !this.isValidIpAddress( urlMatch )) || // Except if it's an IP address
			this.containsMultipleDots( urlMatch )
		) {
			return false;
		}

		return true;
	},


	isValidIpAddress : function ( uriSchemeMatch ) {
		var newRegex = new RegExp(this.hasFullProtocolRegex.source + this.ipRegex.source);
		var uriScheme = uriSchemeMatch.match( newRegex );

		return uriScheme !== null;
	},

	containsMultipleDots : function ( urlMatch ) {
		var stringBeforeSlash = urlMatch;
		if (this.hasFullProtocolRegex.test(urlMatch)) {
			stringBeforeSlash = urlMatch.split('://')[1];
		}
		return stringBeforeSlash.split('/')[0].indexOf("..") > -1;
	},

	/**
	 * Determines if the URI scheme is a valid scheme to be autolinked. Returns
	 * `false` if the scheme is 'javascript:' or 'vbscript:'
	 *
	 * @private
	 * @param {String} uriSchemeMatch The match URL string for a full URI scheme
	 *   match. Ex: 'http://yahoo.com' or 'mailto:a@a.com'.
	 * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise.
	 */
	isValidUriScheme : function( uriSchemeMatch ) {
		var uriScheme = uriSchemeMatch.match( this.uriSchemeRegex )[ 0 ].toLowerCase();

		return ( uriScheme !== 'javascript:' && uriScheme !== 'vbscript:' );
	},


	/**
	 * Determines if a URL match does not have either:
	 *
	 * a) a full protocol (i.e. 'http://'), or
	 * b) at least one dot ('.') in the domain name (for a non-full-protocol
	 *    match).
	 *
	 * Either situation is considered an invalid URL (ex: 'git:d' does not have
	 * either the '://' part, or at least one dot in the domain name. If the
	 * match was 'git:abc.com', we would consider this valid.)
	 *
	 * @private
	 * @param {String} urlMatch The matched URL, if there was one. Will be an
	 *   empty string if the match is not a URL match.
	 * @param {String} protocolUrlMatch The match URL string for a protocol
	 *   match. Ex: 'http://yahoo.com'. This is used to match something like
	 *   'http://localhost', where we won't double check that the domain name
	 *   has at least one '.' in it.
	 * @return {Boolean} `true` if the URL match does not have a full protocol,
	 *   or at least one dot ('.') in a non-full-protocol match.
	 */
	urlMatchDoesNotHaveProtocolOrDot : function( urlMatch, protocolUrlMatch ) {
		return ( !!urlMatch && ( !protocolUrlMatch || !this.hasFullProtocolRegex.test( protocolUrlMatch ) ) && urlMatch.indexOf( '.' ) === -1 );
	},


	/**
	 * Determines if a URL match does not have at least one word character after
	 * the protocol (i.e. in the domain name).
	 *
	 * At least one letter character must exist in the domain name after a
	 * protocol match. Ex: skip over something like "git:1.0"
	 *
	 * @private
	 * @param {String} urlMatch The matched URL, if there was one. Will be an
	 *   empty string if the match is not a URL match.
	 * @param {String} protocolUrlMatch The match URL string for a protocol
	 *   match. Ex: 'http://yahoo.com'. This is used to know whether or not we
	 *   have a protocol in the URL string, in order to check for a word
	 *   character after the protocol separator (':').
	 * @return {Boolean} `true` if the URL match does not have at least one word
	 *   character in it after the protocol, `false` otherwise.
	 */
	urlMatchDoesNotHaveAtLeastOneWordChar : function( urlMatch, protocolUrlMatch ) {
		if( urlMatch && protocolUrlMatch ) {
			return !this.hasWordCharAfterProtocolRegex.test( urlMatch );
		} else {
			return false;
		}
	}

};

/*global Autolinker */
/**
 * A truncation feature where the ellipsis will be placed at the end of the URL.
 *
 * @param {String} anchorText
 * @param {Number} truncateLen The maximum length of the truncated output URL string.
 * @param {String} ellipsisChars The characters to place within the url, e.g. "..".
 * @return {String} The truncated URL.
 */
Autolinker.truncate.TruncateEnd = function(anchorText, truncateLen, ellipsisChars){
	return Autolinker.Util.ellipsis( anchorText, truncateLen, ellipsisChars );
};

/*global Autolinker */
/**
 * Date: 2015-10-05
 * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso)
 *
 * A truncation feature, where the ellipsis will be placed in the dead-center of the URL.
 *
 * @param {String} url             A URL.
 * @param {Number} truncateLen     The maximum length of the truncated output URL string.
 * @param {String} ellipsisChars   The characters to place within the url, e.g. "..".
 * @return {String} The truncated URL.
 */
Autolinker.truncate.TruncateMiddle = function(url, truncateLen, ellipsisChars){
  if (url.length <= truncateLen) {
    return url;
  }

  var ellipsisLengthBeforeParsing;
  var ellipsisLength;

  if(ellipsisChars == null) {
    ellipsisChars = '&hellip;';
    ellipsisLengthBeforeParsing = 8;
    ellipsisLength = 3;
  } else {
    ellipsisLengthBeforeParsing = ellipsisChars.length;
    ellipsisLength = ellipsisChars.length;
  }

  var availableLength = truncateLen - ellipsisLength;
  var end = "";
  if (availableLength > 0) {
    end = url.substr((-1)*Math.floor(availableLength/2));
  }
  return (url.substr(0, Math.ceil(availableLength/2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing);
};

/*global Autolinker */
/**
 * Date: 2015-10-05
 * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso)
 *
 * A truncation feature, where the ellipsis will be placed at a section within
 * the URL making it still somewhat human readable.
 *
 * @param {String} url						 A URL.
 * @param {Number} truncateLen		 The maximum length of the truncated output URL string.
 * @param {String} ellipsisChars	 The characters to place within the url, e.g. "...".
 * @return {String} The truncated URL.
 */
Autolinker.truncate.TruncateSmart = function(url, truncateLen, ellipsisChars){

	var ellipsisLengthBeforeParsing;
	var ellipsisLength;

	if(ellipsisChars == null) {
		ellipsisChars = '&hellip;';
		ellipsisLength = 3;
		ellipsisLengthBeforeParsing = 8;
	} else {
		ellipsisLength = ellipsisChars.length;
		ellipsisLengthBeforeParsing = ellipsisChars.length;
	}

	var parse_url = function(url){ // Functionality inspired by PHP function of same name
		var urlObj = {};
		var urlSub = url;
		var match = urlSub.match(/^([a-z]+):\/\//i);
		if (match) {
			urlObj.scheme = match[1];
			urlSub = urlSub.substr(match[0].length);
		}
		match = urlSub.match(/^(.*?)(?=(\?|#|\/|$))/i);
		if (match) {
			urlObj.host = match[1];
			urlSub = urlSub.substr(match[0].length);
		}
		match = urlSub.match(/^\/(.*?)(?=(\?|#|$))/i);
		if (match) {
			urlObj.path = match[1];
			urlSub = urlSub.substr(match[0].length);
		}
		match = urlSub.match(/^\?(.*?)(?=(#|$))/i);
		if (match) {
			urlObj.query = match[1];
			urlSub = urlSub.substr(match[0].length);
		}
		match = urlSub.match(/^#(.*?)$/i);
		if (match) {
			urlObj.fragment = match[1];
			//urlSub = urlSub.substr(match[0].length);  -- not used. Uncomment if adding another block.
		}
		return urlObj;
	};

	var buildUrl = function(urlObj){
		var url = "";
		if (urlObj.scheme && urlObj.host) {
			url += urlObj.scheme + "://";
		}
		if (urlObj.host) {
			url += urlObj.host;
		}
		if (urlObj.path) {
			url += "/" + urlObj.path;
		}
		if (urlObj.query) {
			url += "?" + urlObj.query;
		}
		if (urlObj.fragment) {
			url += "#" + urlObj.fragment;
		}
		return url;
	};

	var buildSegment = function(segment, remainingAvailableLength){
		var remainingAvailableLengthHalf = remainingAvailableLength/ 2,
				startOffset = Math.ceil(remainingAvailableLengthHalf),
				endOffset = (-1)*Math.floor(remainingAvailableLengthHalf),
				end = "";
		if (endOffset < 0) {
			end = segment.substr(endOffset);
		}
		return segment.substr(0, startOffset) + ellipsisChars + end;
	};
	if (url.length <= truncateLen) {
		return url;
	}
	var availableLength = truncateLen - ellipsisLength;
	var urlObj = parse_url(url);
	// Clean up the URL
	if (urlObj.query) {
		var matchQuery = urlObj.query.match(/^(.*?)(?=(\?|\#))(.*?)$/i);
		if (matchQuery) {
			// Malformed URL; two or more "?". Removed any content behind the 2nd.
			urlObj.query = urlObj.query.substr(0, matchQuery[1].length);
			url = buildUrl(urlObj);
		}
	}
	if (url.length <= truncateLen) {
		return url;
	}
	if (urlObj.host) {
		urlObj.host = urlObj.host.replace(/^www\./, "");
		url = buildUrl(urlObj);
	}
	if (url.length <= truncateLen) {
		return url;
	}
	// Process and build the URL
	var str = "";
	if (urlObj.host) {
		str += urlObj.host;
	}
	if (str.length >= availableLength) {
		if (urlObj.host.length == truncateLen) {
			return (urlObj.host.substr(0, (truncateLen - ellipsisLength)) + ellipsisChars).substr(0, availableLength + ellipsisLengthBeforeParsing);
		}
		return buildSegment(str, availableLength).substr(0, availableLength + ellipsisLengthBeforeParsing);
	}
	var pathAndQuery = "";
	if (urlObj.path) {
		pathAndQuery += "/" + urlObj.path;
	}
	if (urlObj.query) {
		pathAndQuery += "?" + urlObj.query;
	}
	if (pathAndQuery) {
		if ((str+pathAndQuery).length >= availableLength) {
			if ((str+pathAndQuery).length == truncateLen) {
				return (str + pathAndQuery).substr(0, truncateLen);
			}
			var remainingAvailableLength = availableLength - str.length;
			return (str + buildSegment(pathAndQuery, remainingAvailableLength)).substr(0, availableLength + ellipsisLengthBeforeParsing);
		} else {
			str += pathAndQuery;
		}
	}
	if (urlObj.fragment) {
		var fragment = "#"+urlObj.fragment;
		if ((str+fragment).length >= availableLength) {
			if ((str+fragment).length == truncateLen) {
				return (str + fragment).substr(0, truncateLen);
			}
			var remainingAvailableLength2 = availableLength - str.length;
			return (str + buildSegment(fragment, remainingAvailableLength2)).substr(0, availableLength + ellipsisLengthBeforeParsing);
		} else {
			str += fragment;
		}
	}
	if (urlObj.scheme && urlObj.host) {
		var scheme = urlObj.scheme + "://";
		if ((str+scheme).length < availableLength) {
			return (scheme + str).substr(0, truncateLen);
		}
	}
	if (str.length <= truncateLen) {
		return str;
	}
	var end = "";
	if (availableLength > 0) {
		end = str.substr((-1)*Math.floor(availableLength/2));
	}
	return (str.substr(0, Math.ceil(availableLength/2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing);
};

return Autolinker;
}));
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
module.exports = function(useSourceMap) {
	var list = [];

	// return the list of modules as css string
	list.toString = function toString() {
		return this.map(function (item) {
			var content = cssWithMappingToString(item, useSourceMap);
			if(item[2]) {
				return "@media " + item[2] + "{" + content + "}";
			} else {
				return content;
			}
		}).join("");
	};

	// import a list of modules into the list
	list.i = function(modules, mediaQuery) {
		if(typeof modules === "string")
			modules = [[null, modules, ""]];
		var alreadyImportedModules = {};
		for(var i = 0; i < this.length; i++) {
			var id = this[i][0];
			if(typeof id === "number")
				alreadyImportedModules[id] = true;
		}
		for(i = 0; i < modules.length; i++) {
			var item = modules[i];
			// skip already imported module
			// this implementation is not 100% perfect for weird media query combinations
			//  when a module is imported multiple times with different media queries.
			//  I hope this will never occur (Hey this way we have smaller bundles)
			if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
				if(mediaQuery && !item[2]) {
					item[2] = mediaQuery;
				} else if(mediaQuery) {
					item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
				}
				list.push(item);
			}
		}
	};
	return list;
};

function cssWithMappingToString(item, useSourceMap) {
	var content = item[1] || '';
	var cssMapping = item[3];
	if (!cssMapping) {
		return content;
	}

	if (useSourceMap && typeof btoa === 'function') {
		var sourceMapping = toComment(cssMapping);
		var sourceURLs = cssMapping.sources.map(function (source) {
			return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
		});

		return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
	}

	return [content].join('\n');
}

// Adapted from convert-source-map (MIT)
function toComment(sourceMap) {
	// eslint-disable-next-line no-undef
	var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
	var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;

	return '/*# ' + data + ' */';
}
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

var stylesInDom = {};

var	memoize = function (fn) {
	var memo;

	return function () {
		if (typeof memo === "undefined") memo = fn.apply(this, arguments);
		return memo;
	};
};

var isOldIE = memoize(function () {
	// Test for IE <= 9 as proposed by Browserhacks
	// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
	// Tests for existence of standard globals is to allow style-loader
	// to operate correctly into non-standard environments
	// @see https://github.com/webpack-contrib/style-loader/issues/177
	return window && document && document.all && !window.atob;
});

var getTarget = function (target, parent) {
  if (parent){
    return parent.querySelector(target);
  }
  return document.querySelector(target);
};

var getElement = (function (fn) {
	var memo = {};

	return function(target, parent) {
                // If passing function in options, then use it for resolve "head" element.
                // Useful for Shadow Root style i.e
                // {
                //   insertInto: function () { return document.querySelector("#foo").shadowRoot }
                // }
                if (typeof target === 'function') {
                        return target();
                }
                if (typeof memo[target] === "undefined") {
			var styleTarget = getTarget.call(this, target, parent);
			// Special case to return head of iframe instead of iframe itself
			if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
				try {
					// This will throw an exception if access to iframe is blocked
					// due to cross-origin restrictions
					styleTarget = styleTarget.contentDocument.head;
				} catch(e) {
					styleTarget = null;
				}
			}
			memo[target] = styleTarget;
		}
		return memo[target]
	};
})();

var singleton = null;
var	singletonCounter = 0;
var	stylesInsertedAtTop = [];

var	fixUrls = __webpack_require__(782);

module.exports = function(list, options) {
	if (typeof DEBUG !== "undefined" && DEBUG) {
		if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
	}

	options = options || {};

	options.attrs = typeof options.attrs === "object" ? options.attrs : {};

	// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
	// tags it will allow on a page
	if (!options.singleton && typeof options.singleton !== "boolean") options.singleton = isOldIE();

	// By default, add <style> tags to the <head> element
        if (!options.insertInto) options.insertInto = "head";

	// By default, add <style> tags to the bottom of the target
	if (!options.insertAt) options.insertAt = "bottom";

	var styles = listToStyles(list, options);

	addStylesToDom(styles, options);

	return function update (newList) {
		var mayRemove = [];

		for (var i = 0; i < styles.length; i++) {
			var item = styles[i];
			var domStyle = stylesInDom[item.id];

			domStyle.refs--;
			mayRemove.push(domStyle);
		}

		if(newList) {
			var newStyles = listToStyles(newList, options);
			addStylesToDom(newStyles, options);
		}

		for (var i = 0; i < mayRemove.length; i++) {
			var domStyle = mayRemove[i];

			if(domStyle.refs === 0) {
				for (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();

				delete stylesInDom[domStyle.id];
			}
		}
	};
};

function addStylesToDom (styles, options) {
	for (var i = 0; i < styles.length; i++) {
		var item = styles[i];
		var domStyle = stylesInDom[item.id];

		if(domStyle) {
			domStyle.refs++;

			for(var j = 0; j < domStyle.parts.length; j++) {
				domStyle.parts[j](item.parts[j]);
			}

			for(; j < item.parts.length; j++) {
				domStyle.parts.push(addStyle(item.parts[j], options));
			}
		} else {
			var parts = [];

			for(var j = 0; j < item.parts.length; j++) {
				parts.push(addStyle(item.parts[j], options));
			}

			stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
		}
	}
}

function listToStyles (list, options) {
	var styles = [];
	var newStyles = {};

	for (var i = 0; i < list.length; i++) {
		var item = list[i];
		var id = options.base ? item[0] + options.base : item[0];
		var css = item[1];
		var media = item[2];
		var sourceMap = item[3];
		var part = {css: css, media: media, sourceMap: sourceMap};

		if(!newStyles[id]) styles.push(newStyles[id] = {id: id, parts: [part]});
		else newStyles[id].parts.push(part);
	}

	return styles;
}

function insertStyleElement (options, style) {
	var target = getElement(options.insertInto)

	if (!target) {
		throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
	}

	var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];

	if (options.insertAt === "top") {
		if (!lastStyleElementInsertedAtTop) {
			target.insertBefore(style, target.firstChild);
		} else if (lastStyleElementInsertedAtTop.nextSibling) {
			target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);
		} else {
			target.appendChild(style);
		}
		stylesInsertedAtTop.push(style);
	} else if (options.insertAt === "bottom") {
		target.appendChild(style);
	} else if (typeof options.insertAt === "object" && options.insertAt.before) {
		var nextSibling = getElement(options.insertAt.before, target);
		target.insertBefore(style, nextSibling);
	} else {
		throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
	}
}

function removeStyleElement (style) {
	if (style.parentNode === null) return false;
	style.parentNode.removeChild(style);

	var idx = stylesInsertedAtTop.indexOf(style);
	if(idx >= 0) {
		stylesInsertedAtTop.splice(idx, 1);
	}
}

function createStyleElement (options) {
	var style = document.createElement("style");

	if(options.attrs.type === undefined) {
		options.attrs.type = "text/css";
	}

	if(options.attrs.nonce === undefined) {
		var nonce = getNonce();
		if (nonce) {
			options.attrs.nonce = nonce;
		}
	}

	addAttrs(style, options.attrs);
	insertStyleElement(options, style);

	return style;
}

function createLinkElement (options) {
	var link = document.createElement("link");

	if(options.attrs.type === undefined) {
		options.attrs.type = "text/css";
	}
	options.attrs.rel = "stylesheet";

	addAttrs(link, options.attrs);
	insertStyleElement(options, link);

	return link;
}

function addAttrs (el, attrs) {
	Object.keys(attrs).forEach(function (key) {
		el.setAttribute(key, attrs[key]);
	});
}

function getNonce() {
	if (false) {}

	return __webpack_require__.nc;
}

function addStyle (obj, options) {
	var style, update, remove, result;

	// If a transform function was defined, run it on the css
	if (options.transform && obj.css) {
	    result = typeof options.transform === 'function'
		 ? options.transform(obj.css) 
		 : options.transform.default(obj.css);

	    if (result) {
	    	// If transform returns a value, use that instead of the original css.
	    	// This allows running runtime transformations on the css.
	    	obj.css = result;
	    } else {
	    	// If the transform function returns a falsy value, don't add this css.
	    	// This allows conditional loading of css
	    	return function() {
	    		// noop
	    	};
	    }
	}

	if (options.singleton) {
		var styleIndex = singletonCounter++;

		style = singleton || (singleton = createStyleElement(options));

		update = applyToSingletonTag.bind(null, style, styleIndex, false);
		remove = applyToSingletonTag.bind(null, style, styleIndex, true);

	} else if (
		obj.sourceMap &&
		typeof URL === "function" &&
		typeof URL.createObjectURL === "function" &&
		typeof URL.revokeObjectURL === "function" &&
		typeof Blob === "function" &&
		typeof btoa === "function"
	) {
		style = createLinkElement(options);
		update = updateLink.bind(null, style, options);
		remove = function () {
			removeStyleElement(style);

			if(style.href) URL.revokeObjectURL(style.href);
		};
	} else {
		style = createStyleElement(options);
		update = applyToTag.bind(null, style);
		remove = function () {
			removeStyleElement(style);
		};
	}

	update(obj);

	return function updateStyle (newObj) {
		if (newObj) {
			if (
				newObj.css === obj.css &&
				newObj.media === obj.media &&
				newObj.sourceMap === obj.sourceMap
			) {
				return;
			}

			update(obj = newObj);
		} else {
			remove();
		}
	};
}

var replaceText = (function () {
	var textStore = [];

	return function (index, replacement) {
		textStore[index] = replacement;

		return textStore.filter(Boolean).join('\n');
	};
})();

function applyToSingletonTag (style, index, remove, obj) {
	var css = remove ? "" : obj.css;

	if (style.styleSheet) {
		style.styleSheet.cssText = replaceText(index, css);
	} else {
		var cssNode = document.createTextNode(css);
		var childNodes = style.childNodes;

		if (childNodes[index]) style.removeChild(childNodes[index]);

		if (childNodes.length) {
			style.insertBefore(cssNode, childNodes[index]);
		} else {
			style.appendChild(cssNode);
		}
	}
}

function applyToTag (style, obj) {
	var css = obj.css;
	var media = obj.media;

	if(media) {
		style.setAttribute("media", media)
	}

	if(style.styleSheet) {
		style.styleSheet.cssText = css;
	} else {
		while(style.firstChild) {
			style.removeChild(style.firstChild);
		}

		style.appendChild(document.createTextNode(css));
	}
}

function updateLink (link, options, obj) {
	var css = obj.css;
	var sourceMap = obj.sourceMap;

	/*
		If convertToAbsoluteUrls isn't defined, but sourcemaps are enabled
		and there is no publicPath defined then lets turn convertToAbsoluteUrls
		on by default.  Otherwise default to the convertToAbsoluteUrls option
		directly
	*/
	var autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;

	if (options.convertToAbsoluteUrls || autoFixUrls) {
		css = fixUrls(css);
	}

	if (sourceMap) {
		// http://stackoverflow.com/a/26603875
		css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
	}

	var blob = new Blob([css], { type: "text/css" });

	var oldSrc = link.href;

	link.href = URL.createObjectURL(blob);

	if(oldSrc) URL.revokeObjectURL(oldSrc);
}

/**
 * When source maps are enabled, `style-loader` uses a link element with a data-uri to
 * embed the css on the page. This breaks all relative urls because now they are relative to a
 * bundle instead of the current page.
 *
 * One solution is to only use full urls, but that may be impossible.
 *
 * Instead, this function "fixes" the relative urls to be absolute according to the current page location.
 *
 * A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.
 *
 */

module.exports = function (css) {
  // get current location
  var location = typeof window !== "undefined" && window.location;

  if (!location) {
    throw new Error("fixUrls requires window.location");
  }

	// blank or null?
	if (!css || typeof css !== "string") {
	  return css;
  }

  var baseUrl = location.protocol + "//" + location.host;
  var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");

	// convert each url(...)
	/*
	This regular expression is just a way to recursively match brackets within
	a string.

	 /url\s*\(  = Match on the word "url" with any whitespace after it and then a parens
	   (  = Start a capturing group
	     (?:  = Start a non-capturing group
	         [^)(]  = Match anything that isn't a parentheses
	         |  = OR
	         \(  = Match a start parentheses
	             (?:  = Start another non-capturing groups
	                 [^)(]+  = Match anything that isn't a parentheses
	                 |  = OR
	                 \(  = Match a start parentheses
	                     [^)(]*  = Match anything that isn't a parentheses
	                 \)  = Match a end parentheses
	             )  = End Group
              *\) = Match anything and then a close parens
          )  = Close non-capturing group
          *  = Match anything
       )  = Close capturing group
	 \)  = Match a close parens

	 /gi  = Get all matches, not the first.  Be case insensitive.
	 */
	var fixedCss = css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
		// strip quotes (if they exist)
		var unquotedOrigUrl = origUrl
			.trim()
			.replace(/^"(.*)"$/, function(o, $1){ return $1; })
			.replace(/^'(.*)'$/, function(o, $1){ return $1; });

		// already a full url? no change
		if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(unquotedOrigUrl)) {
		  return fullMatch;
		}

		// convert the url to a full url
		var newUrl;

		if (unquotedOrigUrl.indexOf("//") === 0) {
		  	//TODO: should we add protocol?
			newUrl = unquotedOrigUrl;
		} else if (unquotedOrigUrl.indexOf("/") === 0) {
			// path should be relative to the base url
			newUrl = baseUrl + unquotedOrigUrl; // already starts with '/'
		} else {
			// path should be relative to current directory
			newUrl = currentDir + unquotedOrigUrl.replace(/^\.\//, ""); // Strip leading './'
		}

		// send back the fixed url(...)
		return "url(" + JSON.stringify(newUrl) + ")";
	});

	// send back the fixed css
	return fixedCss;
};
/* WEBPACK VAR INJECTION */(function(global) {/**
 * marked - a markdown parser
 * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT Licensed)
 * https://github.com/markedjs/marked
 */

;(function(root) {
'use strict';

/**
 * Block-Level Grammar
 */

var block = {
  newline: /^\n+/,
  code: /^( {4}[^\n]+\n*)+/,
  fences: /^ {0,3}(`{3,}|~{3,})([^`~\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
  hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
  heading: /^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,
  blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
  list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
  html: '^ {0,3}(?:' // optional indentation
    + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
    + '|comment[^\\n]*(\\n+|$)' // (2)
    + '|<\\?[\\s\\S]*?\\?>\\n*' // (3)
    + '|<![A-Z][\\s\\S]*?>\\n*' // (4)
    + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*' // (5)
    + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
    + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
    + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
    + ')',
  def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
  nptable: noop,
  table: noop,
  lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
  // regex template, placeholders will be replaced according to different paragraph
  // interruption rules of commonmark and the original markdown spec:
  _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,
  text: /^[^\n]+/
};

block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
block.def = edit(block.def)
  .replace('label', block._label)
  .replace('title', block._title)
  .getRegex();

block.bullet = /(?:[*+-]|\d{1,9}\.)/;
block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/;
block.item = edit(block.item, 'gm')
  .replace(/bull/g, block.bullet)
  .getRegex();

block.list = edit(block.list)
  .replace(/bull/g, block.bullet)
  .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
  .replace('def', '\\n+(?=' + block.def.source + ')')
  .getRegex();

block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
  + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'
  + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'
  + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
  + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
  + '|track|ul';
block._comment = /<!--(?!-?>)[\s\S]*?-->/;
block.html = edit(block.html, 'i')
  .replace('comment', block._comment)
  .replace('tag', block._tag)
  .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/)
  .getRegex();

block.paragraph = edit(block._paragraph)
  .replace('hr', block.hr)
  .replace('heading', ' {0,3}#{1,6} +')
  .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
  .replace('blockquote', ' {0,3}>')
  .replace('fences', ' {0,3}(?:`{3,}|~{3,})[^`\\n]*\\n')
  .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
  .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
  .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
  .getRegex();

block.blockquote = edit(block.blockquote)
  .replace('paragraph', block.paragraph)
  .getRegex();

/**
 * Normal Block Grammar
 */

block.normal = merge({}, block);

/**
 * GFM Block Grammar
 */

block.gfm = merge({}, block.normal, {
  nptable: /^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,
  table: /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/
});

/**
 * Pedantic grammar (original John Gruber's loose markdown specification)
 */

block.pedantic = merge({}, block.normal, {
  html: edit(
    '^ *(?:comment *(?:\\n|\\s*$)'
    + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
    + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))')
    .replace('comment', block._comment)
    .replace(/tag/g, '(?!(?:'
      + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'
      + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'
      + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b')
    .getRegex(),
  def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
  heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,
  fences: noop, // fences not supported
  paragraph: edit(block.normal._paragraph)
    .replace('hr', block.hr)
    .replace('heading', ' *#{1,6} *[^\n]')
    .replace('lheading', block.lheading)
    .replace('blockquote', ' {0,3}>')
    .replace('|fences', '')
    .replace('|list', '')
    .replace('|html', '')
    .getRegex()
});

/**
 * Block Lexer
 */

function Lexer(options) {
  this.tokens = [];
  this.tokens.links = Object.create(null);
  this.options = options || marked.defaults;
  this.rules = block.normal;

  if (this.options.pedantic) {
    this.rules = block.pedantic;
  } else if (this.options.gfm) {
    this.rules = block.gfm;
  }
}

/**
 * Expose Block Rules
 */

Lexer.rules = block;

/**
 * Static Lex Method
 */

Lexer.lex = function(src, options) {
  var lexer = new Lexer(options);
  return lexer.lex(src);
};

/**
 * Preprocessing
 */

Lexer.prototype.lex = function(src) {
  src = src
    .replace(/\r\n|\r/g, '\n')
    .replace(/\t/g, '    ')
    .replace(/\u00a0/g, ' ')
    .replace(/\u2424/g, '\n');

  return this.token(src, true);
};

/**
 * Lexing
 */

Lexer.prototype.token = function(src, top) {
  src = src.replace(/^ +$/gm, '');
  var next,
      loose,
      cap,
      bull,
      b,
      item,
      listStart,
      listItems,
      t,
      space,
      i,
      tag,
      l,
      isordered,
      istask,
      ischecked;

  while (src) {
    // newline
    if (cap = this.rules.newline.exec(src)) {
      src = src.substring(cap[0].length);
      if (cap[0].length > 1) {
        this.tokens.push({
          type: 'space'
        });
      }
    }

    // code
    if (cap = this.rules.code.exec(src)) {
      var lastToken = this.tokens[this.tokens.length - 1];
      src = src.substring(cap[0].length);
      // An indented code block cannot interrupt a paragraph.
      if (lastToken && lastToken.type === 'paragraph') {
        lastToken.text += '\n' + cap[0].trimRight();
      } else {
        cap = cap[0].replace(/^ {4}/gm, '');
        this.tokens.push({
          type: 'code',
          codeBlockStyle: 'indented',
          text: !this.options.pedantic
            ? rtrim(cap, '\n')
            : cap
        });
      }
      continue;
    }

    // fences
    if (cap = this.rules.fences.exec(src)) {
      src = src.substring(cap[0].length);
      this.tokens.push({
        type: 'code',
        lang: cap[2] ? cap[2].trim() : cap[2],
        text: cap[3] || ''
      });
      continue;
    }

    // heading
    if (cap = this.rules.heading.exec(src)) {
      src = src.substring(cap[0].length);
      this.tokens.push({
        type: 'heading',
        depth: cap[1].length,
        text: cap[2]
      });
      continue;
    }

    // table no leading pipe (gfm)
    if (cap = this.rules.nptable.exec(src)) {
      item = {
        type: 'table',
        header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
        cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
      };

      if (item.header.length === item.align.length) {
        src = src.substring(cap[0].length);

        for (i = 0; i < item.align.length; i++) {
          if (/^ *-+: *$/.test(item.align[i])) {
            item.align[i] = 'right';
          } else if (/^ *:-+: *$/.test(item.align[i])) {
            item.align[i] = 'center';
          } else if (/^ *:-+ *$/.test(item.align[i])) {
            item.align[i] = 'left';
          } else {
            item.align[i] = null;
          }
        }

        for (i = 0; i < item.cells.length; i++) {
          item.cells[i] = splitCells(item.cells[i], item.header.length);
        }

        this.tokens.push(item);

        continue;
      }
    }

    // hr
    if (cap = this.rules.hr.exec(src)) {
      src = src.substring(cap[0].length);
      this.tokens.push({
        type: 'hr'
      });
      continue;
    }

    // blockquote
    if (cap = this.rules.blockquote.exec(src)) {
      src = src.substring(cap[0].length);

      this.tokens.push({
        type: 'blockquote_start'
      });

      cap = cap[0].replace(/^ *> ?/gm, '');

      // Pass `top` to keep the current
      // "toplevel" state. This is exactly
      // how markdown.pl works.
      this.token(cap, top);

      this.tokens.push({
        type: 'blockquote_end'
      });

      continue;
    }

    // list
    if (cap = this.rules.list.exec(src)) {
      src = src.substring(cap[0].length);
      bull = cap[2];
      isordered = bull.length > 1;

      listStart = {
        type: 'list_start',
        ordered: isordered,
        start: isordered ? +bull : '',
        loose: false
      };

      this.tokens.push(listStart);

      // Get each top-level item.
      cap = cap[0].match(this.rules.item);

      listItems = [];
      next = false;
      l = cap.length;
      i = 0;

      for (; i < l; i++) {
        item = cap[i];

        // Remove the list item's bullet
        // so it is seen as the next token.
        space = item.length;
        item = item.replace(/^ *([*+-]|\d+\.) */, '');

        // Outdent whatever the
        // list item contains. Hacky.
        if (~item.indexOf('\n ')) {
          space -= item.length;
          item = !this.options.pedantic
            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
            : item.replace(/^ {1,4}/gm, '');
        }

        // Determine whether the next list item belongs here.
        // Backpedal if it does not belong in this list.
        if (i !== l - 1) {
          b = block.bullet.exec(cap[i + 1])[0];
          if (bull.length > 1 ? b.length === 1
            : (b.length > 1 || (this.options.smartLists && b !== bull))) {
            src = cap.slice(i + 1).join('\n') + src;
            i = l - 1;
          }
        }

        // Determine whether item is loose or not.
        // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
        // for discount behavior.
        loose = next || /\n\n(?!\s*$)/.test(item);
        if (i !== l - 1) {
          next = item.charAt(item.length - 1) === '\n';
          if (!loose) loose = next;
        }

        if (loose) {
          listStart.loose = true;
        }

        // Check for task list items
        istask = /^\[[ xX]\] /.test(item);
        ischecked = undefined;
        if (istask) {
          ischecked = item[1] !== ' ';
          item = item.replace(/^\[[ xX]\] +/, '');
        }

        t = {
          type: 'list_item_start',
          task: istask,
          checked: ischecked,
          loose: loose
        };

        listItems.push(t);
        this.tokens.push(t);

        // Recurse.
        this.token(item, false);

        this.tokens.push({
          type: 'list_item_end'
        });
      }

      if (listStart.loose) {
        l = listItems.length;
        i = 0;
        for (; i < l; i++) {
          listItems[i].loose = true;
        }
      }

      this.tokens.push({
        type: 'list_end'
      });

      continue;
    }

    // html
    if (cap = this.rules.html.exec(src)) {
      src = src.substring(cap[0].length);
      this.tokens.push({
        type: this.options.sanitize
          ? 'paragraph'
          : 'html',
        pre: !this.options.sanitizer
          && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
        text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0]
      });
      continue;
    }

    // def
    if (top && (cap = this.rules.def.exec(src))) {
      src = src.substring(cap[0].length);
      if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
      tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
      if (!this.tokens.links[tag]) {
        this.tokens.links[tag] = {
          href: cap[2],
          title: cap[3]
        };
      }
      continue;
    }

    // table (gfm)
    if (cap = this.rules.table.exec(src)) {
      item = {
        type: 'table',
        header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
        cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
      };

      if (item.header.length === item.align.length) {
        src = src.substring(cap[0].length);

        for (i = 0; i < item.align.length; i++) {
          if (/^ *-+: *$/.test(item.align[i])) {
            item.align[i] = 'right';
          } else if (/^ *:-+: *$/.test(item.align[i])) {
            item.align[i] = 'center';
          } else if (/^ *:-+ *$/.test(item.align[i])) {
            item.align[i] = 'left';
          } else {
            item.align[i] = null;
          }
        }

        for (i = 0; i < item.cells.length; i++) {
          item.cells[i] = splitCells(
            item.cells[i].replace(/^ *\| *| *\| *$/g, ''),
            item.header.length);
        }

        this.tokens.push(item);

        continue;
      }
    }

    // lheading
    if (cap = this.rules.lheading.exec(src)) {
      src = src.substring(cap[0].length);
      this.tokens.push({
        type: 'heading',
        depth: cap[2].charAt(0) === '=' ? 1 : 2,
        text: cap[1]
      });
      continue;
    }

    // top-level paragraph
    if (top && (cap = this.rules.paragraph.exec(src))) {
      src = src.substring(cap[0].length);
      this.tokens.push({
        type: 'paragraph',
        text: cap[1].charAt(cap[1].length - 1) === '\n'
          ? cap[1].slice(0, -1)
          : cap[1]
      });
      continue;
    }

    // text
    if (cap = this.rules.text.exec(src)) {
      // Top-level should never reach here.
      src = src.substring(cap[0].length);
      this.tokens.push({
        type: 'text',
        text: cap[0]
      });
      continue;
    }

    if (src) {
      throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
    }
  }

  return this.tokens;
};

/**
 * Inline-Level Grammar
 */

var inline = {
  escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
  autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
  url: noop,
  tag: '^comment'
    + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
    + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
    + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
    + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
    + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section
  link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
  reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
  nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
  strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,
  em: /^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,
  code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
  br: /^( {2,}|\\)\n(?!\s*$)/,
  del: noop,
  text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/
};

// list of punctuation marks from common mark spec
// without ` and ] to workaround Rule 17 (inline code blocks/links)
inline._punctuation = '!"#$%&\'()*+,\\-./:;<=>?@\\[^_{|}~';
inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex();

inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;

inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
inline.autolink = edit(inline.autolink)
  .replace('scheme', inline._scheme)
  .replace('email', inline._email)
  .getRegex();

inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;

inline.tag = edit(inline.tag)
  .replace('comment', block._comment)
  .replace('attribute', inline._attribute)
  .getRegex();

inline._label = /(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
inline._href = /<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/;
inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;

inline.link = edit(inline.link)
  .replace('label', inline._label)
  .replace('href', inline._href)
  .replace('title', inline._title)
  .getRegex();

inline.reflink = edit(inline.reflink)
  .replace('label', inline._label)
  .getRegex();

/**
 * Normal Inline Grammar
 */

inline.normal = merge({}, inline);

/**
 * Pedantic Inline Grammar
 */

inline.pedantic = merge({}, inline.normal, {
  strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
  em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
  link: edit(/^!?\[(label)\]\((.*?)\)/)
    .replace('label', inline._label)
    .getRegex(),
  reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/)
    .replace('label', inline._label)
    .getRegex()
});

/**
 * GFM Inline Grammar
 */

inline.gfm = merge({}, inline.normal, {
  escape: edit(inline.escape).replace('])', '~|])').getRegex(),
  _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
  url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
  _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
  del: /^~+(?=\S)([\s\S]*?\S)~+/,
  text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?= {2,}\n|[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
});

inline.gfm.url = edit(inline.gfm.url, 'i')
  .replace('email', inline.gfm._extended_email)
  .getRegex();
/**
 * GFM + Line Breaks Inline Grammar
 */

inline.breaks = merge({}, inline.gfm, {
  br: edit(inline.br).replace('{2,}', '*').getRegex(),
  text: edit(inline.gfm.text)
    .replace('\\b_', '\\b_| {2,}\\n')
    .replace(/\{2,\}/g, '*')
    .getRegex()
});

/**
 * Inline Lexer & Compiler
 */

function InlineLexer(links, options) {
  this.options = options || marked.defaults;
  this.links = links;
  this.rules = inline.normal;
  this.renderer = this.options.renderer || new Renderer();
  this.renderer.options = this.options;

  if (!this.links) {
    throw new Error('Tokens array requires a `links` property.');
  }

  if (this.options.pedantic) {
    this.rules = inline.pedantic;
  } else if (this.options.gfm) {
    if (this.options.breaks) {
      this.rules = inline.breaks;
    } else {
      this.rules = inline.gfm;
    }
  }
}

/**
 * Expose Inline Rules
 */

InlineLexer.rules = inline;

/**
 * Static Lexing/Compiling Method
 */

InlineLexer.output = function(src, links, options) {
  var inline = new InlineLexer(links, options);
  return inline.output(src);
};

/**
 * Lexing/Compiling
 */

InlineLexer.prototype.output = function(src) {
  var out = '',
      link,
      text,
      href,
      title,
      cap,
      prevCapZero;

  while (src) {
    // escape
    if (cap = this.rules.escape.exec(src)) {
      src = src.substring(cap[0].length);
      out += escape(cap[1]);
      continue;
    }

    // tag
    if (cap = this.rules.tag.exec(src)) {
      if (!this.inLink && /^<a /i.test(cap[0])) {
        this.inLink = true;
      } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
        this.inLink = false;
      }
      if (!this.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
        this.inRawBlock = true;
      } else if (this.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
        this.inRawBlock = false;
      }

      src = src.substring(cap[0].length);
      out += this.options.sanitize
        ? this.options.sanitizer
          ? this.options.sanitizer(cap[0])
          : escape(cap[0])
        : cap[0];
      continue;
    }

    // link
    if (cap = this.rules.link.exec(src)) {
      var lastParenIndex = findClosingBracket(cap[2], '()');
      if (lastParenIndex > -1) {
        var linkLen = 4 + cap[1].length + lastParenIndex;
        cap[2] = cap[2].substring(0, lastParenIndex);
        cap[0] = cap[0].substring(0, linkLen).trim();
        cap[3] = '';
      }
      src = src.substring(cap[0].length);
      this.inLink = true;
      href = cap[2];
      if (this.options.pedantic) {
        link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);

        if (link) {
          href = link[1];
          title = link[3];
        } else {
          title = '';
        }
      } else {
        title = cap[3] ? cap[3].slice(1, -1) : '';
      }
      href = href.trim().replace(/^<([\s\S]*)>$/, '$1');
      out += this.outputLink(cap, {
        href: InlineLexer.escapes(href),
        title: InlineLexer.escapes(title)
      });
      this.inLink = false;
      continue;
    }

    // reflink, nolink
    if ((cap = this.rules.reflink.exec(src))
        || (cap = this.rules.nolink.exec(src))) {
      src = src.substring(cap[0].length);
      link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
      link = this.links[link.toLowerCase()];
      if (!link || !link.href) {
        out += cap[0].charAt(0);
        src = cap[0].substring(1) + src;
        continue;
      }
      this.inLink = true;
      out += this.outputLink(cap, link);
      this.inLink = false;
      continue;
    }

    // strong
    if (cap = this.rules.strong.exec(src)) {
      src = src.substring(cap[0].length);
      out += this.renderer.strong(this.output(cap[4] || cap[3] || cap[2] || cap[1]));
      continue;
    }

    // em
    if (cap = this.rules.em.exec(src)) {
      src = src.substring(cap[0].length);
      out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]));
      continue;
    }

    // code
    if (cap = this.rules.code.exec(src)) {
      src = src.substring(cap[0].length);
      out += this.renderer.codespan(escape(cap[2].trim(), true));
      continue;
    }

    // br
    if (cap = this.rules.br.exec(src)) {
      src = src.substring(cap[0].length);
      out += this.renderer.br();
      continue;
    }

    // del (gfm)
    if (cap = this.rules.del.exec(src)) {
      src = src.substring(cap[0].length);
      out += this.renderer.del(this.output(cap[1]));
      continue;
    }

    // autolink
    if (cap = this.rules.autolink.exec(src)) {
      src = src.substring(cap[0].length);
      if (cap[2] === '@') {
        text = escape(this.mangle(cap[1]));
        href = 'mailto:' + text;
      } else {
        text = escape(cap[1]);
        href = text;
      }
      out += this.renderer.link(href, null, text);
      continue;
    }

    // url (gfm)
    if (!this.inLink && (cap = this.rules.url.exec(src))) {
      if (cap[2] === '@') {
        text = escape(cap[0]);
        href = 'mailto:' + text;
      } else {
        // do extended autolink path validation
        do {
          prevCapZero = cap[0];
          cap[0] = this.rules._backpedal.exec(cap[0])[0];
        } while (prevCapZero !== cap[0]);
        text = escape(cap[0]);
        if (cap[1] === 'www.') {
          href = 'http://' + text;
        } else {
          href = text;
        }
      }
      src = src.substring(cap[0].length);
      out += this.renderer.link(href, null, text);
      continue;
    }

    // text
    if (cap = this.rules.text.exec(src)) {
      src = src.substring(cap[0].length);
      if (this.inRawBlock) {
        out += this.renderer.text(this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0]);
      } else {
        out += this.renderer.text(escape(this.smartypants(cap[0])));
      }
      continue;
    }

    if (src) {
      throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
    }
  }

  return out;
};

InlineLexer.escapes = function(text) {
  return text ? text.replace(InlineLexer.rules._escapes, '$1') : text;
};

/**
 * Compile Link
 */

InlineLexer.prototype.outputLink = function(cap, link) {
  var href = link.href,
      title = link.title ? escape(link.title) : null;

  return cap[0].charAt(0) !== '!'
    ? this.renderer.link(href, title, this.output(cap[1]))
    : this.renderer.image(href, title, escape(cap[1]));
};

/**
 * Smartypants Transformations
 */

InlineLexer.prototype.smartypants = function(text) {
  if (!this.options.smartypants) return text;
  return text
    // em-dashes
    .replace(/---/g, '\u2014')
    // en-dashes
    .replace(/--/g, '\u2013')
    // opening singles
    .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
    // closing singles & apostrophes
    .replace(/'/g, '\u2019')
    // opening doubles
    .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
    // closing doubles
    .replace(/"/g, '\u201d')
    // ellipses
    .replace(/\.{3}/g, '\u2026');
};

/**
 * Mangle Links
 */

InlineLexer.prototype.mangle = function(text) {
  if (!this.options.mangle) return text;
  var out = '',
      l = text.length,
      i = 0,
      ch;

  for (; i < l; i++) {
    ch = text.charCodeAt(i);
    if (Math.random() > 0.5) {
      ch = 'x' + ch.toString(16);
    }
    out += '&#' + ch + ';';
  }

  return out;
};

/**
 * Renderer
 */

function Renderer(options) {
  this.options = options || marked.defaults;
}

Renderer.prototype.code = function(code, infostring, escaped) {
  var lang = (infostring || '').match(/\S*/)[0];
  if (this.options.highlight) {
    var out = this.options.highlight(code, lang);
    if (out != null && out !== code) {
      escaped = true;
      code = out;
    }
  }

  if (!lang) {
    return '<pre><code>'
      + (escaped ? code : escape(code, true))
      + '</code></pre>';
  }

  return '<pre><code class="'
    + this.options.langPrefix
    + escape(lang, true)
    + '">'
    + (escaped ? code : escape(code, true))
    + '</code></pre>\n';
};

Renderer.prototype.blockquote = function(quote) {
  return '<blockquote>\n' + quote + '</blockquote>\n';
};

Renderer.prototype.html = function(html) {
  return html;
};

Renderer.prototype.heading = function(text, level, raw, slugger) {
  if (this.options.headerIds) {
    return '<h'
      + level
      + ' id="'
      + this.options.headerPrefix
      + slugger.slug(raw)
      + '">'
      + text
      + '</h'
      + level
      + '>\n';
  }
  // ignore IDs
  return '<h' + level + '>' + text + '</h' + level + '>\n';
};

Renderer.prototype.hr = function() {
  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
};

Renderer.prototype.list = function(body, ordered, start) {
  var type = ordered ? 'ol' : 'ul',
      startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
  return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
};

Renderer.prototype.listitem = function(text) {
  return '<li>' + text + '</li>\n';
};

Renderer.prototype.checkbox = function(checked) {
  return '<input '
    + (checked ? 'checked="" ' : '')
    + 'disabled="" type="checkbox"'
    + (this.options.xhtml ? ' /' : '')
    + '> ';
};

Renderer.prototype.paragraph = function(text) {
  return '<p>' + text + '</p>\n';
};

Renderer.prototype.table = function(header, body) {
  if (body) body = '<tbody>' + body + '</tbody>';

  return '<table>\n'
    + '<thead>\n'
    + header
    + '</thead>\n'
    + body
    + '</table>\n';
};

Renderer.prototype.tablerow = function(content) {
  return '<tr>\n' + content + '</tr>\n';
};

Renderer.prototype.tablecell = function(content, flags) {
  var type = flags.header ? 'th' : 'td';
  var tag = flags.align
    ? '<' + type + ' align="' + flags.align + '">'
    : '<' + type + '>';
  return tag + content + '</' + type + '>\n';
};

// span level renderer
Renderer.prototype.strong = function(text) {
  return '<strong>' + text + '</strong>';
};

Renderer.prototype.em = function(text) {
  return '<em>' + text + '</em>';
};

Renderer.prototype.codespan = function(text) {
  return '<code>' + text + '</code>';
};

Renderer.prototype.br = function() {
  return this.options.xhtml ? '<br/>' : '<br>';
};

Renderer.prototype.del = function(text) {
  return '<del>' + text + '</del>';
};

Renderer.prototype.link = function(href, title, text) {
  href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
  if (href === null) {
    return text;
  }
  var out = '<a href="' + escape(href) + '"';
  if (title) {
    out += ' title="' + title + '"';
  }
  out += '>' + text + '</a>';
  return out;
};

Renderer.prototype.image = function(href, title, text) {
  href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
  if (href === null) {
    return text;
  }

  var out = '<img src="' + href + '" alt="' + text + '"';
  if (title) {
    out += ' title="' + title + '"';
  }
  out += this.options.xhtml ? '/>' : '>';
  return out;
};

Renderer.prototype.text = function(text) {
  return text;
};

/**
 * TextRenderer
 * returns only the textual part of the token
 */

function TextRenderer() {}

// no need for block level renderers

TextRenderer.prototype.strong =
TextRenderer.prototype.em =
TextRenderer.prototype.codespan =
TextRenderer.prototype.del =
TextRenderer.prototype.text = function(text) {
  return text;
};

TextRenderer.prototype.link =
TextRenderer.prototype.image = function(href, title, text) {
  return '' + text;
};

TextRenderer.prototype.br = function() {
  return '';
};

/**
 * Parsing & Compiling
 */

function Parser(options) {
  this.tokens = [];
  this.token = null;
  this.options = options || marked.defaults;
  this.options.renderer = this.options.renderer || new Renderer();
  this.renderer = this.options.renderer;
  this.renderer.options = this.options;
  this.slugger = new Slugger();
}

/**
 * Static Parse Method
 */

Parser.parse = function(src, options) {
  var parser = new Parser(options);
  return parser.parse(src);
};

/**
 * Parse Loop
 */

Parser.prototype.parse = function(src) {
  this.inline = new InlineLexer(src.links, this.options);
  // use an InlineLexer with a TextRenderer to extract pure text
  this.inlineText = new InlineLexer(
    src.links,
    merge({}, this.options, { renderer: new TextRenderer() })
  );
  this.tokens = src.reverse();

  var out = '';
  while (this.next()) {
    out += this.tok();
  }

  return out;
};

/**
 * Next Token
 */

Parser.prototype.next = function() {
  this.token = this.tokens.pop();
  return this.token;
};

/**
 * Preview Next Token
 */

Parser.prototype.peek = function() {
  return this.tokens[this.tokens.length - 1] || 0;
};

/**
 * Parse Text Tokens
 */

Parser.prototype.parseText = function() {
  var body = this.token.text;

  while (this.peek().type === 'text') {
    body += '\n' + this.next().text;
  }

  return this.inline.output(body);
};

/**
 * Parse Current Token
 */

Parser.prototype.tok = function() {
  switch (this.token.type) {
    case 'space': {
      return '';
    }
    case 'hr': {
      return this.renderer.hr();
    }
    case 'heading': {
      return this.renderer.heading(
        this.inline.output(this.token.text),
        this.token.depth,
        unescape(this.inlineText.output(this.token.text)),
        this.slugger);
    }
    case 'code': {
      return this.renderer.code(this.token.text,
        this.token.lang,
        this.token.escaped);
    }
    case 'table': {
      var header = '',
          body = '',
          i,
          row,
          cell,
          j;

      // header
      cell = '';
      for (i = 0; i < this.token.header.length; i++) {
        cell += this.renderer.tablecell(
          this.inline.output(this.token.header[i]),
          { header: true, align: this.token.align[i] }
        );
      }
      header += this.renderer.tablerow(cell);

      for (i = 0; i < this.token.cells.length; i++) {
        row = this.token.cells[i];

        cell = '';
        for (j = 0; j < row.length; j++) {
          cell += this.renderer.tablecell(
            this.inline.output(row[j]),
            { header: false, align: this.token.align[j] }
          );
        }

        body += this.renderer.tablerow(cell);
      }
      return this.renderer.table(header, body);
    }
    case 'blockquote_start': {
      body = '';

      while (this.next().type !== 'blockquote_end') {
        body += this.tok();
      }

      return this.renderer.blockquote(body);
    }
    case 'list_start': {
      body = '';
      var ordered = this.token.ordered,
          start = this.token.start;

      while (this.next().type !== 'list_end') {
        body += this.tok();
      }

      return this.renderer.list(body, ordered, start);
    }
    case 'list_item_start': {
      body = '';
      var loose = this.token.loose;
      var checked = this.token.checked;
      var task = this.token.task;

      if (this.token.task) {
        body += this.renderer.checkbox(checked);
      }

      while (this.next().type !== 'list_item_end') {
        body += !loose && this.token.type === 'text'
          ? this.parseText()
          : this.tok();
      }
      return this.renderer.listitem(body, task, checked);
    }
    case 'html': {
      // TODO parse inline content if parameter markdown=1
      return this.renderer.html(this.token.text);
    }
    case 'paragraph': {
      return this.renderer.paragraph(this.inline.output(this.token.text));
    }
    case 'text': {
      return this.renderer.paragraph(this.parseText());
    }
    default: {
      var errMsg = 'Token with "' + this.token.type + '" type was not found.';
      if (this.options.silent) {
        console.log(errMsg);
      } else {
        throw new Error(errMsg);
      }
    }
  }
};

/**
 * Slugger generates header id
 */

function Slugger() {
  this.seen = {};
}

/**
 * Convert string to unique id
 */

Slugger.prototype.slug = function(value) {
  var slug = value
    .toLowerCase()
    .trim()
    .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
    .replace(/\s/g, '-');

  if (this.seen.hasOwnProperty(slug)) {
    var originalSlug = slug;
    do {
      this.seen[originalSlug]++;
      slug = originalSlug + '-' + this.seen[originalSlug];
    } while (this.seen.hasOwnProperty(slug));
  }
  this.seen[slug] = 0;

  return slug;
};

/**
 * Helpers
 */

function escape(html, encode) {
  if (encode) {
    if (escape.escapeTest.test(html)) {
      return html.replace(escape.escapeReplace, function(ch) { return escape.replacements[ch]; });
    }
  } else {
    if (escape.escapeTestNoEncode.test(html)) {
      return html.replace(escape.escapeReplaceNoEncode, function(ch) { return escape.replacements[ch]; });
    }
  }

  return html;
}

escape.escapeTest = /[&<>"']/;
escape.escapeReplace = /[&<>"']/g;
escape.replacements = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;'
};

escape.escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
escape.escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;

function unescape(html) {
  // explicitly match decimal, hex, and named HTML entities
  return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) {
    n = n.toLowerCase();
    if (n === 'colon') return ':';
    if (n.charAt(0) === '#') {
      return n.charAt(1) === 'x'
        ? String.fromCharCode(parseInt(n.substring(2), 16))
        : String.fromCharCode(+n.substring(1));
    }
    return '';
  });
}

function edit(regex, opt) {
  regex = regex.source || regex;
  opt = opt || '';
  return {
    replace: function(name, val) {
      val = val.source || val;
      val = val.replace(/(^|[^\[])\^/g, '$1');
      regex = regex.replace(name, val);
      return this;
    },
    getRegex: function() {
      return new RegExp(regex, opt);
    }
  };
}

function cleanUrl(sanitize, base, href) {
  if (sanitize) {
    try {
      var prot = decodeURIComponent(unescape(href))
        .replace(/[^\w:]/g, '')
        .toLowerCase();
    } catch (e) {
      return null;
    }
    if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
      return null;
    }
  }
  if (base && !originIndependentUrl.test(href)) {
    href = resolveUrl(base, href);
  }
  try {
    href = encodeURI(href).replace(/%25/g, '%');
  } catch (e) {
    return null;
  }
  return href;
}

function resolveUrl(base, href) {
  if (!baseUrls[' ' + base]) {
    // we can ignore everything in base after the last slash of its path component,
    // but we might need to add _that_
    // https://tools.ietf.org/html/rfc3986#section-3
    if (/^[^:]+:\/*[^/]*$/.test(base)) {
      baseUrls[' ' + base] = base + '/';
    } else {
      baseUrls[' ' + base] = rtrim(base, '/', true);
    }
  }
  base = baseUrls[' ' + base];

  if (href.slice(0, 2) === '//') {
    return base.replace(/:[\s\S]*/, ':') + href;
  } else if (href.charAt(0) === '/') {
    return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href;
  } else {
    return base + href;
  }
}
var baseUrls = {};
var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;

function noop() {}
noop.exec = noop;

function merge(obj) {
  var i = 1,
      target,
      key;

  for (; i < arguments.length; i++) {
    target = arguments[i];
    for (key in target) {
      if (Object.prototype.hasOwnProperty.call(target, key)) {
        obj[key] = target[key];
      }
    }
  }

  return obj;
}

function splitCells(tableRow, count) {
  // ensure that every cell-delimiting pipe has a space
  // before it to distinguish it from an escaped pipe
  var row = tableRow.replace(/\|/g, function(match, offset, str) {
        var escaped = false,
            curr = offset;
        while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
        if (escaped) {
          // odd number of slashes means | is escaped
          // so we leave it alone
          return '|';
        } else {
          // add space before unescaped |
          return ' |';
        }
      }),
      cells = row.split(/ \|/),
      i = 0;

  if (cells.length > count) {
    cells.splice(count);
  } else {
    while (cells.length < count) cells.push('');
  }

  for (; i < cells.length; i++) {
    // leading or trailing whitespace is ignored per the gfm spec
    cells[i] = cells[i].trim().replace(/\\\|/g, '|');
  }
  return cells;
}

// Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
// /c*$/ is vulnerable to REDOS.
// invert: Remove suffix of non-c chars instead. Default falsey.
function rtrim(str, c, invert) {
  if (str.length === 0) {
    return '';
  }

  // Length of suffix matching the invert condition.
  var suffLen = 0;

  // Step left until we fail to match the invert condition.
  while (suffLen < str.length) {
    var currChar = str.charAt(str.length - suffLen - 1);
    if (currChar === c && !invert) {
      suffLen++;
    } else if (currChar !== c && invert) {
      suffLen++;
    } else {
      break;
    }
  }

  return str.substr(0, str.length - suffLen);
}

function findClosingBracket(str, b) {
  if (str.indexOf(b[1]) === -1) {
    return -1;
  }
  var level = 0;
  for (var i = 0; i < str.length; i++) {
    if (str[i] === '\\') {
      i++;
    } else if (str[i] === b[0]) {
      level++;
    } else if (str[i] === b[1]) {
      level--;
      if (level < 0) {
        return i;
      }
    }
  }
  return -1;
}

function checkSanitizeDeprecation(opt) {
  if (opt && opt.sanitize && !opt.silent) {
    console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
  }
}

/**
 * Marked
 */

function marked(src, opt, callback) {
  // throw error in case of non string input
  if (typeof src === 'undefined' || src === null) {
    throw new Error('marked(): input parameter is undefined or null');
  }
  if (typeof src !== 'string') {
    throw new Error('marked(): input parameter is of type '
      + Object.prototype.toString.call(src) + ', string expected');
  }

  if (callback || typeof opt === 'function') {
    if (!callback) {
      callback = opt;
      opt = null;
    }

    opt = merge({}, marked.defaults, opt || {});
    checkSanitizeDeprecation(opt);

    var highlight = opt.highlight,
        tokens,
        pending,
        i = 0;

    try {
      tokens = Lexer.lex(src, opt);
    } catch (e) {
      return callback(e);
    }

    pending = tokens.length;

    var done = function(err) {
      if (err) {
        opt.highlight = highlight;
        return callback(err);
      }

      var out;

      try {
        out = Parser.parse(tokens, opt);
      } catch (e) {
        err = e;
      }

      opt.highlight = highlight;

      return err
        ? callback(err)
        : callback(null, out);
    };

    if (!highlight || highlight.length < 3) {
      return done();
    }

    delete opt.highlight;

    if (!pending) return done();

    for (; i < tokens.length; i++) {
      (function(token) {
        if (token.type !== 'code') {
          return --pending || done();
        }
        return highlight(token.text, token.lang, function(err, code) {
          if (err) return done(err);
          if (code == null || code === token.text) {
            return --pending || done();
          }
          token.text = code;
          token.escaped = true;
          --pending || done();
        });
      })(tokens[i]);
    }

    return;
  }
  try {
    if (opt) opt = merge({}, marked.defaults, opt);
    checkSanitizeDeprecation(opt);
    return Parser.parse(Lexer.lex(src, opt), opt);
  } catch (e) {
    e.message += '\nPlease report this to https://github.com/markedjs/marked.';
    if ((opt || marked.defaults).silent) {
      return '<p>An error occurred:</p><pre>'
        + escape(e.message + '', true)
        + '</pre>';
    }
    throw e;
  }
}

/**
 * Options
 */

marked.options =
marked.setOptions = function(opt) {
  merge(marked.defaults, opt);
  return marked;
};

marked.getDefaults = function() {
  return {
    baseUrl: null,
    breaks: false,
    gfm: true,
    headerIds: true,
    headerPrefix: '',
    highlight: null,
    langPrefix: 'language-',
    mangle: true,
    pedantic: false,
    renderer: new Renderer(),
    sanitize: false,
    sanitizer: null,
    silent: false,
    smartLists: false,
    smartypants: false,
    xhtml: false
  };
};

marked.defaults = marked.getDefaults();

/**
 * Expose
 */

marked.Parser = Parser;
marked.parser = Parser.parse;

marked.Renderer = Renderer;
marked.TextRenderer = TextRenderer;

marked.Lexer = Lexer;
marked.lexer = Lexer.lex;

marked.InlineLexer = InlineLexer;
marked.inlineLexer = InlineLexer.output;

marked.Slugger = Slugger;

marked.parse = marked;

if (true) {
  module.exports = marked;
} else {}
})(this || (typeof window !== 'undefined' ? window : global));

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(48)))/* WEBPACK VAR INJECTION */(function(_) {/* harmony import */ var http_status_codes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(100);
/* harmony import */ var http_status_codes__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(http_status_codes__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _microsoft_signalr_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(608);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(config__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var purechat_constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(25);
/* harmony import */ var purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(84);
/* harmony import */ var purechat_content_images_avatars_visitor_png__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(311);
/* harmony import */ var purechat_content_images_avatars_visitor_png__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(purechat_content_images_avatars_visitor_png__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _event_api_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(206);
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }








var array = [];
var slice = array.slice; // private, context has to be set explicitly on call

var callCallback = {
  message: function message(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedMessage = (args.message || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('message', {
      id: args.id,
      userId: args.userId,
      userDisplayName: escapedUserDisplayName,
      roomId: args.roomId,
      roomDisplayName: escapedRoomDisplayName,
      time: args.time,
      message: escapedMessage.length > 0 ? escapedMessage : null,
      isHistory: args.isHistory,
      timeElpased: args.timeElapsed,
      protocolVersion: args.protocolVersion,
      avatarUrl: args.avatarUrl,
      fromOperator: args.fromOperator,
      roomUtcOffset: args.roomUtcOffset,
      type: args.type,
      status: args.status,
      serverId: args.serverId
    });
  },
  joined: function joined(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('joined', args.userId, escapedUserDisplayName, args.roomId, escapedRoomDisplayName, args.time, args.isHistory);
  },
  left: function left(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('left', args.userId, escapedUserDisplayName, args.roomId, escapedRoomDisplayName, args.time, args.isHistory);
  },
  roomdestroyed: function roomdestroyed(args) {
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('roomdestroyed', args.roomId, escapedRoomDisplayName, args.time, args.reasonCode);
  },
  userDestroyed: function userDestroyed(args) {
    this.trigger('userDestroyed', args.userId);
  },
  typing: function typing(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('typing', args.userId, escapedUserDisplayName, args.roomId, args.roomDisplayName, args.isTyping, args.time);
  },
  roomchanged: function roomchanged(args) {
    if (args && args.action === 'closedroom' && window.PureChatEvents) {
      window.PureChatEvents.trigger('roomclosed', args.room.id);
    }

    this.trigger('roomchanged', args);
  },
  default: function _default(event, args) {
    this.trigger(event, args);
  }
};

var PureChat =
/*#__PURE__*/
function () {
  function PureChat(socketUrl, userId, domainId, authToken, identifyStatus, errorStatus, restrictTransports, poppedOut, emailMD5Hash, reconnectLimit) {
    var _this = this;

    _classCallCheck(this, PureChat);

    _defineProperty(this, "events", {});

    this.deviceVersion = 1.0;
    this.currentUserId = userId;
    this.currentDomainId = domainId;
    this.currentAuthToken = authToken;
    this.poppedOut = poppedOut;
    this.emailMD5Hash = emailMD5Hash;
    this.connectionAttempts = 0;
    this.remoteParticipantKey = this.getRemoteParticipantKey(this.currentUserId);
    this.socket = new _microsoft_signalr_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_1__[/* HubConnectionBuilder */ "a"]().withUrl("".concat(config__WEBPACK_IMPORTED_MODULE_2___default.a.signalrRoomApi, "/chatHub")).build();

    var onStart = function onStart() {
      _this.identify(_this.currentUserId, _this.currentDomainId, _this.currentAuthToken, identifyStatus, _this.poppedOut, _this.emailMD5Hash);
    };

    this.socket.start().then(onStart).catch(function (err) {
      return console.error(err.toString());
    }); // eslint-disable-line no-console
    // stores socket.io messages that need to be sent out after the client registers callbacks

    this.messageQueue = []; // registers the handler for a message type - incoming messages will be sent to the callback if there is one, queued otherwise
    // this.eventFncMappings = {};
    // this.chatServerEvents = [
    //     'message',
    //     'messageDeleted',
    //     'joined',
    //     'left',
    //     'roomdestroyed',
    //     'userDestroyed',
    //     'typing',
    //     'reidentify',
    //     'userdeleted',
    //     'chat-counts',
    //     'opInvite',
    //     'roomchanged',
    //     'roomclosed',
    //     'rooms',
    //     'onlineOperatorStatus',
    //     'opStatus',
    //     'serverNotice',
    //     'roomdetailschanged',
    //     'userSettings:change',
    //     'canned-responses:changed',
    //     'canned-responses:added',
    //     'canned-responses:deleted',
    //     'userOnboarding:change',
    //     'operator:refresh',
    //     'noOperatorJoined',
    //     'contact:changed',
    //     'affiliate:reviewed',
    //     'clientEvent' // All client events broadcast from api server. Should be used for all api events going forward.
    // ];
    // this.chatServerEvents.forEach((name) => {
    //     this.eventFncMappings[name] = (args) => {
    //         if (callCallback[name]) {
    //             callCallback[name].call(this, args);
    //         } else {
    //             callCallback.default.call(this, name, args);
    //         }
    //     };
    //     this.socket.on(name, this.eventFncMappings[name]);
    // });
    // this.socket.on("identify:success", () => {
    //     this.onIdentifySuccessCallback.call(this, true);
    // });
    // this.socket.on("message:send", () => {
    //     this.onIdentifySuccessCallback.call(this, true);
    // });

    this.onSocketMessage = this.onSocketMessage.bind(this);
    this.socket.on('message', this.onSocketMessage);
    this.socket.onreconnecting(function (error) {
      console.log("SIGNALR -- RECONNECTING EVENT: ".concat(error)); // eslint-disable-line no-console

      _this.trigger('connection:disconnected:socketio');
    });
    this.socket.onreconnected(function (connectionId) {
      console.log("SIGNALR -- RECONNECTED EVENT: ".concat(connectionId)); // eslint-disable-line no-console

      _this.trigger('connection:connected:socketio');
    });
    this.socket.onclose(function (error) {
      console.log("SIGNALR -- CLOSE EVENT: ".concat(error)); // eslint-disable-line no-console

      _this.trigger('connection:disconnected:socketio');
    });
    this.on('connection:retry:socketio', function () {
      return _this.socket.state === _microsoft_signalr_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_1__[/* HubConnectionState */ "b"].Connected ? _this.trigger('connection:connected:socketio') : _this.socket.start().then(onStart).catch(function (err) {
        return console.error(err.toString());
      }) // eslint-disable-line no-console
      ;
    });
  } // Chat Server Events


  _createClass(PureChat, [{
    key: "onSocketMessage",
    value: function onSocketMessage(event) {
      var messageType = event.messageType;

      if (messageType === 'identify:success') {
        this.onIdentifySuccess(event);
      } else if (messageType === 'message:send') {
        this.onMessageSend(event);
      } else if (messageType === 'message:deleted') {
        this.onMessageDeleted(event);
      } else if (messageType === 'operator:status') {
        this.onOperatorStatus(event);
      } else if (messageType === 'room:created') {
        this.onRoomCreated(event);
      } else if (messageType === 'room:joined') {
        this.onRoomJoined(event);
      } else if (messageType === 'room:left') {
        this.onRoomLeft(event);
      } else if (messageType === 'room:closed') {
        this.onRoomClosed(event);
      } else if (messageType === 'rooms:list') {
        this.onRoomList(event);
      } else if (messageType === 'room.attributes:changed') {
        this.onRoomAttributesChanged(event);
      } else if (messageType === 'typing') {
        this.onTyping(event);
      } else if (messageType === 'file') {
        this.onFile(event);
      } else if (messageType === 'invite') {
        this.onInvite(event);
      }
    }
  }, {
    key: "onIdentifySuccess",
    value: function onIdentifySuccess() {
      this.roomApiUserKey = 'participant:room';
      this.onIdentifySuccessCallback.call(this, true);
      this.trigger('connection:connected:socketio');
    }
  }, {
    key: "onMessageSend",
    value: function onMessageSend(event) {
      var participant = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyUser */ "b"])(event.participant);
      var room = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.room);
      var messageData = event.messageData;
      var messageDetails = {
        userDisplayName: participant.name,
        roomDisplayName: room.name,
        message: messageData.message,
        id: messageData.messageId,
        userId: participant.id,
        roomId: room.id,
        time: event.timeJs,
        isHistory: event.isHistory,
        timeElapsed: messageData.timeElapsed,
        protocolVersion: 1,
        avatarUrl: participant.avatar || purechat_content_images_avatars_visitor_png__WEBPACK_IMPORTED_MODULE_5___default.a,
        fromOperator: false,
        roomUtcOffset: 0,
        type: 0,
        status: 0
      };
      callCallback.message.call(this, messageDetails);
    }
  }, {
    key: "onMessageDeleted",
    value: function onMessageDeleted(args) {
      this.trigger('messageDeleted', _objectSpread({}, args, {
        roomId: parseInt(args.room.attributes.chatId, 10),
        messageId: args.messageData.messageId
      }));
    }
  }, {
    key: "onOperatorStatus",
    value: function onOperatorStatus(event) {
      var messageData = event.messageData;
      var messageDetails = {
        onlineOperatorStatus: {
          operators: messageData.operators.map(function (opStatus) {
            return _objectSpread({}, opStatus, {
              widgetStatus: {
                1: opStatus.available
              }
            });
          })
        }
      };
      callCallback.default.call(this, 'onlineOperatorStatus', messageDetails);
    }
  }, {
    key: "onRoomCreated",
    value: function onRoomCreated(event) {
      var room = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.messageData);
      callCallback.default.call(this, 'room:created', room);
    }
  }, {
    key: "onRoomJoined",
    value: function onRoomJoined(event) {
      var messageDataRoom = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.messageData.room);
      var user = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyUser */ "b"])(event.messageData.participant);

      if (!event.isHistory) {
        this.trigger('roomchanged', {
          action: 'joinedroom',
          room: messageDataRoom
        });
        this.trigger('room:joined', messageDataRoom);
      }

      var escapedUserDisplayName = (user.name || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      var escapedRoomDisplayName = messageDataRoom.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      this.trigger('joined', user.id, escapedUserDisplayName, messageDataRoom.id, escapedRoomDisplayName, event.time, event.isHistory);
    }
  }, {
    key: "onRoomAttributesChanged",
    value: function onRoomAttributesChanged(event) {
      var messageDataRoom = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.messageData);
      this.trigger('roomdetailschanged', messageDataRoom);
    }
  }, {
    key: "onRoomLeft",
    value: function onRoomLeft(event) {
      var messageDataRoom = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.messageData.room);
      var user = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyUser */ "b"])(event.messageData.participant);

      if (!event.isHistory) {
        this.trigger('roomchanged', {
          action: 'leftroom',
          room: messageDataRoom
        });
        this.trigger('room:left', messageDataRoom);
      }

      var escapedUserDisplayName = (user.name || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      var escapedRoomDisplayName = messageDataRoom.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      this.trigger('left', user.id, escapedUserDisplayName, messageDataRoom.id, escapedRoomDisplayName, event.time, event.isHistory);
    }
  }, {
    key: "onRoomClosed",
    value: function onRoomClosed(event) {
      var messageDataRoom = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.messageData.room);
      callCallback.default.call(this, 'room:closed', messageDataRoom);
      var escapedRoomDisplayName = messageDataRoom.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      this.trigger('roomdestroyed', messageDataRoom.id, escapedRoomDisplayName, event.time, event.isHistory);
    }
  }, {
    key: "onRoomList",
    value: function onRoomList(event) {
      this.trigger('rooms', {
        rooms: event.messageData.map(function (r) {
          return Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(r);
        })
      });
    }
  }, {
    key: "onTyping",
    value: function onTyping(event) {
      var participant = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyUser */ "b"])(event.participant);
      var room = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.room);
      var messageData = event.messageData;
      var escapedUserDisplayName = participant.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      this.trigger('typing', participant.id, escapedUserDisplayName, room.id, room.name, messageData.isTyping, event.time);
    }
  }, {
    key: "onInvite",
    value: function onInvite(event) {
      if (event.messageData.userId !== this.currentUserId) return;
      this.trigger('opInvite', event.messageData);
    }
  }, {
    key: "onFile",
    value: function onFile(event) {
      var participant = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyUser */ "b"])(event.participant);
      var room = Object(purechat_lib_legacy_conversion__WEBPACK_IMPORTED_MODULE_4__[/* convertToLegacyRoom */ "a"])(event.room);
      var messageData = event.messageData;
      var messageDetails = {
        userDisplayName: participant.name,
        roomDisplayName: room.name,
        message: messageData.message,
        id: messageData.id || messageData.messageId,
        userId: participant.id,
        roomId: room.id,
        time: event.timeJs,
        isHistory: event.isHistory,
        timeElapsed: messageData.timeElapsed,
        protocolVersion: 1,
        avatarUrl: '',
        fromOperator: false,
        roomUtcOffset: 0,
        type: messageData.messageType,
        status: messageData.status,
        serverId: event.id
      };
      callCallback.message.call(this, messageDetails);
    }
  }, {
    key: "getRemoteParticipantKey",
    value: function getRemoteParticipantKey(userId) {
      // this is pretty hacky.  need to pass the user type into the client
      var intId = Number(userId);
      return Number.isNaN(intId) ? "participant:purechat:contactid:".concat(userId) : "participant:purechat:userid:".concat(userId);
    }
  }, {
    key: "getRoomApiRoomKey",
    value: function getRoomApiRoomKey(roomType, roomId) {
      // todo fix ==.  currently roomType is a string
      var keyType = roomType == purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* RoomType */ "k"].Visitor ? 'chatid' : 'operatorids';
      return "room:purechat:".concat(keyType, ":").concat(roomId);
    }
  }, {
    key: "getAccountRoomKey",
    value: function getAccountRoomKey() {
      return "room:purechat:accountid:".concat(this.currentDomainId);
    }
  }, {
    key: "disconnect",
    value: function disconnect() {
      this.socket.off('message', this.onSocketMessage);
      this.socket.stop();
      this.roomApiUserKey = null;
      this.roomApiRoomKey = null;
      this.socket = null;
    }
  }, {
    key: "testWebsocketStatus",
    value: function testWebsocketStatus() {// todo
      // if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
      //     const socketError = 'socket not connected';
      //     console.log(socketError);
      //     throw socketError;
      // }
    }
  }, {
    key: "identify",
    value: function identify(userId, domainId, authToken, status, poppedOut, emailMD5Hash) {
      this.currentUserId = userId;
      this.currentDomainId = domainId;
      this.currentAuthToken = authToken;
      this.deviceType = purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* DeviceType */ "f"].Desktop;
      this.poppedOut = poppedOut;
      this.protocolVersion = '2.0';
      this.emailMD5Hash = emailMD5Hash;
      this.onIdentifySuccessCallback = status;
      this.testWebsocketStatus();
      var remoteKey = this.getRemoteParticipantKey(this.currentUserId);
      this.socket.invoke('action', {
        actionName: 'identify',
        actionMessage: {
          remoteKey: remoteKey,
          authType: 0,
          authCredentials: this.currentAuthToken
        }
      });
    }
  }, {
    key: "sendmessage",
    value: function sendmessage(message, roomId, roomType) {
      this.socket.invoke('action', {
        actionName: 'message:room',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(roomType, roomId),
          roomType: 'purechat:chat',
          messageType: 'message:send',
          messageData: {
            message: message,
            messageType: purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* ChatRecordType */ "c"].Message,
            messageId: new Date().getTime()
          }
        }
      });
    }
  }, {
    key: "deleteMessage",
    value: function deleteMessage(options) {
      if (!options.message) throw new TypeError('message is required');
      if (!options.message.serverId && !options.message.id) throw new TypeError('serverId is required');
      if (!options.roomId) throw new TypeError('roomId is required');
      if (!options.roomType) throw new TypeError('roomType is required');
      this.socket.invoke('action', {
        actionName: 'message:delete',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(options.roomType, options.roomId),
          messageId: options.message.serverId || options.message.id
        }
      });
    }
  }, {
    key: "upload",
    value: function upload(options, callback) {
      if (!_.has(options, 'roomId')) throw new TypeError('roomId is required');
      if (!_.has(options, 'roomType')) throw new TypeError('roomType is required');
      if (!_.has(options, 'status')) throw new TypeError('status is required');
      options.messageId = options.messageId || new Date().getTime();
      this.socket.invoke('action', {
        actionName: 'message:room',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(options.roomType, options.roomId),
          messageType: 'file',
          messageData: {
            id: options.messageId,
            fromOperator: false,
            messageType: 4,
            status: options.status,
            message: options.message
          }
        }
      }).then(function (response) {
        switch (options.status) {
          case purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* UploadStatuses */ "m"].Start:
          case purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* UploadStatuses */ "m"].Uploading:
            callback(true, {
              messageId: options.messageId
            }, http_status_codes__WEBPACK_IMPORTED_MODULE_0___default.a.OK, null);
            break;

          case purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* UploadStatuses */ "m"].Unauthorized:
            callback(true, {
              messageId: options.messageId
            }, http_status_codes__WEBPACK_IMPORTED_MODULE_0___default.a.UNAUTHORIZED, null);
            break;

          case purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* UploadStatuses */ "m"].Error:
            callback(true, {
              messageId: options.messageId
            }, http_status_codes__WEBPACK_IMPORTED_MODULE_0___default.a.BAD_REQUEST, null);
            break;

          case purechat_constants__WEBPACK_IMPORTED_MODULE_3__[/* UploadStatuses */ "m"].Complete:
            callback(true, {
              messageId: options.messageId,
              serverId: response.messageId
            }, http_status_codes__WEBPACK_IMPORTED_MODULE_0___default.a.OK, null);
            break;
        }
      });
    }
  }, {
    key: "sendtyping",
    value: function sendtyping(roomId, roomType, isTyping) {
      this.socket.invoke('action', {
        actionName: 'message:room',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(roomType, roomId),
          messageType: 'typing',
          messageData: {
            userId: this.currentUserId,
            isTyping: isTyping
          }
        }
      });
    }
  }, {
    key: "join",
    value: function join(args) {
      this.socket.invoke('action', {
        actionName: 'room:join',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(args.roomType, args.roomId),
          remoteParticipantKey: this.remoteParticipantKey,
          visible: !args.invisible
        }
      });
    }
  }, {
    key: "leave",
    value: function leave(roomId, roomType) {
      this.socket.invoke('action', {
        actionName: 'room:leave',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(roomType, roomId),
          remoteParticipantKey: this.remoteParticipantKey
        }
      });
    }
  }, {
    key: "closeroom",
    value: function closeroom(roomId, roomType) {
      this.socket.invoke('action', {
        actionName: 'room:close',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(roomType, roomId)
        }
      });
    }
  }, {
    key: "destroyself",
    value: function destroyself(roomId, roomType, status, args) {
      this.closeroom(roomId, roomType, status);
    }
  }, {
    key: "createoperatorroom",
    value: function createoperatorroom(roomName, userIds, status, visitorEmailHash, visitorAvatarUrl) {
      userIds.push(this.currentUserId);
      userIds.sort();
      var operatorRoomId = userIds.join('_');
      var participantRemoteKeys = userIds.map(function (id) {
        return "participant:purechat:userid:".concat(id);
      });
      this.socket.invoke('action', {
        actionName: 'room:create',
        actionMessage: {
          name: roomName,
          roomType: 'purechat:operator',
          accountRoomRemoteKey: "room:purechat:accountid:".concat(this.currentDomainId),
          remoteRooms: [{
            remoteKey: "room:purechat:operatorids:".concat(operatorRoomId),
            remoteRoomName: roomName
          }],
          attributes: {
            operatorRoomId: operatorRoomId
          },
          participantRemoteKeys: participantRemoteKeys
        }
      });
    }
  }, {
    key: "sendcurrentstate",
    value: function sendcurrentstate() {
      this.socket.invoke('action', {
        actionName: 'sendRooms',
        actionMessage: {
          accountRemoteRoomKey: "room:purechat:accountid:".concat(this.currentDomainId),
          roomTypes: ['purechat:chat', 'purechat:operator']
        }
      });
    }
  }, {
    key: "getuser",
    value: function getuser(status) {// this.socket.emit('getuser', status);
    }
  }, {
    key: "getusers",
    value: function getusers(status) {// this.socket.emit('getusers', status);
    }
  }, {
    key: "sendroomhistory",
    value: function sendroomhistory(roomId, roomType, status) {
      this.socket.invoke('action', {
        actionName: 'room:history',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(roomType, roomId)
        }
      });
    }
  }, {
    key: "forcedisconnect",
    value: function forcedisconnect(userId, connectionId, statusCallback) {// this.socket.emit('forcedisconnect', { 'userId': userId, 'connectionId': connectionId }, statusCallback);
    }
  }, {
    key: "startdemo",
    value: function startdemo(widgetId, statusCallback) {// this.socket.emit('startdemo', { 'widgetId': widgetId }, statusCallback);
    }
  }, {
    key: "sendInvite",
    value: function sendInvite(userId, roomId, roomName, fromName, roomType) {
      this.socket.invoke('action', {
        actionName: 'message:room',
        actionMessage: {
          remoteRoomKey: this.getAccountRoomKey(),
          messageType: 'invite',
          messageData: {
            userId: userId,
            roomId: roomId,
            roomType: roomType,
            roomDisplayName: roomName,
            fromName: fromName
          }
        }
      });
    }
  }, {
    key: "setVisitorDetails",
    value: function setVisitorDetails(roomId, roomType, details, statusCallback) {
      // this.socket.emit('setvisitordetails', { 'roomId': roomId, 'details': details }, statusCallback);
      this.socket.invoke('action', {
        actionName: 'room:attributes',
        actionMessage: {
          remoteRoomKey: this.getRoomApiRoomKey(roomType, roomId),
          attributes: details
        }
      });
    }
  }, {
    key: "on",
    value: function on(name, callback, context) {
      if (!Object(_event_api_js__WEBPACK_IMPORTED_MODULE_6__[/* eventsApi */ "a"])(this, 'on', name, [callback, context]) || !callback) return this;
      this.events = this.events || {};
      var events = this.events[name] || (this.events[name] = []);
      events.push({
        callback: callback,
        context: context,
        ctx: context || this
      });
      return this;
    } // Bind an event to only be triggered a single time. After the first time
    // the callback is invoked, it will be removed.

  }, {
    key: "once",
    value: function once(name, callback, context) {
      var _this2 = this,
          _arguments = arguments;

      if (!Object(_event_api_js__WEBPACK_IMPORTED_MODULE_6__[/* eventsApi */ "a"])(this, 'once', name, [callback, context]) || !callback) return this;

      var once = _.once(function () {
        _this2.off(name, once);

        callback.apply(_this2, _arguments);
      });

      once._callback = callback;
      return this.on(name, once, context);
    } // Remove one or many callbacks. If `context` is null, removes all
    // callbacks with that function. If `callback` is null, removes all
    // callbacks for the event. If `name` is null, removes all bound
    // callbacks for all events.

  }, {
    key: "off",
    value: function off(name, callback, context) {
      var retain;
      var ev;
      var events;
      if (!this.events || !Object(_event_api_js__WEBPACK_IMPORTED_MODULE_6__[/* eventsApi */ "a"])(this, 'off', name, [callback, context])) return this;

      if (!name && !callback && !context) {
        this.events = void 0;
        return this;
      }

      var names = name ? [name] : _.keys(this.events);
      var i, l;

      for (i = 0, l = names.length; i < l; i++) {
        name = names[i];
        events = this.events[name];

        if (events) {
          this.events[name] = retain = [];

          if (callback || context) {
            var j = void 0,
                k = void 0;

            for (j = 0, k = events.length; j < k; j++) {
              ev = events[j];

              if (callback && callback !== ev.callback && callback !== ev.callback._callback || context && context !== ev.context) {
                retain.push(ev);
              }
            }
          }

          if (!retain.length) delete this.events[name];
        }
      }

      return this;
    } // Trigger one or many events, firing all bound callbacks. Callbacks are
    // passed the same arguments as `trigger` is, apart from the event name
    // (unless you're listening on `"all"`, which will cause your callback to
    // receive the true name of the event as the first argument).

  }, {
    key: "trigger",
    value: function trigger(name) {
      if (!this.events) return this;
      var args = slice.call(arguments, 1);
      if (!Object(_event_api_js__WEBPACK_IMPORTED_MODULE_6__[/* eventsApi */ "a"])(this, 'trigger', name, args)) return this;
      var events = this.events[name];
      var allEvents = this.events.all;
      if (events) Object(_event_api_js__WEBPACK_IMPORTED_MODULE_6__[/* triggerEvents */ "b"])(events, args);
      if (allEvents) Object(_event_api_js__WEBPACK_IMPORTED_MODULE_6__[/* triggerEvents */ "b"])(allEvents, arguments);
      return this;
    } // Tell this object to stop listening to either specific events ... or
    // to every object it's currently listening to.

  }, {
    key: "stopListening",
    value: function stopListening(obj, name, callback) {
      var listeningTo = this._listeningTo;
      if (!listeningTo) return this;
      var remove = !name && !callback;
      if (!callback && _typeof(name) === 'object') callback = this;
      if (obj) (listeningTo = {})[obj._listenId] = obj;

      for (var id in listeningTo) {
        obj = listeningTo[id];
        obj.off(name, callback, this);
        if (remove || _.isEmpty(obj.events)) delete this._listeningTo[id];
      }

      return this;
    }
  }]);

  return PureChat;
}();

/* harmony default export */ __webpack_exports__["a"] = (PureChat);
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return convertToLegacyUser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return convertToLegacyRoom; });
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

// The enum is here instead of in constants because this file is imported in both the legacy and
// modern widget. Just in case there's something in that file we don't want to expose to the widgets.
var RoomType = {
  Account: 0,
  Operator: 1,
  Visitor: 2
};
var convertToLegacyUser = function convertToLegacyUser(user) {
  var legacyUser = _objectSpread({}, user, {
    displayName: user.name,
    isOperator: user.participantType === 'purechat:operator',
    isInvisibleInRoom: !user.visibleInRoom
  });

  if (legacyUser.participantType === 'purechat:visitor') legacyUser.id = legacyUser.attributes.contactId;

  if (legacyUser.participantType === 'purechat:operator') {
    legacyUser.id = parseInt(legacyUser.attributes.userId, 10);
    legacyUser.avatar = legacyUser.attributes.avatarUrl;
  }

  return legacyUser;
};
var convertToLegacyRoom = function convertToLegacyRoom(room) {
  if (!room) return null;

  var legacyRoom = _objectSpread({}, room, {}, room.attributes);

  if (legacyRoom.participants) {
    legacyRoom.users = legacyRoom.participants.map(function (p) {
      return convertToLegacyUser(p);
    });
  }

  legacyRoom.legacyRoomName = legacyRoom.name;
  legacyRoom.time = legacyRoom.createDate;
  legacyRoom.timeSinceChatStart = 0 - legacyRoom.createDate;
  legacyRoom.timeElapsed = (new Date().getTime() - legacyRoom.createDate * 1000) / 1000;
  legacyRoom.widgetType = parseInt(legacyRoom.attributes.widgetType, 10);
  legacyRoom.visitorCustomerId = legacyRoom.attributes.visitorCustomerId;

  if (legacyRoom.roomType === 'purechat:account') {
    legacyRoom.id = legacyRoom.attributes.accountId;
    legacyRoom.roomType = RoomType.Account;
  } else if (legacyRoom.roomType === 'purechat:chat') {
    legacyRoom.id = parseInt(legacyRoom.attributes.chatId, 10);
    legacyRoom.roomType = RoomType.Visitor;
  } else if (legacyRoom.roomType === 'purechat:operator') {
    legacyRoom.id = legacyRoom.attributes.operatorRoomId;
    legacyRoom.roomType = RoomType.Operator;
  }

  legacyRoom.GeolocationData = {
    City: room.attributes.city,
    State: room.attributes.state,
    CountryAbbreviation: room.attributes.countryAbbreviation,
    Country: room.attributes.country,
    Latitude: room.attributes.latitude,
    Longitude: room.attributes.longitude
  };
  return legacyRoom;
};module.exports = __webpack_require__.p + "visitor.b84d3b849f17f523051e.png";/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return triggerEvents; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return eventsApi; });
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

 // Regular expression used to split event strings.

var EVENT_SPLITTER = /\s+/; // A difficult-to-believe, but optimized internal dispatch function for
// triggering events. Tries to keep the usual cases speedy (most internal
// Backbone events have 3 arguments).

var triggerEvents = function triggerEvents(events, args) {
  var ev,
      i = -1,
      l = events.length,
      a1 = args[0],
      a2 = args[1],
      a3 = args[2]; // eslint-disable-line no-magic-numbers

  switch (args.length) {
    case 0:
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx);
      }

      return;

    case 1:
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx, a1);
      }

      return;

    case 2:
      // eslint-disable-line no-magic-numbers
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx, a1, a2);
      }

      return;

    case 3:
      // eslint-disable-line no-magic-numbers
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx, a1, a2, a3);
      }

      return;

    default:
      while (++i < l) {
        (ev = events[i]).callback.apply(ev.ctx, args);
      }

  }
}; // Implement fancy features of the Events API such as multiple event
// names `"change blur"` and jQuery-style event maps `{change: action}`
// in terms of the existing API.

var eventsApi = function eventsApi(obj, action, name, rest) {
  if (!name) return true; // Handle event maps.

  if (_typeof(name) === 'object') {
    for (var key in name) {
      obj[action].apply(obj, [key, name[key]].concat(rest));
    }

    return false;
  } // Handle space separated event names.


  if (EVENT_SPLITTER.test(name)) {
    var names = name.split(EVENT_SPLITTER);

    for (var i = 0, l = names.length; i < l; i++) {
      obj[action].apply(obj, [names[i]].concat(rest));
    }

    return false;
  }

  return true;
};/* (ignored) */var _instance = null;
/* harmony default export */ __webpack_exports__["a"] = ({
  setInstance: function setInstance(instance) {
    _instance = instance;
    return _instance;
  },
  getInstance: function getInstance() {
    return _instance;
  }
});/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var no_conflict__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* harmony import */ var _pc_data__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216);
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }





var DashboardDataController =
/*#__PURE__*/
function (_PCDataController) {
  _inherits(DashboardDataController, _PCDataController);

  function DashboardDataController(options) {
    var _this;

    _classCallCheck(this, DashboardDataController);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(DashboardDataController).call(this, options));
    _this.chatServerConnection = options.chatServerConnection;
    return _this;
  }

  _createClass(DashboardDataController, [{
    key: "closeChat",
    value: function closeChat() {
      this.chatServerConnection.closeroom(this.connectionInfo.get('roomId'), this.connectionInfo.get('roomType'));
      this.sentChatRequest = false;
      return jquery__WEBPACK_IMPORTED_MODULE_0___default.a.Deferred().resolve();
    }
  }, {
    key: "connectToChatServer",
    value: function connectToChatServer(bindTo) {
      var d = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.Deferred();
      if (bindTo) this.bindEvents(bindTo);
      return d.resolve();
    }
  }, {
    key: "htmlEncode",
    value: function htmlEncode(value) {
      return jquery__WEBPACK_IMPORTED_MODULE_0___default()('<div/>').text(value).html();
    }
  }, {
    key: "getPreviousChat",
    value: function getPreviousChat(options) {
      var _this2 = this;

      var d = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.Deferred();

      var defaultedOptions = no_conflict__WEBPACK_IMPORTED_MODULE_1__[/* _ */ "c"].defaults(options, {
        includeMessages: true,
        previousCount: 1
      });

      jquery__WEBPACK_IMPORTED_MODULE_0___default.a.ajax({
        url: "".concat(this.getOption('apiServerUrl'), "/api/transcripts/related/").concat(defaultedOptions.chatId),
        dataType: 'json',
        data: defaultedOptions,
        type: 'get',
        success: function success(data) {
          var updated = data.map(function (nextChat) {
            return _objectSpread({}, nextChat, {
              Records: nextChat.Records.map(function (next) {
                return _objectSpread({}, next, {
                  Message: _this2.htmlEncode(next.Message)
                });
              })
            });
          });
          d.resolve(updated);
        },
        error: function error() {
          return d.resolve(null);
        }
      });
      return d.promise();
    }
  }, {
    key: "getWidgetSettings",
    value: function getWidgetSettings() {
      var _this3 = this;

      var d = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.Deferred();
      jquery__WEBPACK_IMPORTED_MODULE_0___default.a.ajax({
        url: "".concat(this.getOption('apiServerUrl'), "/User/DashboardSettings"),
        dataType: 'json',
        type: 'post',
        xhrFields: {
          withCredentials: true
        },
        crossDomain: true,
        headers: {
          'X-Requested-With': 'XMLHttpRequest'
        },
        success: function success(data) {
          d.resolve({
            success: true,
            authToken: data.authToken,
            version: '',
            accountId: data.accountId,
            userId: data.userId,
            position: null,
            widgetType: null,
            widgetConfig: data,
            resources: _this3.getOption('resources'),
            googleAnalytics: null,
            chatServerUrl: data.chatServerUrl
          });
        }
      });
      return d.promise();
    }
  }, {
    key: "checkInRoom",
    value: function checkInRoom() {
      return !!this.connectionInfo.get('roomId');
    }
  }]);

  return DashboardDataController;
}(_pc_data__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"]);

/* harmony default export */ __webpack_exports__["a"] = (DashboardDataController);/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return pc_; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return backbone; });
/* unused harmony export $ */
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return marionette; });
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var backbone__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
/* harmony import */ var backbone__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(backbone__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var marionette__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12);
/* harmony import */ var marionette__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(marionette__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var backbone_relational__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(154);
/* harmony import */ var backbone_relational__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(backbone_relational__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var socket_io_client__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(316);
/* harmony import */ var socket_io_client__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(socket_io_client__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _plugins_jquery_purechat_display__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(638);
/* harmony import */ var _plugins_jquery_purechat_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(639);







var host = window.location.hostname;
var isPureChat = /purechat\.(com|me)$/.test(host) && host.indexOf('test.purechat.com') < 0;
var $ = isPureChat ? window.pc$ || window.$ : window.pc$;
var pc_ = isPureChat ? underscore__WEBPACK_IMPORTED_MODULE_0___default.a : underscore__WEBPACK_IMPORTED_MODULE_0___default.a.noConflict();
var backbone = isPureChat ? backbone__WEBPACK_IMPORTED_MODULE_1___default.a : backbone__WEBPACK_IMPORTED_MODULE_1___default.a.noConflict();
var marionette = isPureChat ? marionette__WEBPACK_IMPORTED_MODULE_2___default.a : marionette__WEBPACK_IMPORTED_MODULE_2___default.a.noConflict();
window.JSON3.noConflict();
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);

var displayClasses = ['purechat-display-inline-block', 'purechat-display-flex', 'purechat-display-block', 'purechat-display-none'];

function removeClass(el, className) {
  if (!el.classList || el.tagName.toLowerCase() === 'svg') {
    var classAttribute = el.getAttribute('class') || '';
    var classList = classAttribute.split(' ');
    var matchedIndex = classList.indexOf(className);

    if (matchedIndex > -1) {
      classList.splice(matchedIndex, 1);
      el.setAttribute('class', classList.join(' '));
    }
  } else {
    el.classList.remove(className);
  }
}

function addClass(el, className) {
  if (!el.classList || el.tagName.toLowerCase() === 'svg') {
    var classAttribute = el.getAttribute('class') || '';
    var classList = classAttribute.split(' ');
    var matchedIndex = classList.indexOf(className);

    if (matchedIndex > -1) {
      return;
    } else {
      classList.push(className);
      el.setAttribute('class', classList.join(' '));
    }
  } else {
    el.classList.add(className);
  }
}

jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.purechatDisplay = function (cssDisplayValue) {
  return this.each(function (index, el) {
    if (!el) return; // Always remove the display classes, even if no displayClass is given
    // this.removeClass(displayClasses.join(' '));
    // IE doesn't support removing multiple classes at the same time

    displayClasses.forEach(function (className) {
      removeClass(el, className);
    });
    if (!cssDisplayValue) return;
    var displayClass = "purechat-display-".concat(cssDisplayValue);
    if (displayClasses.indexOf(displayClass) === -1) return;
    addClass(el, displayClass);
  });
};

jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.xshow = function () {
  this.purechatDisplay.call(this);
};

jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.xhide = function () {
  this.purechatDisplay.call(this, 'none');
};/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);

var unitlessProperties = ['animationIterationCount', 'columnCount', 'fillOpacity', 'flexGrow', 'flexShrink', 'fontWeight', 'lineHeight', 'opacity', 'order', 'orphans', 'widows', 'zIndex', 'zoom'];
var $css = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.css;
var $height = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.height;
var $width = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.width; // Add px to all number properties except the ones that can be unitless	

function numberToPx(value) {
  if (typeof value === 'number') {
    if (unitlessProperties.indexOf(value) === -1) {
      return "".concat(value, "px");
    }
  }

  return value;
}

function hyphenate(value) {
  return value.replace(/([A-Z])/g, function (g) {
    return "-".concat(g[0].toLowerCase());
  });
}

jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.purechatCss = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.xcss = function (name, value) {
  // Handle getter
  if (arguments.length === 1 && typeof name === 'string') {
    return $css.apply(this, arguments);
  }

  var el = this.get(0);
  if (!el) return this;
  value = numberToPx(value);

  if (typeof name === 'string') {
    el.style.setProperty(name, value, 'important');
  } else if (jquery__WEBPACK_IMPORTED_MODULE_0___default.a.isPlainObject(name)) {
    var props = name;
    var prop = null;

    for (prop in props) {
      if (!props.hasOwnProperty(prop)) continue;
      value = ['z-index', 'zIndex'].indexOf(prop) < 0 ? numberToPx(props[prop]) : props[prop];
      var hyphenatedProp = hyphenate(prop);
      var ruleRegex = new RegExp(escape(hyphenatedProp) + '\\s*:\\s*' + escape(value) + '(\\s*;)?', 'gmi');
      var rule = "".concat(hyphenatedProp, ":").concat(value, " !important;"); // Wipe out the existing rule and set it to the new value
      // This is the most reliable cross-browser way because it doesn't
      // use setProperty and avoids the bug where setting !important on
      // an existing property doesn't work.

      el.style.cssText = el.style.cssText.replace(ruleRegex, '');
      el.style.cssText += rule;
    }
  }

  return this;
};

jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.purechatHeight = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.height = function (height) {
  if (arguments.length === 0 || typeof height === 'boolean') {
    return $height.apply(this, arguments);
  }

  return this.purechatCss('height', height);
};

jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.purechatWidth = jquery__WEBPACK_IMPORTED_MODULE_0___default.a.fn.width = function (width) {
  if (arguments.length === 0 || typeof width === 'boolean') {
    return $width.apply(this, arguments);
  }

  return this.purechatCss('width', width);
};var Constants = {};
Constants.WidgetType = {
  Tab: 1,
  Button: 2,
  Image: 3,
  ImageTab: 4
};
Constants.BasicWidgetType = 1;
Constants.WidgetStates = {
  Initializing: 'PCStateInitializing',
  Inactive: 'PCStateInactive',
  Activating: 'PCStateActivating',
  Chatting: 'PCStateChatting',
  Closed: 'PCStateClosed',
  Unavailable: 'PCStateUnavailable',
  Unsupported: 'PCStateUnsupported',
  EmailForm: 'PCStateEmailForm'
};
Constants.Features = {
  VisitorTracking: 1
};
Constants.FeatureStatus = {
  Disabled: 0,
  Enabled: 1,
  Off: -1
};
Constants.MobileDisplayTypes = {
  Hidden: 0,
  SameAsDesktop: 1,
  MobileOptimized: 2
};
Constants.EmailButtonBehaviors = {
  ShowEmailForm: 0,
  ShowEmailAddress: 1
};
Constants.UnavailableBehaviors = {
  HideWidget: 0,
  ShowMessage: 1,
  ShowEmail: 2
};
Constants.WidgetPosition = {
  BottomLeft: 1,
  BottomRight: 2,
  TopLeft: 3,
  TopRight: 4
};
Constants.BackgroundTypes = {
  Custom: 1,
  Stock: 2,
  color: 3
};
Constants.StyleTypes = {
  Minimal: 0,
  Classic: 1,
  Mobile: 2
}; // Indexes map directly to StyleTypesEnums

Constants.StyleTypesMappings = ['purechat-style-minimal', 'purechat-style-classic', 'purechat-style-mobile', 'purechat-style-mobile'];
Constants.KeyCodes = {
  Enter: 13,
  Escape: 27,
  LeftArrow: 37,
  UpArrow: 38,
  RightArrow: 39,
  DownArrow: 40,
  Tab: 9
};
Constants.UploadStatuses = {
  Start: 0,
  Uploading: 1,
  Unauthorized: 2,
  Error: 3,
  Complete: 4
};
Constants.UploadErrorMessages = {
  default: 'File Send Failed',
  401: 'You are not authorized to upload.',
  413: 'This file is too large. 10MB Limit.',
  415: 'This file type is not supported.'
};
Constants.MessageTypes = {
  Message: 0,
  Join: 1,
  Leave: 2,
  Close: 3,
  File: 4,
  Separator: 1000,
  Note: 1001,
  UnfurlLink: 2000,
  UnfurlFile: 2001,
  UnfurlImage: 2002,
  UnfurlGiphy: 2003,
  UnfurlTwitter: 2004,
  UnfurlYoutube: 2005
};
Constants.ClosedReasonCodes = {
  ClosedByUser: 0,
  ConnectionTimeout: 1,
  Inactivity: 2,
  ClosedByOperator: 3,
  NoOperatorJoined: 4
};
Constants.MessageSortOrders = {
  Message: 0,
  Closed: 1
};
Constants.HubspotCookieName = 'hubspotutk';
Constants.MarkdownFields = ['closed_message', 'emailForm_message', 'error_noOperators', 'label_initial', 'emailForm_success_message'];
Constants.RoomType = {
  Account: 0,
  Operator: 1,
  Visitor: 2
};
/* harmony default export */ __webpack_exports__["a"] = (Constants);/* harmony import */ var no_conflict__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }



var Message = no_conflict__WEBPACK_IMPORTED_MODULE_0__[/* Backbone */ "a"].RelationalModel.extend({
  sortOrder: _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageSortOrders.Message,
  events: {
    'change:messageResource': function changeMessageResource() {}
  },
  getTypeString: function getTypeString() {
    switch (this.get('type')) {
      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.UnfurlLink:
        return 'unfurl-link';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.UnfurlImage:
        return 'unfurl-image';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.UnfurlGiphy:
        return 'unfurl-giphy';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.UnfurlYoutube:
        return 'unfurl-youtube';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.UnfurlTwitter:
        return 'unfurl-twitter';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.File:
        return 'file';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.Closed:
        return 'closed';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.Note:
        return 'note';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.Separator:
        return 'separator';

      case _constants__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].MessageTypes.Message:
      default:
        return 'message';
    }
  },
  parseMessage: function parseMessage() {
    var message = this.get('message');
    if (!message) return {};
    var FILE_MESSAGE_REGEX = /(.*)\((http.*)\)\s(.*)\s•\s(.*)/;
    var matches = message.match(FILE_MESSAGE_REGEX);
    if (!matches) return {};

    var _ref = matches || [],
        _ref2 = _slicedToArray(_ref, 5),
        name = _ref2[1],
        url = _ref2[2],
        size = _ref2[3],
        mimeType = _ref2[4];

    return {
      name: name,
      url: url,
      size: size,
      mimeType: mimeType
    };
  }
});
/* harmony default export */ __webpack_exports__["a"] = (Message);__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = ({
  linkify: /(^|&nbsp;|\s)(www\.)?(?=[a-zA-Z0-9])(([-a-zA-Z0-9@:%_\+//=]){1,256}\.)+([a-zA-Z]{2,15})\b(:[0-9]{2,})?([?/#]([-a-zA-Z0-9,@:%_\+.~#!?&//=\[\]]|[^\x00-\x7F])*)?/gim,
  email: /^[a-zA-Z]([a-zA-Z0-9\._%\+\-])*@([a-zA-Z0-9\.\-])*\.[a-zA-Z]{2,10}$/,
  brTags: /(<br>|<br\/>)/gi,
  tagRemoval: /<.+?>/g,
  fileMessage: /(.*)\((http.*)\)\s\S(.*)\s•\s(.*)/
});/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(config__WEBPACK_IMPORTED_MODULE_2__);



var RETRY_INTERVAL = 60000; // 1 minute

var MAX_CHAR_LIMIT = 75;
var INCREASED_MAX_CHAR_LIMIT = 150;
var LEVELS = {
  TRACE: 10000,
  DEBUG: 20000,
  INFO: 30000,
  WARN: 40000,
  ERROR: 50000,
  FATAL: 60000
}; // If you want everything to be logged, set this to `Number.MAX_VALUE`. If you
// want nothing to be logged, set this to `Number.MIN_VALUE`.

var DEFAULT_LOG_LEVEL = LEVELS.INFO;
var logLevel = DEFAULT_LOG_LEVEL;
var retryId = null;
var messageQueue = [];

function send(data) {
  return jquery__WEBPACK_IMPORTED_MODULE_1___default.a.ajax({
    url: "".concat(config__WEBPACK_IMPORTED_MODULE_2___default.a.apiUrl, "/ajaxlogger/log"),
    method: 'POST',
    data: data,
    timeout: 20000,
    crossDomain: {
      crossDomain: true
    },
    // Setup ajax prefilters for CORS
    xhrFields: {
      withCredentials: true
    }
  }).done(function () {}).fail(function () {});
}

function startRetry() {
  retryId = setInterval(function () {
    // Grab the oldest message in the queue, attempt to send it off. If,
    // successful, send the rest of the messages. If not, just continue
    // the interval.
    var oldest = underscore__WEBPACK_IMPORTED_MODULE_0___default.a.first(messageQueue);

    send(oldest).then(function () {
      // AJAX call was successful, do the rest of the stuff
      clearInterval(retryId);
      retryId = null; // Remove item that we just sent and send the rest

      messageQueue.shift();

      while (messageQueue.length > 0) {
        var next = underscore__WEBPACK_IMPORTED_MODULE_0___default.a.first(messageQueue);

        messageQueue.shift(); // This `send` is ok to be fire-and-forget so no `await` is necessary

        send(next);
      }
    });
  }, RETRY_INTERVAL);
}

function logHandler(level, message, stackTrace, increaseCharacterLimit, chatServerUrl, accountId) {
  if (underscore__WEBPACK_IMPORTED_MODULE_0___default.a.isString(level)) level = LEVELS[level]; // Only log messages that are of higher or equal level than what was set as
  // the default.

  if (level >= logLevel) {
    var charLimit = increaseCharacterLimit ? INCREASED_MAX_CHAR_LIMIT : MAX_CHAR_LIMIT;
    var stack = stackTrace ? window.encodeURIComponent(stackTrace.substr(0, charLimit)) : null;
    var chatServer = chatServerUrl ? window.encodeURIComponent(chatServerUrl) : 'N/A';
    var data = {
      level: level.toString(),
      message: message,
      stackTrace: stack,
      chatServerUrl: chatServer,
      accountId: accountId,
      timestamp: new Date().toISOString()
    }; // If there's messages in the queue from before, safe to assume the
    // retry is running so just push this log message onto the queue.

    if (messageQueue.length > 0) {
      messageQueue.push(data);
      if (!retryId) startRetry();
    } else {
      send(data).fail(function () {
        messageQueue.push(data);
        startRetry();
      });
    }
  }
}

/* harmony default export */ __webpack_exports__["a"] = ({
  log: logHandler,
  LEVELS: LEVELS,
  setLogLevel: function setLogLevel(level) {
    logLevel = level;
  }
});module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='';
 if (obj.isNote()) { 
__p+='\r\n	<span class="purechat-message-note purechat-important" data-username="'+
((__t=( obj.username ))==null?'':__t)+
'" data-resourcekey="'+
((__t=( obj.resourceKey || '' ))==null?'':__t)+
'">\r\n		'+
((__t=( obj.message ))==null?'':__t)+
'\r\n	</span>\r\n';
 } else if (obj.isSeparator()) { 
__p+='\r\n	<span class="purechat-important purechat-separator" data-username="'+
((__t=( obj.username ))==null?'':__t)+
'" data-resourcekey="'+
((__t=( obj.resourceKey || '' ))==null?'':__t)+
'">\r\n		'+
((__t=( obj.message ))==null?'':__t)+
'\r\n	</span>\r\n';
 } else if (obj.isMessage() && obj.message) { 
__p+='\r\n	<div data-resourcekey="'+
((__t=( obj.resourceKey || '' ))==null?'':__t)+
'" class="purechat-message-container '+
((__t=( obj.myMessage ? 'purechat-message-right' : 'purechat-message-left' ))==null?'':__t)+
'">\r\n		<img class="purechat-operator-gravatar" height="50" width="50" src="'+
((__t=( obj.avatarUrl ))==null?'':__t)+
'" alt=""/>\r\n		<div class="purechat-message">\r\n			';
 if (obj.userName) { 
__p+='\r\n			<span class="purechat-displayname ';
 if (obj.hasMultipleOperators()) { 
__p+='purechat-display-block';
 } 
__p+='">'+
((__t=( obj.userName ))==null?'':__t)+
'</span>\r\n			';
 } 
__p+='\r\n			<span class="purechat-message-actual">\r\n				<span class="purechat-new-thought">\r\n					'+
((__t=( obj.enhance(obj.message) ))==null?'':__t)+
'\r\n				</span>\r\n			</span>\r\n			<div class="purechat-message-tail">\r\n				<svg viewBox="0 0 18 16" class="pc-svgicon">\r\n					<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#'+
((__t=( obj.myMessage ? 'pc-svgicon-tail-right' : 'pc-svgicon-tail-left' ))==null?'':__t)+
'"></use>\r\n				</svg>\r\n			</div>\r\n		</div>\r\n		<div class="purechat-timestamp">\r\n			';
 if(obj.time) { 
__p+='<time class="purechat-time" title="'+
((__t=( obj.date ))==null?'':__t)+
'" datetime="'+
((__t=( obj.date ))==null?'':__t)+
'">'+
((__t=( obj.prettyDate(obj.date) ))==null?'':__t)+
'</time>';
 } 
__p+='\r\n		</div>\r\n	</div>\r\n';
 } 
__p+='\r\n';
}
return __p;
};
/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div data-resourcekey="closed_message">'+
((__t=( obj.getResource('closed_message') ))==null?'':__t)+
'</div>\r\n';
 if (obj.AskForRating) { 
__p+='\r\n<div class="purechat-thumbs-container">\r\n	<p data-resourcekey="closed_askForRating">'+
((__t=( obj.getResource('closed_askForRating') ))==null?'':_.escape(__t))+
'</p>\r\n	<div class="purechat-thumbs purechat-thumbs-up purechat-thumbs-selectable">\r\n		<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-xl">\r\n			<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-happy-face"></use>\r\n		</svg>\r\n	</div>\r\n	<div class="purechat-thumbs purechat-thumbs-down purechat-thumbs-selectable">\r\n		<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-xl">\r\n			<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-sad-face"></use>\r\n		</svg>\r\n	</div>\r\n</div>\r\n<p class="purechat-rating-thanks"></p>\r\n';
 } 
__p+='\r\n\r\n';
 if (obj.CtaButton) { 
__p+='\r\n<p class="purechat-form purechat-ended-form" action="">\r\n	<a href="'+
((__t=( obj.ctaUrl() ))==null?'':__t)+
'" data-resourcekey="button_cta" class="purechat-btn" target="_blank">'+
((__t=( obj.getResource('button_cta') ))==null?'':_.escape(__t))+
'</a>\r\n</p>\r\n';
 } 
__p+='\r\n';
 if (obj.DownloadTranscript) { 
__p+='\r\n<p class="purechat-download-container">\r\n	<a data-resourcekey="closed_downloadTrans" target="_blank" href="'+
((__t=( obj.apiUrl ))==null?'':__t)+
'/api/VisitorWidget/Transcript?chatId='+
((__t=((obj.dataController || obj.oldDataController).connectionInfo.get('chatId')))==null?'':__t)+
'&authToken='+
((__t=((obj.dataController || obj.oldDataController).connectionInfo.get('authToken')))==null?'':__t)+
'">'+
((__t=( obj.getResource('closed_downloadTrans') ))==null?'':_.escape(__t))+
'</a>\r\n</p>\r\n';
 } 
__p+='\r\n\r\n';
 if (obj.showPoweredBy) { 
__p+='\r\n<p class="purechat-poweredby-text">\r\n	Love chatting? Add <a class="purechat-poweredby-link" href="'+
((__t=( obj.poweredByUrl ))==null?'':__t)+
'" rel="noopener" target="_blank">Pure Chat</a> to your site for free!\r\n</p>\r\n';
 } 
__p+='\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div data-resourcekey="'+
((__t=( obj.parent.get('resourceKey') || '' ))==null?'':__t)+
'" class="purechat-message-container '+
((__t=( obj.parent.get('myMessage') ? 'purechat-message-right' : 'purechat-message-left' ))==null?'':__t)+
'">\r\n	<div class="purechat-message">\r\n		<div class="purechat-message-actual">\r\n			<div class="purechat-new-thought">\r\n				';
 if (obj.image) { 
__p+='\r\n					<img src="'+
((__t=( obj.image ))==null?'':__t)+
'" alt="" class="purechat-unfurl-media" />\r\n				';
 } 
__p+='\r\n				<div class="purechat-unfurl-link-container">\r\n					';
 if (obj.title) { 
__p+='\r\n						<div class="purechat-unfurl-title">\r\n							';
 if (obj.icon) { 
__p+='\r\n							<img src="'+
((__t=( obj.icon ))==null?'':__t)+
'" alt="'+
((__t=( obj.title ))==null?'':__t)+
'" width="16" height="16" class="purechat-unfurl-favicon" />\r\n							';
 } 
__p+='\r\n							<a href="'+
((__t=( obj.link ))==null?'':__t)+
'" target="_blank">'+
((__t=( obj.title ))==null?'':__t)+
'</a>\r\n						</div>\r\n					';
 } 
__p+='\r\n					';
 if (obj.description) { 
__p+='\r\n						'+
((__t=( obj.description ))==null?'':__t)+
'\r\n					';
 } 
__p+='\r\n				</div>\r\n			</div>\r\n		</div>\r\n	</div>\r\n	<div class="purechat-timestamp">\r\n		';
 if(obj.time) { 
__p+='<time class="purechat-time" title="'+
((__t=( obj.date ))==null?'':__t)+
'" datetime="'+
((__t=( obj.date ))==null?'':__t)+
'">'+
((__t=( obj.prettyDate(obj.date) ))==null?'':__t)+
'</time>';
 } 
__p+='\r\n	</div>\r\n</div>\r\n';
}
return __p;
};
module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div data-resourcekey="'+
((__t=( obj.parent.get('resourceKey') || '' ))==null?'':__t)+
'" class="purechat-message-container '+
((__t=( obj.parent.get('myMessage') ? 'purechat-message-right' : 'purechat-message-left' ))==null?'':__t)+
'">\r\n	<div class="purechat-message">\r\n		<span class="purechat-message-actual">\r\n			<span class="purechat-new-thought">\r\n				';
 if (obj.title) { 
__p+='\r\n					<div class="purechat-unfurl-title">\r\n						';
 if (obj.icon) { 
__p+='\r\n						<img src="'+
((__t=( obj.icon ))==null?'':__t)+
'" alt="" width="16" height="16" class="purechat-unfurl-favicon" />\r\n						';
 } 
__p+='\r\n						<a href="'+
((__t=( obj.link ))==null?'':__t)+
'" target="_blank">'+
((__t=( obj.title ))==null?'':__t)+
'</a>\r\n					</div>\r\n				';
 } 
__p+='\r\n				<a href="'+
((__t=( obj.link ))==null?'':__t)+
'" target="_blank">\r\n					<img src="'+
((__t=( obj.media ))==null?'':__t)+
'" alt="" class="purechat-unfurl-media" />\r\n				</a>\r\n			</span>\r\n		</span>\r\n	</div>\r\n	<div class="purechat-timestamp">\r\n		';
 if(obj.time) { 
__p+='<time class="purechat-time" title="'+
((__t=( obj.date ))==null?'':__t)+
'" datetime="'+
((__t=( obj.date ))==null?'':__t)+
'">'+
((__t=( obj.prettyDate(obj.date) ))==null?'':__t)+
'</time>';
 } 
__p+='\r\n	</div>\r\n</div>\r\n';
}
return __p;
};
module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div data-resourcekey="'+
((__t=( obj.parent.get('resourceKey') || '' ))==null?'':__t)+
'" class="purechat-message-container '+
((__t=( obj.parent.get('myMessage') ? 'purechat-message-right' : 'purechat-message-left' ))==null?'':__t)+
'">\r\n	<div class="purechat-message">\r\n		<span class="purechat-message-actual">\r\n			<span class="purechat-new-thought">\r\n				';
 if (obj.title) { 
__p+='\r\n					<div class="purechat-unfurl-title">\r\n						';
 if (obj.icon) { 
__p+='\r\n						<div class="purechat-unfurl-favicon">\r\n							<img src="'+
((__t=( obj.icon ))==null?'':__t)+
'" alt="" width="16" height="16" />\r\n						</div>\r\n						';
 } 
__p+='\r\n						<a href="'+
((__t=( obj.link ))==null?'':__t)+
'" target="_blank">'+
((__t=( obj.title ))==null?'':__t)+
'</a>\r\n					</div>\r\n				';
 } 
__p+='\r\n				';
 if (obj.image) { 
__p+='\r\n				<div class="purechat-unfurl-youtube-wrapper">\r\n					<img src="'+
((__t=( obj.image ))==null?'':__t)+
'" alt="" class="purechat-unfurl-media" />\r\n					<div class="purechat-unfurl-play">\r\n						<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n							<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-play"></use>\r\n						</svg>\r\n					</div>\r\n				</div>\r\n				';
 } else { 
__p+='\r\n				<iframe src="'+
((__t=( obj.media ))==null?'':__t)+
'" class="purechat-unfurl-iframe" frameborder="0"  webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>\r\n				';
 } 
__p+='\r\n			</span>\r\n		</span>\r\n	</div>\r\n	<div class="purechat-timestamp">\r\n		';
 if(obj.time) { 
__p+='<time class="purechat-time" title="'+
((__t=( obj.date ))==null?'':__t)+
'" datetime="'+
((__t=( obj.date ))==null?'':__t)+
'">'+
((__t=( obj.prettyDate(obj.date) ))==null?'':__t)+
'</time>';
 } 
__p+='\r\n	</div>\r\n</div>\r\n';
}
return __p;
};
module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div data-resourcekey="'+
((__t=( obj.parent.get('resourceKey') || '' ))==null?'':__t)+
'" class="purechat-message-container '+
((__t=( obj.parent.get('myMessage') ? 'purechat-message-right' : 'purechat-message-left' ))==null?'':__t)+
'">\r\n	<div class="purechat-message">\r\n		<span class="purechat-message-actual">\r\n			<span class="purechat-new-thought">\r\n				';
 if (obj.media) { 
__p+='\r\n				'+
((__t=( obj.media ))==null?'':__t)+
'\r\n				';
 } else { 
__p+='\r\n				<div class="purechat-loading '+
((__t=( obj.parent.get('myMessage') ? 'purechat-loading-dark' : 'purechat-loading-light' ))==null?'':__t)+
'"></div>\r\n				';
 } 
__p+='\r\n			</span>\r\n		</span>\r\n	</div>\r\n	<div class="purechat-timestamp">\r\n		';
 if(obj.time) { 
__p+='<time class="purechat-time" title="'+
((__t=( obj.date ))==null?'':__t)+
'" datetime="'+
((__t=( obj.date ))==null?'':__t)+
'">'+
((__t=( obj.prettyDate(obj.date) ))==null?'':__t)+
'</time>';
 } 
__p+='\r\n	</div>\r\n</div>\r\n';
}
return __p;
};
module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<img src="'+
((__t=( obj.imageUrl ))==null?'':__t)+
'" alt="" />\r\n<button type="button" class="purechat-image-preview-close">✖</button>';
}
return __p;
};
module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-message-container '+
((__t=( obj.myMessage ? 'purechat-message-right' : 'purechat-message-left' ))==null?'':__t)+
' '+
((__t=( obj.transferStateClass() ))==null?'':__t)+
'">\r\n	';
 if (obj.isOperator()) { 
__p+='\r\n	<img class="purechat-operator-gravatar" height="50" width="50" src="'+
((__t=( obj.avatarUrl ))==null?'':__t)+
'" alt=""/>\r\n	';
 } 
__p+='\r\n	<div class="purechat-message">\r\n		';
 if(obj.userName && obj.isOperator()) { 
__p+='\r\n		<span class="purechat-displayname">'+
((__t=( obj.userName ))==null?'':__t)+
'</span>\r\n		';
 } 
__p+='\r\n		<span class="purechat-message-actual">\r\n			<span class="purechat-new-thought purechat-display-flex">\r\n				';
 if (!obj.isError()) { 
__p+='\r\n					';
 if (obj.isImage()) { 
__p+='\r\n						<div class="purechat-file-image">\r\n							<div class="purechat-file-image-name">'+
((__t=( obj.parsed.name ))==null?'':__t)+
'</div>\r\n							<div class="purechat-loading purechat-loading-large purechat-loading-center '+
((__t=( obj.myMessage ? 'purechat-loading-dark' : 'purechat-loading-light' ))==null?'':__t)+
'"></div>\r\n							<img src="'+
((__t=( obj.parsed.url ))==null?'':__t)+
'?'+
((__t=( obj.isOperator() ? 'width=500&height=500' : 'width=300&height=80' ))==null?'':__t)+
'" alt="';
 obj.parsed.name 
__p+='" class="purechat-display-none" />\r\n							<div class="purechat-file-actions">\r\n								';
 if (obj.myMessage && !obj.isClosedChat) { 
__p+='\r\n									<button type="button" class="purechat-file-delete">\r\n										<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n											<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-close-filled"></use>\r\n										</svg>\r\n									</button>\r\n								';
 } else { 
__p+='\r\n									<a href="'+
((__t=( obj.parsed.url ))==null?'':__t)+
'" download="'+
((__t=( obj.parsed.url ))==null?'':__t)+
'" target="_blank" class="purechat-btn purechat-file-download">\r\n										<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n											<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-download"></use>\r\n										</svg>\r\n									</a>\r\n								';
 } 
__p+='\r\n							</div>\r\n						</div>\r\n					';
 } else { 
__p+='\r\n						<div class="purechat-file-icon">\r\n							<img src="' + __webpack_require__(778) + '" alt="" />\r\n						</div>\r\n						<div class="purechat-file-description">\r\n							'+
((__t=( obj.getMessageDescription() ))==null?'':__t)+
'\r\n						</div>\r\n						<div class="purechat-file-actions">\r\n							';
 if (obj.isUploading()) { 
__p+='\r\n								<div class="purechat-loading purechat-loading-large '+
((__t=( obj.myMessage ? 'purechat-loading-dark' : 'purechat-loading-light' ))==null?'':__t)+
'"></div>\r\n							';
 } else if (obj.myMessage && !obj.isClosedChat) { 
__p+='\r\n								<button type="button" class="purechat-file-delete">\r\n									<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n										<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-close-filled"></use>\r\n									</svg>\r\n								</button>\r\n							';
 } else { 
__p+='\r\n								<a href="'+
((__t=( obj.parsed.url ))==null?'':__t)+
'" target="_self" class="purechat-file-download">\r\n									<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n										<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-download"></use>\r\n									</svg>\r\n								</a>\r\n							';
 } 
__p+='\r\n						</div>\r\n					';
 } 
__p+='\r\n				';
 } else { 
__p+='\r\n				<div class="purechat-file-error">\r\n					<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n						<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-notification"></use>\r\n					</svg>\r\n					'+
((__t=( obj.myMessage ? obj.message : obj.getGeneralError() ))==null?'':__t)+
'\r\n				</div>\r\n				';
 } 
__p+='\r\n			</span>\r\n		</span>\r\n		';
 if (!obj.isError()) { 
__p+='\r\n		<div class="purechat-message-tail">\r\n			<svg viewBox="0 0 18 16" class="pc-svgicon">\r\n				<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#'+
((__t=( obj.myMessage ? 'pc-svgicon-tail-right' : 'pc-svgicon-tail-left' ))==null?'':__t)+
'"></use>\r\n			</svg>\r\n		</div>\r\n		';
 } 
__p+='\r\n	</div>\r\n	<div class="purechat-timestamp">\r\n		';
 if(obj.time) { 
__p+='<time class="purechat-time" title="'+
((__t=( obj.date ))==null?'':__t)+
'" datetime="'+
((__t=( obj.date ))==null?'':__t)+
'">'+
((__t=( obj.prettyDate(obj.date) ))==null?'':__t)+
'</time>';
 } 
__p+='\r\n	</div>\r\n</div>\r\n';
}
return __p;
};
module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAA0CAYAAAAT3cGOAAAABGdBTUEAALGPC/xhBQAABC5JREFUaAXtmvtLFFEUx8/s6trD3XxkCJYlQYb2zjR6kGBtRGiaLVHRi+hF9vgn+jkog8qifpTsQUL0Q25JBGWFEBRSEEkvMsJH7cPZnUf3TM24zrgzc2dnXAMPLHPuvd9z7mfv3Dl3YZYBCvP7G2aFY9xZYKCAIiwlKQPAgtvV8rTjXkeG2UwIGolzjwHEMhDNRqWuw6kYTvCLophHwI1t/ZZAgRCNPiLKRcZqZxS+qSVTDFe2urZ2Jvd7OKgGXbumMlK5asU0Z9AAeI6D8xevjkqvC1tT05DPhrigCOLiUVGksWRROdtYv9Ux2FgspoF1qSHktgQqxINkryyR+3w+r+ym5Tom7ObNgbxhPt4hirBUpjpx7CCsqlguN9Ny1cCu27o7N8QOdxCaZTLR8SMHYNfO7VgExrEOyLOPXEfBIihEfhNQUVnCo4f3w55djVKEKAj8SOj4ewpsdX19DkR+PSR7dIWMceTQXti7e4fcBDImKI00OFI1QND4IP+QzL9SZiBlCcrKSuFV92u5C/r7BxQ/HY4Eyw1yd8nkFYkAL152A35U5lG1kza5n2+ksYyZ9p0jrkAg4CFPTXXSWZMMeL3ZU5IMkS3PQ6TnpvRB3y7LCIUKyZH7UcmXlZX1hXExSfcmQ37FlC6YL/g3bpinBKkctjcIfLhP6kU/q8SvUlhrak6w263XZufkzLCWjUSJsV8Q/XBfiUffU7QaGI9P6bPqKNXAagJ1XPTdHRC5YaUbfeyzw2yF5Yd6IfbtuYYL+3AsVbMVNtLTirVYw4R9OJaq2QYb+/oMuMGRB1UNhmOoScXsgeVZiL7HUq1vkoZorZotsPjEC+yQIQNqEiuFYYBKkDKsEPkBWEvNGmoxxoqlDIsnlShwpudGLcZYMc2hQJske2UTbYhlfcora3lmC4GmVzb89i18vnQZhrq6ID4wAJm5uTCjqgrmHDsK08vLLUxNH2IMy/Pw6UIzfGpuBiEeV2Zg+/rgR3s7/HzwAIqbmqD41EkAl7M3yhAWQXvPnVMg1Q5+AXm8+Mxp9bCtbV1YvPW4omYMdfmbNmq2ROGO62bCJc33Wwd1tbr3Dfdo4q3Xy4Q61DtpurD4MNEYrZ4mN2p1YfGppzFaPU1u1OrCYnmiMVo9TW7U6sJiHaUxWj1NbtTqwmLBd2VmmsqJOtQ7abqweDJhwTdjqHP6JNOtswhZfPIvrPoEk78ArqhygsmdDl0NYcHtBjyZsOBP/N8G/1YJb/HCC+cdWjNzaY1X1lyepCqjIzRp4BgDug/YGPq0dk3COrX8kys7ubJkBf6rbaCps7wggEA+6TbkUJsGdlvjPrVmwrRd0ap8Hpjk7xAmBCnhQ053b2enMLektIhAKe/AJgRgAgTDMC1PblxpV/4cUVdX5w2H3abfcyXkctTl8zLYzra2EE7yByEpfO6yzEYcAAAAAElFTkSuQmCC"module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-message-display purechat-clearfix">\r\n	<div class="purechat-showPrevious">\r\n		<a href="#">See Previous Conversation</a>\r\n	</div>\r\n</div>\r\n<div class="purechat-emojis purechat-display-flex"></div>\r\n<div class="purechat-emoji-autocomplete purechat-display-none"></div>\r\n';
}
return __p;
};
module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-card-header">\r\n	<input type="text" class="purechat-emoji-search" placeholder="Search" /> \r\n</div>\r\n<div class="purechat-card-body">\r\n	<div class="purechat-message-wrapper purechat-clearfix purechat-separator">\r\n		<span class="purechat-important purechat-separator">Most Used</span>\r\n	</div>\r\n	<div class="purechat-curated-emojis"></div>\r\n\r\n	<div class="purechat-message-wrapper purechat-clearfix purechat-separator">\r\n		<span class="purechat-important purechat-separator">Emojis</span>\r\n	</div>\r\n	<div class="purechat-all-emojis"></div>\r\n</div>\r\n\r\n';
}
return __p;
};
module.exports = JSON.parse("[{\"emoji\":\"🙂\",\"category\":\"people\",\"description\":\"slightly smiling face\",\"names\":[\"slightly_smiling_face\"],\"tags\":[]},{\"emoji\":\"😀\",\"category\":\"people\",\"description\":\"grinning face\",\"names\":[\"grinning\"],\"tags\":[\"smile\",\"happy\"]},{\"emoji\":\"😃\",\"category\":\"people\",\"description\":\"smiling face with open mouth\",\"names\":[\"smiley\"],\"tags\":[\"happy\",\"joy\",\"haha\"]},{\"emoji\":\"😄\",\"category\":\"people\",\"description\":\"smiling face with open mouth & smiling eyes\",\"names\":[\"smile\"],\"tags\":[\"happy\",\"joy\",\"laugh\",\"pleased\"]},{\"emoji\":\"😁\",\"category\":\"people\",\"description\":\"grinning face with smiling eyes\",\"names\":[\"grin\"],\"tags\":[]},{\"emoji\":\"😆\",\"category\":\"people\",\"description\":\"smiling face with open mouth & closed eyes\",\"names\":[\"laughing\",\"satisfied\"],\"tags\":[\"happy\",\"haha\"]},{\"emoji\":\"😅\",\"category\":\"people\",\"description\":\"smiling face with open mouth & cold sweat\",\"names\":[\"sweat_smile\"],\"tags\":[\"hot\"]},{\"emoji\":\"😂\",\"category\":\"people\",\"description\":\"face with tears of joy\",\"names\":[\"joy\"],\"tags\":[\"tears\"]},{\"emoji\":\"😊\",\"category\":\"people\",\"description\":\"smiling face with smiling eyes\",\"names\":[\"blush\"],\"tags\":[\"proud\"]},{\"emoji\":\"😇\",\"category\":\"people\",\"description\":\"smiling face with halo\",\"names\":[\"innocent\"],\"tags\":[\"angel\"]},{\"emoji\":\"😉\",\"category\":\"people\",\"description\":\"winking face\",\"names\":[\"wink\"],\"tags\":[\"flirt\"]},{\"emoji\":\"😌\",\"category\":\"people\",\"description\":\"relieved face\",\"names\":[\"relieved\"],\"tags\":[\"whew\"]},{\"emoji\":\"😍\",\"category\":\"people\",\"description\":\"smiling face with heart-eyes\",\"names\":[\"heart_eyes\"],\"tags\":[\"love\",\"crush\"]},{\"emoji\":\"😘\",\"category\":\"people\",\"description\":\"face blowing a kiss\",\"names\":[\"kissing_heart\"],\"tags\":[\"flirt\"]},{\"emoji\":\"😗\",\"category\":\"people\",\"description\":\"kissing face\",\"names\":[\"kissing\"],\"tags\":[]},{\"emoji\":\"😙\",\"category\":\"people\",\"description\":\"kissing face with smiling eyes\",\"names\":[\"kissing_smiling_eyes\"],\"tags\":[]},{\"emoji\":\"😚\",\"category\":\"people\",\"description\":\"kissing face with closed eyes\",\"names\":[\"kissing_closed_eyes\"],\"tags\":[]},{\"emoji\":\"😋\",\"category\":\"people\",\"description\":\"face savouring delicious food\",\"names\":[\"yum\"],\"tags\":[\"tongue\",\"lick\"]},{\"emoji\":\"😜\",\"category\":\"people\",\"description\":\"face with stuck-out tongue & winking eye\",\"names\":[\"stuck_out_tongue_winking_eye\"],\"tags\":[\"prank\",\"silly\"]},{\"emoji\":\"😝\",\"category\":\"people\",\"description\":\"face with stuck-out tongue & closed eyes\",\"names\":[\"stuck_out_tongue_closed_eyes\"],\"tags\":[\"prank\"]},{\"emoji\":\"😛\",\"category\":\"people\",\"description\":\"face with stuck-out tongue\",\"names\":[\"stuck_out_tongue\"],\"tags\":[]},{\"emoji\":\"😎\",\"category\":\"people\",\"description\":\"smiling face with sunglasses\",\"names\":[\"sunglasses\"],\"tags\":[\"cool\"]},{\"emoji\":\"😏\",\"category\":\"people\",\"description\":\"smirking face\",\"names\":[\"smirk\"],\"tags\":[\"smug\"]},{\"emoji\":\"😒\",\"category\":\"people\",\"description\":\"unamused face\",\"names\":[\"unamused\"],\"tags\":[\"meh\"]},{\"emoji\":\"😞\",\"category\":\"people\",\"description\":\"disappointed face\",\"names\":[\"disappointed\"],\"tags\":[\"sad\"]},{\"emoji\":\"😔\",\"category\":\"people\",\"description\":\"pensive face\",\"names\":[\"pensive\"],\"tags\":[]},{\"emoji\":\"😟\",\"category\":\"people\",\"description\":\"worried face\",\"names\":[\"worried\"],\"tags\":[\"nervous\"]},{\"emoji\":\"😕\",\"category\":\"people\",\"description\":\"confused face\",\"names\":[\"confused\"],\"tags\":[]},{\"emoji\":\"😣\",\"category\":\"people\",\"description\":\"persevering face\",\"names\":[\"persevere\"],\"tags\":[\"struggling\"]},{\"emoji\":\"😖\",\"category\":\"people\",\"description\":\"confounded face\",\"names\":[\"confounded\"],\"tags\":[]},{\"emoji\":\"😫\",\"category\":\"people\",\"description\":\"tired face\",\"names\":[\"tired_face\"],\"tags\":[\"upset\",\"whine\"]},{\"emoji\":\"😩\",\"category\":\"people\",\"description\":\"weary face\",\"names\":[\"weary\"],\"tags\":[\"tired\"]},{\"emoji\":\"😤\",\"category\":\"people\",\"description\":\"face with steam from nose\",\"names\":[\"triumph\"],\"tags\":[\"smug\"]},{\"emoji\":\"😠\",\"category\":\"people\",\"description\":\"angry face\",\"names\":[\"angry\"],\"tags\":[\"mad\",\"annoyed\"]},{\"emoji\":\"😡\",\"category\":\"people\",\"description\":\"pouting face\",\"names\":[\"rage\",\"pout\"],\"tags\":[\"angry\"]},{\"emoji\":\"😶\",\"category\":\"people\",\"description\":\"face without mouth\",\"names\":[\"no_mouth\"],\"tags\":[\"mute\",\"silence\"]},{\"emoji\":\"😐\",\"category\":\"people\",\"description\":\"neutral face\",\"names\":[\"neutral_face\"],\"tags\":[\"meh\"]},{\"emoji\":\"😑\",\"category\":\"people\",\"description\":\"expressionless face\",\"names\":[\"expressionless\"],\"tags\":[]},{\"emoji\":\"😯\",\"category\":\"people\",\"description\":\"hushed face\",\"names\":[\"hushed\"],\"tags\":[\"silence\",\"speechless\"]},{\"emoji\":\"😦\",\"category\":\"people\",\"description\":\"frowning face with open mouth\",\"names\":[\"frowning\"],\"tags\":[]},{\"emoji\":\"😧\",\"category\":\"people\",\"description\":\"anguished face\",\"names\":[\"anguished\"],\"tags\":[\"stunned\"]},{\"emoji\":\"😮\",\"category\":\"people\",\"description\":\"face with open mouth\",\"names\":[\"open_mouth\"],\"tags\":[\"surprise\",\"impressed\",\"wow\"]},{\"emoji\":\"😲\",\"category\":\"people\",\"description\":\"astonished face\",\"names\":[\"astonished\"],\"tags\":[\"amazed\",\"gasp\"]},{\"emoji\":\"😵\",\"category\":\"people\",\"description\":\"dizzy face\",\"names\":[\"dizzy_face\"],\"tags\":[]},{\"emoji\":\"😳\",\"category\":\"people\",\"description\":\"flushed face\",\"names\":[\"flushed\"],\"tags\":[]},{\"emoji\":\"😱\",\"category\":\"people\",\"description\":\"face screaming in fear\",\"names\":[\"scream\"],\"tags\":[\"horror\",\"shocked\"]},{\"emoji\":\"😨\",\"category\":\"people\",\"description\":\"fearful face\",\"names\":[\"fearful\"],\"tags\":[\"scared\",\"shocked\",\"oops\"]},{\"emoji\":\"😰\",\"category\":\"people\",\"description\":\"face with open mouth & cold sweat\",\"names\":[\"cold_sweat\"],\"tags\":[\"nervous\"]},{\"emoji\":\"😢\",\"category\":\"people\",\"description\":\"crying face\",\"names\":[\"cry\"],\"tags\":[\"sad\",\"tear\"]},{\"emoji\":\"😥\",\"category\":\"people\",\"description\":\"disappointed but relieved face\",\"names\":[\"disappointed_relieved\"],\"tags\":[\"phew\",\"sweat\",\"nervous\"]},{\"emoji\":\"😭\",\"category\":\"people\",\"description\":\"loudly crying face\",\"names\":[\"sob\"],\"tags\":[\"sad\",\"cry\",\"bawling\"]},{\"emoji\":\"😓\",\"category\":\"people\",\"description\":\"face with cold sweat\",\"names\":[\"sweat\"],\"tags\":[]},{\"emoji\":\"😪\",\"category\":\"people\",\"description\":\"sleepy face\",\"names\":[\"sleepy\"],\"tags\":[\"tired\"]},{\"emoji\":\"😴\",\"category\":\"people\",\"description\":\"sleeping face\",\"names\":[\"sleeping\"],\"tags\":[\"zzz\"]},{\"emoji\":\"😬\",\"category\":\"people\",\"description\":\"grimacing face\",\"names\":[\"grimacing\"],\"tags\":[]},{\"emoji\":\"😷\",\"category\":\"people\",\"description\":\"face with medical mask\",\"names\":[\"mask\"],\"tags\":[\"sick\",\"ill\"]},{\"emoji\":\"😈\",\"category\":\"people\",\"description\":\"smiling face with horns\",\"names\":[\"smiling_imp\"],\"tags\":[\"devil\",\"evil\",\"horns\"]},{\"emoji\":\"👿\",\"category\":\"people\",\"description\":\"angry face with horns\",\"names\":[\"imp\"],\"tags\":[\"angry\",\"devil\",\"evil\",\"horns\"]},{\"emoji\":\"👹\",\"category\":\"people\",\"description\":\"ogre\",\"names\":[\"japanese_ogre\"],\"tags\":[\"monster\"]},{\"emoji\":\"👺\",\"category\":\"people\",\"description\":\"goblin\",\"names\":[\"japanese_goblin\"],\"tags\":[]},{\"emoji\":\"💩\",\"category\":\"people\",\"description\":\"pile of poo\",\"names\":[\"hankey\",\"poop\",\"shit\"],\"tags\":[\"crap\"]},{\"emoji\":\"👻\",\"category\":\"people\",\"description\":\"ghost\",\"names\":[\"ghost\"],\"tags\":[\"halloween\"]},{\"emoji\":\"💀\",\"category\":\"people\",\"description\":\"skull\",\"names\":[\"skull\"],\"tags\":[\"dead\",\"danger\",\"poison\"]},{\"emoji\":\"☠️\",\"category\":\"people\",\"description\":\"skull and crossbones\",\"names\":[\"skull_and_crossbones\"],\"tags\":[\"danger\",\"pirate\"]},{\"emoji\":\"👽\",\"category\":\"people\",\"description\":\"alien\",\"names\":[\"alien\"],\"tags\":[\"ufo\"]},{\"emoji\":\"👾\",\"category\":\"people\",\"description\":\"alien monster\",\"names\":[\"space_invader\"],\"tags\":[\"game\",\"retro\"]},{\"emoji\":\"🎃\",\"category\":\"people\",\"description\":\"jack-o-lantern\",\"names\":[\"jack_o_lantern\"],\"tags\":[\"halloween\"]},{\"emoji\":\"😺\",\"category\":\"people\",\"description\":\"smiling cat face with open mouth\",\"names\":[\"smiley_cat\"],\"tags\":[]},{\"emoji\":\"😸\",\"category\":\"people\",\"description\":\"grinning cat face with smiling eyes\",\"names\":[\"smile_cat\"],\"tags\":[]},{\"emoji\":\"😹\",\"category\":\"people\",\"description\":\"cat face with tears of joy\",\"names\":[\"joy_cat\"],\"tags\":[]},{\"emoji\":\"😻\",\"category\":\"people\",\"description\":\"smiling cat face with heart-eyes\",\"names\":[\"heart_eyes_cat\"],\"tags\":[]},{\"emoji\":\"😼\",\"category\":\"people\",\"description\":\"cat face with wry smile\",\"names\":[\"smirk_cat\"],\"tags\":[]},{\"emoji\":\"😽\",\"category\":\"people\",\"description\":\"kissing cat face with closed eyes\",\"names\":[\"kissing_cat\"],\"tags\":[]},{\"emoji\":\"🙀\",\"category\":\"people\",\"description\":\"weary cat face\",\"names\":[\"scream_cat\"],\"tags\":[\"horror\"]},{\"emoji\":\"😿\",\"category\":\"people\",\"description\":\"crying cat face\",\"names\":[\"crying_cat_face\"],\"tags\":[\"sad\",\"tear\"]},{\"emoji\":\"😾\",\"category\":\"people\",\"description\":\"pouting cat face\",\"names\":[\"pouting_cat\"],\"tags\":[]},{\"emoji\":\"👐\",\"category\":\"people\",\"description\":\"open hands\",\"names\":[\"open_hands\"],\"tags\":[]},{\"emoji\":\"🙌\",\"category\":\"people\",\"description\":\"raising hands\",\"names\":[\"raised_hands\"],\"tags\":[\"hooray\"]},{\"emoji\":\"👏\",\"category\":\"people\",\"description\":\"clapping hands\",\"names\":[\"clap\"],\"tags\":[\"praise\",\"applause\"]},{\"emoji\":\"🙏\",\"category\":\"people\",\"description\":\"folded hands\",\"names\":[\"pray\"],\"tags\":[\"please\",\"hope\",\"wish\"]},{\"emoji\":\"👍\",\"category\":\"people\",\"description\":\"thumbs up\",\"names\":[\"+1\",\"thumbsup\"],\"tags\":[\"approve\",\"ok\"]},{\"emoji\":\"👎\",\"category\":\"people\",\"description\":\"thumbs down\",\"names\":[\"-1\",\"thumbsdown\"],\"tags\":[\"disapprove\",\"bury\"]},{\"emoji\":\"👊\",\"category\":\"people\",\"description\":\"oncoming fist\",\"names\":[\"fist_oncoming\",\"facepunch\",\"punch\"],\"tags\":[\"attack\"]},{\"emoji\":\"✌️\",\"category\":\"people\",\"description\":\"victory hand\",\"names\":[\"v\"],\"tags\":[\"victory\",\"peace\"]},{\"emoji\":\"👌\",\"category\":\"people\",\"description\":\"OK hand\",\"names\":[\"ok_hand\"],\"tags\":[]},{\"emoji\":\"👈\",\"category\":\"people\",\"description\":\"backhand index pointing left\",\"names\":[\"point_left\"],\"tags\":[]},{\"emoji\":\"👉\",\"category\":\"people\",\"description\":\"backhand index pointing right\",\"names\":[\"point_right\"],\"tags\":[]},{\"emoji\":\"👆\",\"category\":\"people\",\"description\":\"backhand index pointing up\",\"names\":[\"point_up_2\"],\"tags\":[]},{\"emoji\":\"👇\",\"category\":\"people\",\"description\":\"backhand index pointing down\",\"names\":[\"point_down\"],\"tags\":[]},{\"emoji\":\"☝️\",\"category\":\"people\",\"description\":\"index pointing up\",\"names\":[\"point_up\"],\"tags\":[]},{\"emoji\":\"👋\",\"category\":\"people\",\"description\":\"waving hand\",\"names\":[\"wave\"],\"tags\":[\"goodbye\"]},{\"emoji\":\"💪\",\"category\":\"people\",\"description\":\"flexed biceps\",\"names\":[\"muscle\"],\"tags\":[\"flex\",\"bicep\",\"strong\",\"workout\"]},{\"emoji\":\"💅\",\"category\":\"people\",\"description\":\"nail polish\",\"names\":[\"nail_care\"],\"tags\":[\"beauty\",\"manicure\"]},{\"emoji\":\"💍\",\"category\":\"people\",\"description\":\"ring\",\"names\":[\"ring\"],\"tags\":[\"wedding\",\"marriage\",\"engaged\"]},{\"emoji\":\"💄\",\"category\":\"people\",\"description\":\"lipstick\",\"names\":[\"lipstick\"],\"tags\":[\"makeup\"]},{\"emoji\":\"💋\",\"category\":\"people\",\"description\":\"kiss mark\",\"names\":[\"kiss\"],\"tags\":[\"lipstick\"]},{\"emoji\":\"👄\",\"category\":\"people\",\"description\":\"mouth\",\"names\":[\"lips\"],\"tags\":[\"kiss\"]},{\"emoji\":\"👅\",\"category\":\"people\",\"description\":\"tongue\",\"names\":[\"tongue\"],\"tags\":[\"taste\"]},{\"emoji\":\"👂\",\"category\":\"people\",\"description\":\"ear\",\"names\":[\"ear\"],\"tags\":[\"hear\",\"sound\",\"listen\"]},{\"emoji\":\"👃\",\"category\":\"people\",\"description\":\"nose\",\"names\":[\"nose\"],\"tags\":[\"smell\"]},{\"emoji\":\"👣\",\"category\":\"people\",\"description\":\"footprints\",\"names\":[\"footprints\"],\"tags\":[\"feet\",\"tracks\"]},{\"emoji\":\"👀\",\"category\":\"people\",\"description\":\"eyes\",\"names\":[\"eyes\"],\"tags\":[\"look\",\"see\",\"watch\"]},{\"emoji\":\"👤\",\"category\":\"people\",\"description\":\"bust in silhouette\",\"names\":[\"bust_in_silhouette\"],\"tags\":[\"user\"]},{\"emoji\":\"👥\",\"category\":\"people\",\"description\":\"busts in silhouette\",\"names\":[\"busts_in_silhouette\"],\"tags\":[\"users\",\"group\",\"team\"]},{\"emoji\":\"👶\",\"category\":\"people\",\"description\":\"baby\",\"names\":[\"baby\"],\"tags\":[\"child\",\"newborn\"]},{\"emoji\":\"👦\",\"category\":\"people\",\"description\":\"boy\",\"names\":[\"boy\"],\"tags\":[\"child\"]},{\"emoji\":\"👧\",\"category\":\"people\",\"description\":\"girl\",\"names\":[\"girl\"],\"tags\":[\"child\"]},{\"emoji\":\"👨\",\"category\":\"people\",\"description\":\"man\",\"names\":[\"man\"],\"tags\":[\"mustache\",\"father\",\"dad\"]},{\"emoji\":\"👩\",\"category\":\"people\",\"description\":\"woman\",\"names\":[\"woman\"],\"tags\":[\"girls\"]},{\"emoji\":\"👱\",\"category\":\"people\",\"description\":\"blond-haired person\",\"names\":[\"blonde_man\",\"person_with_blond_hair\"],\"tags\":[\"boy\"]},{\"emoji\":\"👴\",\"category\":\"people\",\"description\":\"old man\",\"names\":[\"older_man\"],\"tags\":[]},{\"emoji\":\"👵\",\"category\":\"people\",\"description\":\"old woman\",\"names\":[\"older_woman\"],\"tags\":[]},{\"emoji\":\"👲\",\"category\":\"people\",\"description\":\"man with Chinese cap\",\"names\":[\"man_with_gua_pi_mao\"],\"tags\":[]},{\"emoji\":\"👳\",\"category\":\"people\",\"description\":\"person wearing turban\",\"names\":[\"man_with_turban\"],\"tags\":[]},{\"emoji\":\"👮\",\"category\":\"people\",\"description\":\"police officer\",\"names\":[\"policeman\",\"cop\"],\"tags\":[\"police\",\"law\"]},{\"emoji\":\"👷\",\"category\":\"people\",\"description\":\"construction worker\",\"names\":[\"construction_worker_man\",\"construction_worker\"],\"tags\":[\"helmet\"]},{\"emoji\":\"💂\",\"category\":\"people\",\"description\":\"guard\",\"names\":[\"guardsman\"],\"tags\":[]},{\"emoji\":\"🎅\",\"category\":\"people\",\"description\":\"Santa Claus\",\"names\":[\"santa\"],\"tags\":[\"christmas\"]},{\"emoji\":\"👸\",\"category\":\"people\",\"description\":\"princess\",\"names\":[\"princess\"],\"tags\":[\"blonde\",\"crown\",\"royal\"]},{\"emoji\":\"👰\",\"category\":\"people\",\"description\":\"bride with veil\",\"names\":[\"bride_with_veil\"],\"tags\":[\"marriage\",\"wedding\"]},{\"emoji\":\"👼\",\"category\":\"people\",\"description\":\"baby angel\",\"names\":[\"angel\"],\"tags\":[]},{\"emoji\":\"🙇\",\"category\":\"people\",\"description\":\"person bowing\",\"names\":[\"bowing_man\",\"bow\"],\"tags\":[\"respect\",\"thanks\"]},{\"emoji\":\"💁\",\"category\":\"people\",\"description\":\"person tipping hand\",\"names\":[\"tipping_hand_woman\",\"information_desk_person\",\"sassy_woman\"],\"tags\":[]},{\"emoji\":\"🙅\",\"category\":\"people\",\"description\":\"person gesturing NO\",\"names\":[\"no_good_woman\",\"no_good\",\"ng_woman\"],\"tags\":[\"stop\",\"halt\"]},{\"emoji\":\"🙆\",\"category\":\"people\",\"description\":\"person gesturing OK\",\"names\":[\"ok_woman\"],\"tags\":[]},{\"emoji\":\"🙋\",\"category\":\"people\",\"description\":\"person raising hand\",\"names\":[\"raising_hand_woman\",\"raising_hand\"],\"tags\":[]},{\"emoji\":\"🙎\",\"category\":\"people\",\"description\":\"person pouting\",\"names\":[\"pouting_woman\",\"person_with_pouting_face\"],\"tags\":[]},{\"emoji\":\"🙍\",\"category\":\"people\",\"description\":\"person frowning\",\"names\":[\"frowning_woman\",\"person_frowning\"],\"tags\":[\"sad\"]},{\"emoji\":\"💇\",\"category\":\"people\",\"description\":\"person getting haircut\",\"names\":[\"haircut_woman\",\"haircut\"],\"tags\":[\"beauty\"]},{\"emoji\":\"💆\",\"category\":\"people\",\"description\":\"person getting massage\",\"names\":[\"massage_woman\",\"massage\"],\"tags\":[\"spa\"]},{\"emoji\":\"💃\",\"category\":\"people\",\"description\":\"woman dancing\",\"names\":[\"dancer\"],\"tags\":[\"dress\"]},{\"emoji\":\"👯\",\"category\":\"people\",\"description\":\"people with bunny ears partying\",\"names\":[\"dancing_women\",\"dancers\"],\"tags\":[\"bunny\"]},{\"emoji\":\"🚶\",\"category\":\"people\",\"description\":\"person walking\",\"names\":[\"walking_man\",\"walking\"],\"tags\":[]},{\"emoji\":\"🏃\",\"category\":\"people\",\"description\":\"person running\",\"names\":[\"running_man\",\"runner\",\"running\"],\"tags\":[\"exercise\",\"workout\",\"marathon\"]},{\"emoji\":\"👫\",\"category\":\"people\",\"description\":\"man and woman holding hands\",\"names\":[\"couple\"],\"tags\":[\"date\"]},{\"emoji\":\"👭\",\"category\":\"people\",\"description\":\"two women holding hands\",\"names\":[\"two_women_holding_hands\"],\"tags\":[\"couple\",\"date\"]},{\"emoji\":\"👬\",\"category\":\"people\",\"description\":\"two men holding hands\",\"names\":[\"two_men_holding_hands\"],\"tags\":[\"couple\",\"date\"]},{\"emoji\":\"💑\",\"category\":\"people\",\"description\":\"couple with heart\",\"names\":[\"couple_with_heart_woman_man\",\"couple_with_heart\"],\"tags\":[]},{\"emoji\":\"💏\",\"category\":\"people\",\"description\":\"kiss\",\"names\":[\"couplekiss_man_woman\"],\"tags\":[]},{\"emoji\":\"👪\",\"category\":\"people\",\"description\":\"family\",\"names\":[\"family_man_woman_boy\",\"family\"],\"tags\":[\"home\",\"parents\",\"child\"]},{\"emoji\":\"👚\",\"category\":\"people\",\"description\":\"woman’s clothes\",\"names\":[\"womans_clothes\"],\"tags\":[]},{\"emoji\":\"👕\",\"category\":\"people\",\"description\":\"t-shirt\",\"names\":[\"shirt\",\"tshirt\"],\"tags\":[]},{\"emoji\":\"👖\",\"category\":\"people\",\"description\":\"jeans\",\"names\":[\"jeans\"],\"tags\":[\"pants\"]},{\"emoji\":\"👔\",\"category\":\"people\",\"description\":\"necktie\",\"names\":[\"necktie\"],\"tags\":[\"shirt\",\"formal\"]},{\"emoji\":\"👗\",\"category\":\"people\",\"description\":\"dress\",\"names\":[\"dress\"],\"tags\":[]},{\"emoji\":\"👙\",\"category\":\"people\",\"description\":\"bikini\",\"names\":[\"bikini\"],\"tags\":[\"beach\"]},{\"emoji\":\"👘\",\"category\":\"people\",\"description\":\"kimono\",\"names\":[\"kimono\"],\"tags\":[]},{\"emoji\":\"👠\",\"category\":\"people\",\"description\":\"high-heeled shoe\",\"names\":[\"high_heel\"],\"tags\":[\"shoe\"]},{\"emoji\":\"👡\",\"category\":\"people\",\"description\":\"woman’s sandal\",\"names\":[\"sandal\"],\"tags\":[\"shoe\"]},{\"emoji\":\"👢\",\"category\":\"people\",\"description\":\"woman’s boot\",\"names\":[\"boot\"],\"tags\":[]},{\"emoji\":\"👞\",\"category\":\"people\",\"description\":\"man’s shoe\",\"names\":[\"mans_shoe\",\"shoe\"],\"tags\":[]},{\"emoji\":\"👟\",\"category\":\"people\",\"description\":\"running shoe\",\"names\":[\"athletic_shoe\"],\"tags\":[\"sneaker\",\"sport\",\"running\"]},{\"emoji\":\"👒\",\"category\":\"people\",\"description\":\"woman’s hat\",\"names\":[\"womans_hat\"],\"tags\":[]},{\"emoji\":\"🎩\",\"category\":\"people\",\"description\":\"top hat\",\"names\":[\"tophat\"],\"tags\":[\"hat\",\"classy\"]},{\"emoji\":\"🎓\",\"category\":\"people\",\"description\":\"graduation cap\",\"names\":[\"mortar_board\"],\"tags\":[\"education\",\"college\",\"university\",\"graduation\"]},{\"emoji\":\"👑\",\"category\":\"people\",\"description\":\"crown\",\"names\":[\"crown\"],\"tags\":[\"king\",\"queen\",\"royal\"]},{\"emoji\":\"🎒\",\"category\":\"people\",\"description\":\"school backpack\",\"names\":[\"school_satchel\"],\"tags\":[]},{\"emoji\":\"👝\",\"category\":\"people\",\"description\":\"clutch bag\",\"names\":[\"pouch\"],\"tags\":[\"bag\"]},{\"emoji\":\"👛\",\"category\":\"people\",\"description\":\"purse\",\"names\":[\"purse\"],\"tags\":[]},{\"emoji\":\"👜\",\"category\":\"people\",\"description\":\"handbag\",\"names\":[\"handbag\"],\"tags\":[\"bag\"]},{\"emoji\":\"💼\",\"category\":\"people\",\"description\":\"briefcase\",\"names\":[\"briefcase\"],\"tags\":[\"business\"]},{\"emoji\":\"👓\",\"category\":\"people\",\"description\":\"glasses\",\"names\":[\"eyeglasses\"],\"tags\":[\"glasses\"]},{\"emoji\":\"🌂\",\"category\":\"people\",\"description\":\"closed umbrella\",\"names\":[\"closed_umbrella\"],\"tags\":[\"weather\",\"rain\"]},{\"emoji\":\"☂️\",\"category\":\"people\",\"description\":\"umbrella\",\"names\":[\"open_umbrella\"],\"tags\":[]},{\"emoji\":\"🐶\",\"category\":\"nature\",\"description\":\"dog face\",\"names\":[\"dog\"],\"tags\":[\"pet\"]},{\"emoji\":\"🐱\",\"category\":\"nature\",\"description\":\"cat face\",\"names\":[\"cat\"],\"tags\":[\"pet\"]},{\"emoji\":\"🐭\",\"category\":\"nature\",\"description\":\"mouse face\",\"names\":[\"mouse\"],\"tags\":[]},{\"emoji\":\"🐹\",\"category\":\"nature\",\"description\":\"hamster face\",\"names\":[\"hamster\"],\"tags\":[\"pet\"]},{\"emoji\":\"🐰\",\"category\":\"nature\",\"description\":\"rabbit face\",\"names\":[\"rabbit\"],\"tags\":[\"bunny\"]},{\"emoji\":\"🐻\",\"category\":\"nature\",\"description\":\"bear face\",\"names\":[\"bear\"],\"tags\":[]},{\"emoji\":\"🐼\",\"category\":\"nature\",\"description\":\"panda face\",\"names\":[\"panda_face\"],\"tags\":[]},{\"emoji\":\"🐨\",\"category\":\"nature\",\"description\":\"koala\",\"names\":[\"koala\"],\"tags\":[]},{\"emoji\":\"🐯\",\"category\":\"nature\",\"description\":\"tiger face\",\"names\":[\"tiger\"],\"tags\":[]},{\"emoji\":\"🐮\",\"category\":\"nature\",\"description\":\"cow face\",\"names\":[\"cow\"],\"tags\":[]},{\"emoji\":\"🐷\",\"category\":\"nature\",\"description\":\"pig face\",\"names\":[\"pig\"],\"tags\":[]},{\"emoji\":\"🐽\",\"category\":\"nature\",\"description\":\"pig nose\",\"names\":[\"pig_nose\"],\"tags\":[]},{\"emoji\":\"🐸\",\"category\":\"nature\",\"description\":\"frog face\",\"names\":[\"frog\"],\"tags\":[]},{\"emoji\":\"🐵\",\"category\":\"nature\",\"description\":\"monkey face\",\"names\":[\"monkey_face\"],\"tags\":[]},{\"emoji\":\"🙈\",\"category\":\"nature\",\"description\":\"see-no-evil monkey\",\"names\":[\"see_no_evil\"],\"tags\":[\"monkey\",\"blind\",\"ignore\"]},{\"emoji\":\"🙉\",\"category\":\"nature\",\"description\":\"hear-no-evil monkey\",\"names\":[\"hear_no_evil\"],\"tags\":[\"monkey\",\"deaf\"]},{\"emoji\":\"🙊\",\"category\":\"nature\",\"description\":\"speak-no-evil monkey\",\"names\":[\"speak_no_evil\"],\"tags\":[\"monkey\",\"mute\",\"hush\"]},{\"emoji\":\"🐒\",\"category\":\"nature\",\"description\":\"monkey\",\"names\":[\"monkey\"],\"tags\":[]},{\"emoji\":\"🐔\",\"category\":\"nature\",\"description\":\"chicken\",\"names\":[\"chicken\"],\"tags\":[]},{\"emoji\":\"🐧\",\"category\":\"nature\",\"description\":\"penguin\",\"names\":[\"penguin\"],\"tags\":[]},{\"emoji\":\"🐦\",\"category\":\"nature\",\"description\":\"bird\",\"names\":[\"bird\"],\"tags\":[]},{\"emoji\":\"🐤\",\"category\":\"nature\",\"description\":\"baby chick\",\"names\":[\"baby_chick\"],\"tags\":[]},{\"emoji\":\"🐣\",\"category\":\"nature\",\"description\":\"hatching chick\",\"names\":[\"hatching_chick\"],\"tags\":[]},{\"emoji\":\"🐥\",\"category\":\"nature\",\"description\":\"front-facing baby chick\",\"names\":[\"hatched_chick\"],\"tags\":[]},{\"emoji\":\"🐺\",\"category\":\"nature\",\"description\":\"wolf face\",\"names\":[\"wolf\"],\"tags\":[]},{\"emoji\":\"🐗\",\"category\":\"nature\",\"description\":\"boar\",\"names\":[\"boar\"],\"tags\":[]},{\"emoji\":\"🐴\",\"category\":\"nature\",\"description\":\"horse face\",\"names\":[\"horse\"],\"tags\":[]},{\"emoji\":\"🐝\",\"category\":\"nature\",\"description\":\"honeybee\",\"names\":[\"bee\",\"honeybee\"],\"tags\":[]},{\"emoji\":\"🐛\",\"category\":\"nature\",\"description\":\"bug\",\"names\":[\"bug\"],\"tags\":[]},{\"emoji\":\"🐌\",\"category\":\"nature\",\"description\":\"snail\",\"names\":[\"snail\"],\"tags\":[\"slow\"]},{\"emoji\":\"🐚\",\"category\":\"nature\",\"description\":\"spiral shell\",\"names\":[\"shell\"],\"tags\":[\"sea\",\"beach\"]},{\"emoji\":\"🐞\",\"category\":\"nature\",\"description\":\"lady beetle\",\"names\":[\"beetle\"],\"tags\":[\"bug\"]},{\"emoji\":\"🐜\",\"category\":\"nature\",\"description\":\"ant\",\"names\":[\"ant\"],\"tags\":[]},{\"emoji\":\"🐢\",\"category\":\"nature\",\"description\":\"turtle\",\"names\":[\"turtle\"],\"tags\":[\"slow\"]},{\"emoji\":\"🐍\",\"category\":\"nature\",\"description\":\"snake\",\"names\":[\"snake\"],\"tags\":[]},{\"emoji\":\"🐙\",\"category\":\"nature\",\"description\":\"octopus\",\"names\":[\"octopus\"],\"tags\":[]},{\"emoji\":\"🐠\",\"category\":\"nature\",\"description\":\"tropical fish\",\"names\":[\"tropical_fish\"],\"tags\":[]},{\"emoji\":\"🐟\",\"category\":\"nature\",\"description\":\"fish\",\"names\":[\"fish\"],\"tags\":[]},{\"emoji\":\"🐡\",\"category\":\"nature\",\"description\":\"blowfish\",\"names\":[\"blowfish\"],\"tags\":[]},{\"emoji\":\"🐬\",\"category\":\"nature\",\"description\":\"dolphin\",\"names\":[\"dolphin\",\"flipper\"],\"tags\":[]},{\"emoji\":\"🐳\",\"category\":\"nature\",\"description\":\"spouting whale\",\"names\":[\"whale\"],\"tags\":[\"sea\"]},{\"emoji\":\"🐋\",\"category\":\"nature\",\"description\":\"whale\",\"names\":[\"whale2\"],\"tags\":[]},{\"emoji\":\"🐊\",\"category\":\"nature\",\"description\":\"crocodile\",\"names\":[\"crocodile\"],\"tags\":[]},{\"emoji\":\"🐆\",\"category\":\"nature\",\"description\":\"leopard\",\"names\":[\"leopard\"],\"tags\":[]},{\"emoji\":\"🐅\",\"category\":\"nature\",\"description\":\"tiger\",\"names\":[\"tiger2\"],\"tags\":[]},{\"emoji\":\"🐃\",\"category\":\"nature\",\"description\":\"water buffalo\",\"names\":[\"water_buffalo\"],\"tags\":[]},{\"emoji\":\"🐂\",\"category\":\"nature\",\"description\":\"ox\",\"names\":[\"ox\"],\"tags\":[]},{\"emoji\":\"🐄\",\"category\":\"nature\",\"description\":\"cow\",\"names\":[\"cow2\"],\"tags\":[]},{\"emoji\":\"🐪\",\"category\":\"nature\",\"description\":\"camel\",\"names\":[\"dromedary_camel\"],\"tags\":[\"desert\"]},{\"emoji\":\"🐫\",\"category\":\"nature\",\"description\":\"two-hump camel\",\"names\":[\"camel\"],\"tags\":[]},{\"emoji\":\"🐘\",\"category\":\"nature\",\"description\":\"elephant\",\"names\":[\"elephant\"],\"tags\":[]},{\"emoji\":\"🐎\",\"category\":\"nature\",\"description\":\"horse\",\"names\":[\"racehorse\"],\"tags\":[\"speed\"]},{\"emoji\":\"🐖\",\"category\":\"nature\",\"description\":\"pig\",\"names\":[\"pig2\"],\"tags\":[]},{\"emoji\":\"🐐\",\"category\":\"nature\",\"description\":\"goat\",\"names\":[\"goat\"],\"tags\":[]},{\"emoji\":\"🐏\",\"category\":\"nature\",\"description\":\"ram\",\"names\":[\"ram\"],\"tags\":[]},{\"emoji\":\"🐑\",\"category\":\"nature\",\"description\":\"sheep\",\"names\":[\"sheep\"],\"tags\":[]},{\"emoji\":\"🐕\",\"category\":\"nature\",\"description\":\"dog\",\"names\":[\"dog2\"],\"tags\":[]},{\"emoji\":\"🐩\",\"category\":\"nature\",\"description\":\"poodle\",\"names\":[\"poodle\"],\"tags\":[\"dog\"]},{\"emoji\":\"🐈\",\"category\":\"nature\",\"description\":\"cat\",\"names\":[\"cat2\"],\"tags\":[]},{\"emoji\":\"🐓\",\"category\":\"nature\",\"description\":\"rooster\",\"names\":[\"rooster\"],\"tags\":[]},{\"emoji\":\"🐇\",\"category\":\"nature\",\"description\":\"rabbit\",\"names\":[\"rabbit2\"],\"tags\":[]},{\"emoji\":\"🐁\",\"category\":\"nature\",\"description\":\"mouse\",\"names\":[\"mouse2\"],\"tags\":[]},{\"emoji\":\"🐀\",\"category\":\"nature\",\"description\":\"rat\",\"names\":[\"rat\"],\"tags\":[]},{\"emoji\":\"🐾\",\"category\":\"nature\",\"description\":\"paw prints\",\"names\":[\"feet\",\"paw_prints\"],\"tags\":[]},{\"emoji\":\"🐉\",\"category\":\"nature\",\"description\":\"dragon\",\"names\":[\"dragon\"],\"tags\":[]},{\"emoji\":\"🐲\",\"category\":\"nature\",\"description\":\"dragon face\",\"names\":[\"dragon_face\"],\"tags\":[]},{\"emoji\":\"🌵\",\"category\":\"nature\",\"description\":\"cactus\",\"names\":[\"cactus\"],\"tags\":[]},{\"emoji\":\"🎄\",\"category\":\"nature\",\"description\":\"Christmas tree\",\"names\":[\"christmas_tree\"],\"tags\":[]},{\"emoji\":\"🌲\",\"category\":\"nature\",\"description\":\"evergreen tree\",\"names\":[\"evergreen_tree\"],\"tags\":[\"wood\"]},{\"emoji\":\"🌳\",\"category\":\"nature\",\"description\":\"deciduous tree\",\"names\":[\"deciduous_tree\"],\"tags\":[\"wood\"]},{\"emoji\":\"🌴\",\"category\":\"nature\",\"description\":\"palm tree\",\"names\":[\"palm_tree\"],\"tags\":[]},{\"emoji\":\"🌱\",\"category\":\"nature\",\"description\":\"seedling\",\"names\":[\"seedling\"],\"tags\":[\"plant\"]},{\"emoji\":\"🌿\",\"category\":\"nature\",\"description\":\"herb\",\"names\":[\"herb\"],\"tags\":[]},{\"emoji\":\"☘️\",\"category\":\"nature\",\"description\":\"shamrock\",\"names\":[\"shamrock\"],\"tags\":[]},{\"emoji\":\"🍀\",\"category\":\"nature\",\"description\":\"four leaf clover\",\"names\":[\"four_leaf_clover\"],\"tags\":[\"luck\"]},{\"emoji\":\"🎍\",\"category\":\"nature\",\"description\":\"pine decoration\",\"names\":[\"bamboo\"],\"tags\":[]},{\"emoji\":\"🎋\",\"category\":\"nature\",\"description\":\"tanabata tree\",\"names\":[\"tanabata_tree\"],\"tags\":[]},{\"emoji\":\"🍃\",\"category\":\"nature\",\"description\":\"leaf fluttering in wind\",\"names\":[\"leaves\"],\"tags\":[\"leaf\"]},{\"emoji\":\"🍂\",\"category\":\"nature\",\"description\":\"fallen leaf\",\"names\":[\"fallen_leaf\"],\"tags\":[\"autumn\"]},{\"emoji\":\"🍁\",\"category\":\"nature\",\"description\":\"maple leaf\",\"names\":[\"maple_leaf\"],\"tags\":[\"canada\"]},{\"emoji\":\"🍄\",\"category\":\"nature\",\"description\":\"mushroom\",\"names\":[\"mushroom\"],\"tags\":[]},{\"emoji\":\"🌾\",\"category\":\"nature\",\"description\":\"sheaf of rice\",\"names\":[\"ear_of_rice\"],\"tags\":[]},{\"emoji\":\"💐\",\"category\":\"nature\",\"description\":\"bouquet\",\"names\":[\"bouquet\"],\"tags\":[\"flowers\"]},{\"emoji\":\"🌷\",\"category\":\"nature\",\"description\":\"tulip\",\"names\":[\"tulip\"],\"tags\":[\"flower\"]},{\"emoji\":\"🌹\",\"category\":\"nature\",\"description\":\"rose\",\"names\":[\"rose\"],\"tags\":[\"flower\"]},{\"emoji\":\"🌻\",\"category\":\"nature\",\"description\":\"sunflower\",\"names\":[\"sunflower\"],\"tags\":[]},{\"emoji\":\"🌼\",\"category\":\"nature\",\"description\":\"blossom\",\"names\":[\"blossom\"],\"tags\":[]},{\"emoji\":\"🌸\",\"category\":\"nature\",\"description\":\"cherry blossom\",\"names\":[\"cherry_blossom\"],\"tags\":[\"flower\",\"spring\"]},{\"emoji\":\"🌺\",\"category\":\"nature\",\"description\":\"hibiscus\",\"names\":[\"hibiscus\"],\"tags\":[]},{\"emoji\":\"🌎\",\"category\":\"nature\",\"description\":\"globe showing Americas\",\"names\":[\"earth_americas\"],\"tags\":[\"globe\",\"world\",\"international\"]},{\"emoji\":\"🌍\",\"category\":\"nature\",\"description\":\"globe showing Europe-Africa\",\"names\":[\"earth_africa\"],\"tags\":[\"globe\",\"world\",\"international\"]},{\"emoji\":\"🌏\",\"category\":\"nature\",\"description\":\"globe showing Asia-Australia\",\"names\":[\"earth_asia\"],\"tags\":[\"globe\",\"world\",\"international\"]},{\"emoji\":\"🌕\",\"category\":\"nature\",\"description\":\"full moon\",\"names\":[\"full_moon\"],\"tags\":[]},{\"emoji\":\"🌖\",\"category\":\"nature\",\"description\":\"waning gibbous moon\",\"names\":[\"waning_gibbous_moon\"],\"tags\":[]},{\"emoji\":\"🌗\",\"category\":\"nature\",\"description\":\"last quarter moon\",\"names\":[\"last_quarter_moon\"],\"tags\":[]},{\"emoji\":\"🌘\",\"category\":\"nature\",\"description\":\"waning crescent moon\",\"names\":[\"waning_crescent_moon\"],\"tags\":[]},{\"emoji\":\"🌑\",\"category\":\"nature\",\"description\":\"new moon\",\"names\":[\"new_moon\"],\"tags\":[]},{\"emoji\":\"🌒\",\"category\":\"nature\",\"description\":\"waxing crescent moon\",\"names\":[\"waxing_crescent_moon\"],\"tags\":[]},{\"emoji\":\"🌓\",\"category\":\"nature\",\"description\":\"first quarter moon\",\"names\":[\"first_quarter_moon\"],\"tags\":[]},{\"emoji\":\"🌔\",\"category\":\"nature\",\"description\":\"waxing gibbous moon\",\"names\":[\"moon\",\"waxing_gibbous_moon\"],\"tags\":[]},{\"emoji\":\"🌚\",\"category\":\"nature\",\"description\":\"new moon face\",\"names\":[\"new_moon_with_face\"],\"tags\":[]},{\"emoji\":\"🌝\",\"category\":\"nature\",\"description\":\"full moon with face\",\"names\":[\"full_moon_with_face\"],\"tags\":[]},{\"emoji\":\"🌞\",\"category\":\"nature\",\"description\":\"sun with face\",\"names\":[\"sun_with_face\"],\"tags\":[\"summer\"]},{\"emoji\":\"🌛\",\"category\":\"nature\",\"description\":\"first quarter moon with face\",\"names\":[\"first_quarter_moon_with_face\"],\"tags\":[]},{\"emoji\":\"🌜\",\"category\":\"nature\",\"description\":\"last quarter moon with face\",\"names\":[\"last_quarter_moon_with_face\"],\"tags\":[]},{\"emoji\":\"🌙\",\"category\":\"nature\",\"description\":\"crescent moon\",\"names\":[\"crescent_moon\"],\"tags\":[\"night\"]},{\"emoji\":\"💫\",\"category\":\"nature\",\"description\":\"dizzy\",\"names\":[\"dizzy\"],\"tags\":[\"star\"]},{\"emoji\":\"⭐️\",\"category\":\"nature\",\"description\":\"white medium star\",\"names\":[\"star\"],\"tags\":[]},{\"emoji\":\"🌟\",\"category\":\"nature\",\"description\":\"glowing star\",\"names\":[\"star2\"],\"tags\":[]},{\"emoji\":\"✨\",\"category\":\"nature\",\"description\":\"sparkles\",\"names\":[\"sparkles\"],\"tags\":[\"shiny\"]},{\"emoji\":\"⚡️\",\"category\":\"nature\",\"description\":\"high voltage\",\"names\":[\"zap\"],\"tags\":[\"lightning\",\"thunder\"]},{\"emoji\":\"🔥\",\"category\":\"nature\",\"description\":\"fire\",\"names\":[\"fire\"],\"tags\":[\"burn\"]},{\"emoji\":\"💥\",\"category\":\"nature\",\"description\":\"collision\",\"names\":[\"boom\",\"collision\"],\"tags\":[\"explode\"]},{\"emoji\":\"☄\",\"category\":\"nature\",\"description\":\"comet\",\"names\":[\"comet\"],\"tags\":[]},{\"emoji\":\"☀️\",\"category\":\"nature\",\"description\":\"sun\",\"names\":[\"sunny\"],\"tags\":[\"weather\"]},{\"emoji\":\"⛅️\",\"category\":\"nature\",\"description\":\"sun behind cloud\",\"names\":[\"partly_sunny\"],\"tags\":[\"weather\",\"cloud\"]},{\"emoji\":\"🌈\",\"category\":\"nature\",\"description\":\"rainbow\",\"names\":[\"rainbow\"],\"tags\":[]},{\"emoji\":\"☁️\",\"category\":\"nature\",\"description\":\"cloud\",\"names\":[\"cloud\"],\"tags\":[]},{\"emoji\":\"☃️\",\"category\":\"nature\",\"description\":\"snowman\",\"names\":[\"snowman_with_snow\"],\"tags\":[\"winter\",\"christmas\"]},{\"emoji\":\"⛄️\",\"category\":\"nature\",\"description\":\"snowman without snow\",\"names\":[\"snowman\"],\"tags\":[\"winter\"]},{\"emoji\":\"❄️\",\"category\":\"nature\",\"description\":\"snowflake\",\"names\":[\"snowflake\"],\"tags\":[\"winter\",\"cold\",\"weather\"]},{\"emoji\":\"💨\",\"category\":\"nature\",\"description\":\"dashing away\",\"names\":[\"dash\"],\"tags\":[\"wind\",\"blow\",\"fast\"]},{\"emoji\":\"🌊\",\"category\":\"nature\",\"description\":\"water wave\",\"names\":[\"ocean\"],\"tags\":[\"sea\"]},{\"emoji\":\"💧\",\"category\":\"nature\",\"description\":\"droplet\",\"names\":[\"droplet\"],\"tags\":[\"water\"]},{\"emoji\":\"💦\",\"category\":\"nature\",\"description\":\"sweat droplets\",\"names\":[\"sweat_drops\"],\"tags\":[\"water\",\"workout\"]},{\"emoji\":\"☔️\",\"category\":\"nature\",\"description\":\"umbrella with rain drops\",\"names\":[\"umbrella\"],\"tags\":[\"rain\",\"weather\"]},{\"emoji\":\"🍏\",\"category\":\"foods\",\"description\":\"green apple\",\"names\":[\"green_apple\"],\"tags\":[\"fruit\"]},{\"emoji\":\"🍎\",\"category\":\"foods\",\"description\":\"red apple\",\"names\":[\"apple\"],\"tags\":[]},{\"emoji\":\"🍐\",\"category\":\"foods\",\"description\":\"pear\",\"names\":[\"pear\"],\"tags\":[]},{\"emoji\":\"🍊\",\"category\":\"foods\",\"description\":\"tangerine\",\"names\":[\"tangerine\",\"orange\",\"mandarin\"],\"tags\":[]},{\"emoji\":\"🍋\",\"category\":\"foods\",\"description\":\"lemon\",\"names\":[\"lemon\"],\"tags\":[]},{\"emoji\":\"🍌\",\"category\":\"foods\",\"description\":\"banana\",\"names\":[\"banana\"],\"tags\":[\"fruit\"]},{\"emoji\":\"🍉\",\"category\":\"foods\",\"description\":\"watermelon\",\"names\":[\"watermelon\"],\"tags\":[]},{\"emoji\":\"🍇\",\"category\":\"foods\",\"description\":\"grapes\",\"names\":[\"grapes\"],\"tags\":[]},{\"emoji\":\"🍓\",\"category\":\"foods\",\"description\":\"strawberry\",\"names\":[\"strawberry\"],\"tags\":[\"fruit\"]},{\"emoji\":\"🍈\",\"category\":\"foods\",\"description\":\"melon\",\"names\":[\"melon\"],\"tags\":[]},{\"emoji\":\"🍒\",\"category\":\"foods\",\"description\":\"cherries\",\"names\":[\"cherries\"],\"tags\":[\"fruit\"]},{\"emoji\":\"🍑\",\"category\":\"foods\",\"description\":\"peach\",\"names\":[\"peach\"],\"tags\":[]},{\"emoji\":\"🍍\",\"category\":\"foods\",\"description\":\"pineapple\",\"names\":[\"pineapple\"],\"tags\":[]},{\"emoji\":\"🍅\",\"category\":\"foods\",\"description\":\"tomato\",\"names\":[\"tomato\"],\"tags\":[]},{\"emoji\":\"🍆\",\"category\":\"foods\",\"description\":\"eggplant\",\"names\":[\"eggplant\"],\"tags\":[\"aubergine\"]},{\"emoji\":\"🌽\",\"category\":\"foods\",\"description\":\"ear of corn\",\"names\":[\"corn\"],\"tags\":[]},{\"emoji\":\"🍠\",\"category\":\"foods\",\"description\":\"roasted sweet potato\",\"names\":[\"sweet_potato\"],\"tags\":[]},{\"emoji\":\"🌰\",\"category\":\"foods\",\"description\":\"chestnut\",\"names\":[\"chestnut\"],\"tags\":[]},{\"emoji\":\"🍯\",\"category\":\"foods\",\"description\":\"honey pot\",\"names\":[\"honey_pot\"],\"tags\":[]},{\"emoji\":\"🍞\",\"category\":\"foods\",\"description\":\"bread\",\"names\":[\"bread\"],\"tags\":[\"toast\"]},{\"emoji\":\"🍳\",\"category\":\"foods\",\"description\":\"cooking\",\"names\":[\"fried_egg\"],\"tags\":[\"breakfast\"]},{\"emoji\":\"🍤\",\"category\":\"foods\",\"description\":\"fried shrimp\",\"names\":[\"fried_shrimp\"],\"tags\":[\"tempura\"]},{\"emoji\":\"🍗\",\"category\":\"foods\",\"description\":\"poultry leg\",\"names\":[\"poultry_leg\"],\"tags\":[\"meat\",\"chicken\"]},{\"emoji\":\"🍖\",\"category\":\"foods\",\"description\":\"meat on bone\",\"names\":[\"meat_on_bone\"],\"tags\":[]},{\"emoji\":\"🍕\",\"category\":\"foods\",\"description\":\"pizza\",\"names\":[\"pizza\"],\"tags\":[]},{\"emoji\":\"🍔\",\"category\":\"foods\",\"description\":\"hamburger\",\"names\":[\"hamburger\"],\"tags\":[\"burger\"]},{\"emoji\":\"🍟\",\"category\":\"foods\",\"description\":\"french fries\",\"names\":[\"fries\"],\"tags\":[]},{\"emoji\":\"🍝\",\"category\":\"foods\",\"description\":\"spaghetti\",\"names\":[\"spaghetti\"],\"tags\":[\"pasta\"]},{\"emoji\":\"🍜\",\"category\":\"foods\",\"description\":\"steaming bowl\",\"names\":[\"ramen\"],\"tags\":[\"noodle\"]},{\"emoji\":\"🍲\",\"category\":\"foods\",\"description\":\"pot of food\",\"names\":[\"stew\"],\"tags\":[]},{\"emoji\":\"🍥\",\"category\":\"foods\",\"description\":\"fish cake with swirl\",\"names\":[\"fish_cake\"],\"tags\":[]},{\"emoji\":\"🍣\",\"category\":\"foods\",\"description\":\"sushi\",\"names\":[\"sushi\"],\"tags\":[]},{\"emoji\":\"🍱\",\"category\":\"foods\",\"description\":\"bento box\",\"names\":[\"bento\"],\"tags\":[]},{\"emoji\":\"🍛\",\"category\":\"foods\",\"description\":\"curry rice\",\"names\":[\"curry\"],\"tags\":[]},{\"emoji\":\"🍚\",\"category\":\"foods\",\"description\":\"cooked rice\",\"names\":[\"rice\"],\"tags\":[]},{\"emoji\":\"🍙\",\"category\":\"foods\",\"description\":\"rice ball\",\"names\":[\"rice_ball\"],\"tags\":[]},{\"emoji\":\"🍘\",\"category\":\"foods\",\"description\":\"rice cracker\",\"names\":[\"rice_cracker\"],\"tags\":[]},{\"emoji\":\"🍢\",\"category\":\"foods\",\"description\":\"oden\",\"names\":[\"oden\"],\"tags\":[]},{\"emoji\":\"🍡\",\"category\":\"foods\",\"description\":\"dango\",\"names\":[\"dango\"],\"tags\":[]},{\"emoji\":\"🍧\",\"category\":\"foods\",\"description\":\"shaved ice\",\"names\":[\"shaved_ice\"],\"tags\":[]},{\"emoji\":\"🍨\",\"category\":\"foods\",\"description\":\"ice cream\",\"names\":[\"ice_cream\"],\"tags\":[]},{\"emoji\":\"🍦\",\"category\":\"foods\",\"description\":\"soft ice cream\",\"names\":[\"icecream\"],\"tags\":[]},{\"emoji\":\"🍰\",\"category\":\"foods\",\"description\":\"shortcake\",\"names\":[\"cake\"],\"tags\":[\"dessert\"]},{\"emoji\":\"🎂\",\"category\":\"foods\",\"description\":\"birthday cake\",\"names\":[\"birthday\"],\"tags\":[\"party\"]},{\"emoji\":\"🍮\",\"category\":\"foods\",\"description\":\"custard\",\"names\":[\"custard\"],\"tags\":[]},{\"emoji\":\"🍭\",\"category\":\"foods\",\"description\":\"lollipop\",\"names\":[\"lollipop\"],\"tags\":[]},{\"emoji\":\"🍬\",\"category\":\"foods\",\"description\":\"candy\",\"names\":[\"candy\"],\"tags\":[\"sweet\"]},{\"emoji\":\"🍫\",\"category\":\"foods\",\"description\":\"chocolate bar\",\"names\":[\"chocolate_bar\"],\"tags\":[]},{\"emoji\":\"🍩\",\"category\":\"foods\",\"description\":\"doughnut\",\"names\":[\"doughnut\"],\"tags\":[]},{\"emoji\":\"🍪\",\"category\":\"foods\",\"description\":\"cookie\",\"names\":[\"cookie\"],\"tags\":[]},{\"emoji\":\"🍼\",\"category\":\"foods\",\"description\":\"baby bottle\",\"names\":[\"baby_bottle\"],\"tags\":[\"milk\"]},{\"emoji\":\"☕️\",\"category\":\"foods\",\"description\":\"hot beverage\",\"names\":[\"coffee\"],\"tags\":[\"cafe\",\"espresso\"]},{\"emoji\":\"🍵\",\"category\":\"foods\",\"description\":\"teacup without handle\",\"names\":[\"tea\"],\"tags\":[\"green\",\"breakfast\"]},{\"emoji\":\"🍶\",\"category\":\"foods\",\"description\":\"sake\",\"names\":[\"sake\"],\"tags\":[]},{\"emoji\":\"🍺\",\"category\":\"foods\",\"description\":\"beer mug\",\"names\":[\"beer\"],\"tags\":[\"drink\"]},{\"emoji\":\"🍻\",\"category\":\"foods\",\"description\":\"clinking beer mugs\",\"names\":[\"beers\"],\"tags\":[\"drinks\"]},{\"emoji\":\"🍷\",\"category\":\"foods\",\"description\":\"wine glass\",\"names\":[\"wine_glass\"],\"tags\":[]},{\"emoji\":\"🥃\",\"category\":\"foods\",\"description\":\"tumbler glass\",\"names\":[\"tumbler_glass\"],\"tags\":[\"whisky\"]},{\"emoji\":\"🍸\",\"category\":\"foods\",\"description\":\"cocktail glass\",\"names\":[\"cocktail\"],\"tags\":[\"drink\"]},{\"emoji\":\"🍹\",\"category\":\"foods\",\"description\":\"tropical drink\",\"names\":[\"tropical_drink\"],\"tags\":[\"summer\",\"vacation\"]},{\"emoji\":\"🍴\",\"category\":\"foods\",\"description\":\"fork and knife\",\"names\":[\"fork_and_knife\"],\"tags\":[\"cutlery\"]},{\"emoji\":\"⚽️\",\"category\":\"activity\",\"description\":\"soccer ball\",\"names\":[\"soccer\"],\"tags\":[\"sports\"]},{\"emoji\":\"🏀\",\"category\":\"activity\",\"description\":\"basketball\",\"names\":[\"basketball\"],\"tags\":[\"sports\"]},{\"emoji\":\"🏈\",\"category\":\"activity\",\"description\":\"american football\",\"names\":[\"football\"],\"tags\":[\"sports\"]},{\"emoji\":\"⚾️\",\"category\":\"activity\",\"description\":\"baseball\",\"names\":[\"baseball\"],\"tags\":[\"sports\"]},{\"emoji\":\"🎾\",\"category\":\"activity\",\"description\":\"tennis\",\"names\":[\"tennis\"],\"tags\":[\"sports\"]},{\"emoji\":\"🏉\",\"category\":\"activity\",\"description\":\"rugby football\",\"names\":[\"rugby_football\"],\"tags\":[]},{\"emoji\":\"🎱\",\"category\":\"activity\",\"description\":\"pool 8 ball\",\"names\":[\"8ball\"],\"tags\":[\"pool\",\"billiards\"]},{\"emoji\":\"⛳️\",\"category\":\"activity\",\"description\":\"flag in hole\",\"names\":[\"golf\"],\"tags\":[]},{\"emoji\":\"🎣\",\"category\":\"activity\",\"description\":\"fishing pole\",\"names\":[\"fishing_pole_and_fish\"],\"tags\":[]},{\"emoji\":\"⛸\",\"category\":\"activity\",\"description\":\"ice skate\",\"names\":[\"ice_skate\"],\"tags\":[\"skating\"]},{\"emoji\":\"🎿\",\"category\":\"activity\",\"description\":\"skis\",\"names\":[\"ski\"],\"tags\":[]},{\"emoji\":\"⛷\",\"category\":\"activity\",\"description\":\"skier\",\"names\":[\"skier\"],\"tags\":[]},{\"emoji\":\"🏂\",\"category\":\"activity\",\"description\":\"snowboarder\",\"names\":[\"snowboarder\"],\"tags\":[]},{\"emoji\":\"⛹\",\"category\":\"activity\",\"description\":\"person bouncing ball\",\"names\":[\"basketball_man\"],\"tags\":[]},{\"emoji\":\"🏄\",\"category\":\"activity\",\"description\":\"person surfing\",\"names\":[\"surfing_man\",\"surfer\"],\"tags\":[]},{\"emoji\":\"🏊\",\"category\":\"activity\",\"description\":\"person swimming\",\"names\":[\"swimming_man\",\"swimmer\"],\"tags\":[]},{\"emoji\":\"🚣\",\"category\":\"activity\",\"description\":\"person rowing boat\",\"names\":[\"rowing_man\",\"rowboat\"],\"tags\":[]},{\"emoji\":\"🏇\",\"category\":\"activity\",\"description\":\"horse racing\",\"names\":[\"horse_racing\"],\"tags\":[]},{\"emoji\":\"🚴\",\"category\":\"activity\",\"description\":\"person biking\",\"names\":[\"biking_man\",\"bicyclist\"],\"tags\":[]},{\"emoji\":\"🚵\",\"category\":\"activity\",\"description\":\"person mountain biking\",\"names\":[\"mountain_biking_man\",\"mountain_bicyclist\"],\"tags\":[]},{\"emoji\":\"🎽\",\"category\":\"activity\",\"description\":\"running shirt\",\"names\":[\"running_shirt_with_sash\"],\"tags\":[\"marathon\"]},{\"emoji\":\"🏆\",\"category\":\"activity\",\"description\":\"trophy\",\"names\":[\"trophy\"],\"tags\":[\"award\",\"contest\",\"winner\"]},{\"emoji\":\"🎪\",\"category\":\"activity\",\"description\":\"circus tent\",\"names\":[\"circus_tent\"],\"tags\":[]},{\"emoji\":\"🎭\",\"category\":\"activity\",\"description\":\"performing arts\",\"names\":[\"performing_arts\"],\"tags\":[\"theater\",\"drama\"]},{\"emoji\":\"🎨\",\"category\":\"activity\",\"description\":\"artist palette\",\"names\":[\"art\"],\"tags\":[\"design\",\"paint\"]},{\"emoji\":\"🎬\",\"category\":\"activity\",\"description\":\"clapper board\",\"names\":[\"clapper\"],\"tags\":[\"film\"]},{\"emoji\":\"🎤\",\"category\":\"activity\",\"description\":\"microphone\",\"names\":[\"microphone\"],\"tags\":[\"sing\"]},{\"emoji\":\"🎧\",\"category\":\"activity\",\"description\":\"headphone\",\"names\":[\"headphones\"],\"tags\":[\"music\",\"earphones\"]},{\"emoji\":\"🎼\",\"category\":\"activity\",\"description\":\"musical score\",\"names\":[\"musical_score\"],\"tags\":[]},{\"emoji\":\"🎹\",\"category\":\"activity\",\"description\":\"musical keyboard\",\"names\":[\"musical_keyboard\"],\"tags\":[\"piano\"]},{\"emoji\":\"🎷\",\"category\":\"activity\",\"description\":\"saxophone\",\"names\":[\"saxophone\"],\"tags\":[]},{\"emoji\":\"🎺\",\"category\":\"activity\",\"description\":\"trumpet\",\"names\":[\"trumpet\"],\"tags\":[]},{\"emoji\":\"🎸\",\"category\":\"activity\",\"description\":\"guitar\",\"names\":[\"guitar\"],\"tags\":[\"rock\"]},{\"emoji\":\"🎻\",\"category\":\"activity\",\"description\":\"violin\",\"names\":[\"violin\"],\"tags\":[]},{\"emoji\":\"🎲\",\"category\":\"activity\",\"description\":\"game die\",\"names\":[\"game_die\"],\"tags\":[\"dice\",\"gambling\"]},{\"emoji\":\"🎯\",\"category\":\"activity\",\"description\":\"direct hit\",\"names\":[\"dart\"],\"tags\":[\"target\"]},{\"emoji\":\"🎳\",\"category\":\"activity\",\"description\":\"bowling\",\"names\":[\"bowling\"],\"tags\":[]},{\"emoji\":\"🎮\",\"category\":\"activity\",\"description\":\"video game\",\"names\":[\"video_game\"],\"tags\":[\"play\",\"controller\",\"console\"]},{\"emoji\":\"🎰\",\"category\":\"activity\",\"description\":\"slot machine\",\"names\":[\"slot_machine\"],\"tags\":[]},{\"emoji\":\"🚗\",\"category\":\"places\",\"description\":\"automobile\",\"names\":[\"car\",\"red_car\"],\"tags\":[]},{\"emoji\":\"🚕\",\"category\":\"places\",\"description\":\"taxi\",\"names\":[\"taxi\"],\"tags\":[]},{\"emoji\":\"🚙\",\"category\":\"places\",\"description\":\"sport utility vehicle\",\"names\":[\"blue_car\"],\"tags\":[]},{\"emoji\":\"🚌\",\"category\":\"places\",\"description\":\"bus\",\"names\":[\"bus\"],\"tags\":[]},{\"emoji\":\"🚎\",\"category\":\"places\",\"description\":\"trolleybus\",\"names\":[\"trolleybus\"],\"tags\":[]},{\"emoji\":\"🚓\",\"category\":\"places\",\"description\":\"police car\",\"names\":[\"police_car\"],\"tags\":[]},{\"emoji\":\"🚑\",\"category\":\"places\",\"description\":\"ambulance\",\"names\":[\"ambulance\"],\"tags\":[]},{\"emoji\":\"🚒\",\"category\":\"places\",\"description\":\"fire engine\",\"names\":[\"fire_engine\"],\"tags\":[]},{\"emoji\":\"🚐\",\"category\":\"places\",\"description\":\"minibus\",\"names\":[\"minibus\"],\"tags\":[]},{\"emoji\":\"🚚\",\"category\":\"places\",\"description\":\"delivery truck\",\"names\":[\"truck\"],\"tags\":[]},{\"emoji\":\"🚛\",\"category\":\"places\",\"description\":\"articulated lorry\",\"names\":[\"articulated_lorry\"],\"tags\":[]},{\"emoji\":\"🚜\",\"category\":\"places\",\"description\":\"tractor\",\"names\":[\"tractor\"],\"tags\":[]},{\"emoji\":\"🚲\",\"category\":\"places\",\"description\":\"bicycle\",\"names\":[\"bike\"],\"tags\":[\"bicycle\"]},{\"emoji\":\"🚨\",\"category\":\"places\",\"description\":\"police car light\",\"names\":[\"rotating_light\"],\"tags\":[\"911\",\"emergency\"]},{\"emoji\":\"🚔\",\"category\":\"places\",\"description\":\"oncoming police car\",\"names\":[\"oncoming_police_car\"],\"tags\":[]},{\"emoji\":\"🚍\",\"category\":\"places\",\"description\":\"oncoming bus\",\"names\":[\"oncoming_bus\"],\"tags\":[]},{\"emoji\":\"🚘\",\"category\":\"places\",\"description\":\"oncoming automobile\",\"names\":[\"oncoming_automobile\"],\"tags\":[]},{\"emoji\":\"🚖\",\"category\":\"places\",\"description\":\"oncoming taxi\",\"names\":[\"oncoming_taxi\"],\"tags\":[]},{\"emoji\":\"🚡\",\"category\":\"places\",\"description\":\"aerial tramway\",\"names\":[\"aerial_tramway\"],\"tags\":[]},{\"emoji\":\"🚠\",\"category\":\"places\",\"description\":\"mountain cableway\",\"names\":[\"mountain_cableway\"],\"tags\":[]},{\"emoji\":\"🚟\",\"category\":\"places\",\"description\":\"suspension railway\",\"names\":[\"suspension_railway\"],\"tags\":[]},{\"emoji\":\"🚃\",\"category\":\"places\",\"description\":\"railway car\",\"names\":[\"railway_car\"],\"tags\":[]},{\"emoji\":\"🚋\",\"category\":\"places\",\"description\":\"tram car\",\"names\":[\"train\"],\"tags\":[]},{\"emoji\":\"🚞\",\"category\":\"places\",\"description\":\"mountain railway\",\"names\":[\"mountain_railway\"],\"tags\":[]},{\"emoji\":\"🚝\",\"category\":\"places\",\"description\":\"monorail\",\"names\":[\"monorail\"],\"tags\":[]},{\"emoji\":\"🚄\",\"category\":\"places\",\"description\":\"high-speed train\",\"names\":[\"bullettrain_side\"],\"tags\":[\"train\"]},{\"emoji\":\"🚅\",\"category\":\"places\",\"description\":\"high-speed train with bullet nose\",\"names\":[\"bullettrain_front\"],\"tags\":[\"train\"]},{\"emoji\":\"🚈\",\"category\":\"places\",\"description\":\"light rail\",\"names\":[\"light_rail\"],\"tags\":[]},{\"emoji\":\"🚂\",\"category\":\"places\",\"description\":\"locomotive\",\"names\":[\"steam_locomotive\"],\"tags\":[\"train\"]},{\"emoji\":\"🚆\",\"category\":\"places\",\"description\":\"train\",\"names\":[\"train2\"],\"tags\":[]},{\"emoji\":\"🚇\",\"category\":\"places\",\"description\":\"metro\",\"names\":[\"metro\"],\"tags\":[]},{\"emoji\":\"🚊\",\"category\":\"places\",\"description\":\"tram\",\"names\":[\"tram\"],\"tags\":[]},{\"emoji\":\"🚉\",\"category\":\"places\",\"description\":\"station\",\"names\":[\"station\"],\"tags\":[]},{\"emoji\":\"🚁\",\"category\":\"places\",\"description\":\"helicopter\",\"names\":[\"helicopter\"],\"tags\":[]},{\"emoji\":\"✈️\",\"category\":\"places\",\"description\":\"airplane\",\"names\":[\"airplane\"],\"tags\":[\"flight\"]},{\"emoji\":\"🚀\",\"category\":\"places\",\"description\":\"rocket\",\"names\":[\"rocket\"],\"tags\":[\"ship\",\"launch\"]},{\"emoji\":\"💺\",\"category\":\"places\",\"description\":\"seat\",\"names\":[\"seat\"],\"tags\":[]},{\"emoji\":\"⛵️\",\"category\":\"places\",\"description\":\"sailboat\",\"names\":[\"boat\",\"sailboat\"],\"tags\":[]},{\"emoji\":\"🚤\",\"category\":\"places\",\"description\":\"speedboat\",\"names\":[\"speedboat\"],\"tags\":[\"ship\"]},{\"emoji\":\"⛴\",\"category\":\"places\",\"description\":\"ferry\",\"names\":[\"ferry\"],\"tags\":[]},{\"emoji\":\"🚢\",\"category\":\"places\",\"description\":\"ship\",\"names\":[\"ship\"],\"tags\":[]},{\"emoji\":\"⚓️\",\"category\":\"places\",\"description\":\"anchor\",\"names\":[\"anchor\"],\"tags\":[\"ship\"]},{\"emoji\":\"🚧\",\"category\":\"places\",\"description\":\"construction\",\"names\":[\"construction\"],\"tags\":[\"wip\"]},{\"emoji\":\"⛽️\",\"category\":\"places\",\"description\":\"fuel pump\",\"names\":[\"fuelpump\"],\"tags\":[]},{\"emoji\":\"🚏\",\"category\":\"places\",\"description\":\"bus stop\",\"names\":[\"busstop\"],\"tags\":[]},{\"emoji\":\"🚦\",\"category\":\"places\",\"description\":\"vertical traffic light\",\"names\":[\"vertical_traffic_light\"],\"tags\":[\"semaphore\"]},{\"emoji\":\"🚥\",\"category\":\"places\",\"description\":\"horizontal traffic light\",\"names\":[\"traffic_light\"],\"tags\":[]},{\"emoji\":\"🗿\",\"category\":\"places\",\"description\":\"moai\",\"names\":[\"moyai\"],\"tags\":[\"stone\"]},{\"emoji\":\"🗽\",\"category\":\"places\",\"description\":\"Statue of Liberty\",\"names\":[\"statue_of_liberty\"],\"tags\":[]},{\"emoji\":\"⛲️\",\"category\":\"places\",\"description\":\"fountain\",\"names\":[\"fountain\"],\"tags\":[]},{\"emoji\":\"🗼\",\"category\":\"places\",\"description\":\"Tokyo tower\",\"names\":[\"tokyo_tower\"],\"tags\":[]},{\"emoji\":\"🏰\",\"category\":\"places\",\"description\":\"castle\",\"names\":[\"european_castle\"],\"tags\":[]},{\"emoji\":\"🏯\",\"category\":\"places\",\"description\":\"Japanese castle\",\"names\":[\"japanese_castle\"],\"tags\":[]},{\"emoji\":\"🎡\",\"category\":\"places\",\"description\":\"ferris wheel\",\"names\":[\"ferris_wheel\"],\"tags\":[]},{\"emoji\":\"🎢\",\"category\":\"places\",\"description\":\"roller coaster\",\"names\":[\"roller_coaster\"],\"tags\":[]},{\"emoji\":\"🎠\",\"category\":\"places\",\"description\":\"carousel horse\",\"names\":[\"carousel_horse\"],\"tags\":[]},{\"emoji\":\"⛰\",\"category\":\"places\",\"description\":\"mountain\",\"names\":[\"mountain\"],\"tags\":[]},{\"emoji\":\"🗻\",\"category\":\"places\",\"description\":\"mount fuji\",\"names\":[\"mount_fuji\"],\"tags\":[]},{\"emoji\":\"🌋\",\"category\":\"places\",\"description\":\"volcano\",\"names\":[\"volcano\"],\"tags\":[]},{\"emoji\":\"⛺️\",\"category\":\"places\",\"description\":\"tent\",\"names\":[\"tent\"],\"tags\":[\"camping\"]},{\"emoji\":\"🏭\",\"category\":\"places\",\"description\":\"factory\",\"names\":[\"factory\"],\"tags\":[]},{\"emoji\":\"🏡\",\"category\":\"places\",\"description\":\"house with garden\",\"names\":[\"house_with_garden\"],\"tags\":[]},{\"emoji\":\"🏢\",\"category\":\"places\",\"description\":\"office building\",\"names\":[\"office\"],\"tags\":[]},{\"emoji\":\"🏬\",\"category\":\"places\",\"description\":\"department store\",\"names\":[\"department_store\"],\"tags\":[]},{\"emoji\":\"🏣\",\"category\":\"places\",\"description\":\"Japanese post office\",\"names\":[\"post_office\"],\"tags\":[]},{\"emoji\":\"🏤\",\"category\":\"places\",\"description\":\"post office\",\"names\":[\"european_post_office\"],\"tags\":[]},{\"emoji\":\"🏥\",\"category\":\"places\",\"description\":\"hospital\",\"names\":[\"hospital\"],\"tags\":[]},{\"emoji\":\"🏦\",\"category\":\"places\",\"description\":\"bank\",\"names\":[\"bank\"],\"tags\":[]},{\"emoji\":\"🏨\",\"category\":\"places\",\"description\":\"hotel\",\"names\":[\"hotel\"],\"tags\":[]},{\"emoji\":\"🏪\",\"category\":\"places\",\"description\":\"convenience store\",\"names\":[\"convenience_store\"],\"tags\":[]},{\"emoji\":\"🏫\",\"category\":\"places\",\"description\":\"school\",\"names\":[\"school\"],\"tags\":[]},{\"emoji\":\"🏩\",\"category\":\"places\",\"description\":\"love hotel\",\"names\":[\"love_hotel\"],\"tags\":[]},{\"emoji\":\"💒\",\"category\":\"places\",\"description\":\"wedding\",\"names\":[\"wedding\"],\"tags\":[\"marriage\"]},{\"emoji\":\"⛪️\",\"category\":\"places\",\"description\":\"church\",\"names\":[\"church\"],\"tags\":[]},{\"emoji\":\"🗾\",\"category\":\"places\",\"description\":\"map of Japan\",\"names\":[\"japan\"],\"tags\":[]},{\"emoji\":\"🎑\",\"category\":\"places\",\"description\":\"moon viewing ceremony\",\"names\":[\"rice_scene\"],\"tags\":[]},{\"emoji\":\"🌅\",\"category\":\"places\",\"description\":\"sunrise\",\"names\":[\"sunrise\"],\"tags\":[]},{\"emoji\":\"🌄\",\"category\":\"places\",\"description\":\"sunrise over mountains\",\"names\":[\"sunrise_over_mountains\"],\"tags\":[]},{\"emoji\":\"🌠\",\"category\":\"places\",\"description\":\"shooting star\",\"names\":[\"stars\"],\"tags\":[]},{\"emoji\":\"🎇\",\"category\":\"places\",\"description\":\"sparkler\",\"names\":[\"sparkler\"],\"tags\":[]},{\"emoji\":\"🎆\",\"category\":\"places\",\"description\":\"fireworks\",\"names\":[\"fireworks\"],\"tags\":[\"festival\",\"celebration\"]},{\"emoji\":\"🌇\",\"category\":\"places\",\"description\":\"sunset\",\"names\":[\"city_sunrise\"],\"tags\":[]},{\"emoji\":\"🌆\",\"category\":\"places\",\"description\":\"cityscape at dusk\",\"names\":[\"city_sunset\"],\"tags\":[]},{\"emoji\":\"🌃\",\"category\":\"places\",\"description\":\"night with stars\",\"names\":[\"night_with_stars\"],\"tags\":[]},{\"emoji\":\"🌌\",\"category\":\"places\",\"description\":\"milky way\",\"names\":[\"milky_way\"],\"tags\":[]},{\"emoji\":\"🌉\",\"category\":\"places\",\"description\":\"bridge at night\",\"names\":[\"bridge_at_night\"],\"tags\":[]},{\"emoji\":\"🌁\",\"category\":\"places\",\"description\":\"foggy\",\"names\":[\"foggy\"],\"tags\":[\"karl\"]},{\"emoji\":\"⌚️\",\"category\":\"objects\",\"description\":\"watch\",\"names\":[\"watch\"],\"tags\":[\"time\"]},{\"emoji\":\"📱\",\"category\":\"objects\",\"description\":\"mobile phone\",\"names\":[\"iphone\"],\"tags\":[\"smartphone\",\"mobile\"]},{\"emoji\":\"📲\",\"category\":\"objects\",\"description\":\"mobile phone with arrow\",\"names\":[\"calling\"],\"tags\":[\"call\",\"incoming\"]},{\"emoji\":\"💻\",\"category\":\"objects\",\"description\":\"laptop computer\",\"names\":[\"computer\"],\"tags\":[\"desktop\",\"screen\"]},{\"emoji\":\"💽\",\"category\":\"objects\",\"description\":\"computer disk\",\"names\":[\"minidisc\"],\"tags\":[]},{\"emoji\":\"💾\",\"category\":\"objects\",\"description\":\"floppy disk\",\"names\":[\"floppy_disk\"],\"tags\":[\"save\"]},{\"emoji\":\"💿\",\"category\":\"objects\",\"description\":\"optical disk\",\"names\":[\"cd\"],\"tags\":[]},{\"emoji\":\"📀\",\"category\":\"objects\",\"description\":\"dvd\",\"names\":[\"dvd\"],\"tags\":[]},{\"emoji\":\"📼\",\"category\":\"objects\",\"description\":\"videocassette\",\"names\":[\"vhs\"],\"tags\":[]},{\"emoji\":\"📷\",\"category\":\"objects\",\"description\":\"camera\",\"names\":[\"camera\"],\"tags\":[\"photo\"]},{\"emoji\":\"📹\",\"category\":\"objects\",\"description\":\"video camera\",\"names\":[\"video_camera\"],\"tags\":[]},{\"emoji\":\"🎥\",\"category\":\"objects\",\"description\":\"movie camera\",\"names\":[\"movie_camera\"],\"tags\":[\"film\",\"video\"]},{\"emoji\":\"📞\",\"category\":\"objects\",\"description\":\"telephone receiver\",\"names\":[\"telephone_receiver\"],\"tags\":[\"phone\",\"call\"]},{\"emoji\":\"☎️\",\"category\":\"objects\",\"description\":\"telephone\",\"names\":[\"phone\",\"telephone\"],\"tags\":[]},{\"emoji\":\"📟\",\"category\":\"objects\",\"description\":\"pager\",\"names\":[\"pager\"],\"tags\":[]},{\"emoji\":\"📠\",\"category\":\"objects\",\"description\":\"fax machine\",\"names\":[\"fax\"],\"tags\":[]},{\"emoji\":\"📺\",\"category\":\"objects\",\"description\":\"television\",\"names\":[\"tv\"],\"tags\":[]},{\"emoji\":\"📻\",\"category\":\"objects\",\"description\":\"radio\",\"names\":[\"radio\"],\"tags\":[\"podcast\"]},{\"emoji\":\"⏰\",\"category\":\"objects\",\"description\":\"alarm clock\",\"names\":[\"alarm_clock\"],\"tags\":[\"morning\"]},{\"emoji\":\"⌛️\",\"category\":\"objects\",\"description\":\"hourglass\",\"names\":[\"hourglass\"],\"tags\":[\"time\"]},{\"emoji\":\"⏳\",\"category\":\"objects\",\"description\":\"hourglass with flowing sand\",\"names\":[\"hourglass_flowing_sand\"],\"tags\":[\"time\"]},{\"emoji\":\"📡\",\"category\":\"objects\",\"description\":\"satellite antenna\",\"names\":[\"satellite\"],\"tags\":[\"signal\"]},{\"emoji\":\"🔋\",\"category\":\"objects\",\"description\":\"battery\",\"names\":[\"battery\"],\"tags\":[\"power\"]},{\"emoji\":\"🔌\",\"category\":\"objects\",\"description\":\"electric plug\",\"names\":[\"electric_plug\"],\"tags\":[]},{\"emoji\":\"💡\",\"category\":\"objects\",\"description\":\"light bulb\",\"names\":[\"bulb\"],\"tags\":[\"idea\",\"light\"]},{\"emoji\":\"🔦\",\"category\":\"objects\",\"description\":\"flashlight\",\"names\":[\"flashlight\"],\"tags\":[]},{\"emoji\":\"💸\",\"category\":\"objects\",\"description\":\"money with wings\",\"names\":[\"money_with_wings\"],\"tags\":[\"dollar\"]},{\"emoji\":\"💵\",\"category\":\"objects\",\"description\":\"dollar banknote\",\"names\":[\"dollar\"],\"tags\":[\"money\"]},{\"emoji\":\"💴\",\"category\":\"objects\",\"description\":\"yen banknote\",\"names\":[\"yen\"],\"tags\":[]},{\"emoji\":\"💶\",\"category\":\"objects\",\"description\":\"euro banknote\",\"names\":[\"euro\"],\"tags\":[]},{\"emoji\":\"💷\",\"category\":\"objects\",\"description\":\"pound banknote\",\"names\":[\"pound\"],\"tags\":[]},{\"emoji\":\"💰\",\"category\":\"objects\",\"description\":\"money bag\",\"names\":[\"moneybag\"],\"tags\":[\"dollar\",\"cream\"]},{\"emoji\":\"💳\",\"category\":\"objects\",\"description\":\"credit card\",\"names\":[\"credit_card\"],\"tags\":[\"subscription\"]},{\"emoji\":\"💎\",\"category\":\"objects\",\"description\":\"gem stone\",\"names\":[\"gem\"],\"tags\":[\"diamond\"]},{\"emoji\":\"⚖️\",\"category\":\"objects\",\"description\":\"balance scale\",\"names\":[\"balance_scale\"],\"tags\":[]},{\"emoji\":\"🔧\",\"category\":\"objects\",\"description\":\"wrench\",\"names\":[\"wrench\"],\"tags\":[\"tool\"]},{\"emoji\":\"🔨\",\"category\":\"objects\",\"description\":\"hammer\",\"names\":[\"hammer\"],\"tags\":[\"tool\"]},{\"emoji\":\"🔩\",\"category\":\"objects\",\"description\":\"nut and bolt\",\"names\":[\"nut_and_bolt\"],\"tags\":[]},{\"emoji\":\"⚙️\",\"category\":\"objects\",\"description\":\"gear\",\"names\":[\"gear\"],\"tags\":[]},{\"emoji\":\"⛓\",\"category\":\"objects\",\"description\":\"chains\",\"names\":[\"chains\"],\"tags\":[]},{\"emoji\":\"🔫\",\"category\":\"objects\",\"description\":\"pistol\",\"names\":[\"gun\"],\"tags\":[\"shoot\",\"weapon\"]},{\"emoji\":\"💣\",\"category\":\"objects\",\"description\":\"bomb\",\"names\":[\"bomb\"],\"tags\":[\"boom\"]},{\"emoji\":\"🔪\",\"category\":\"objects\",\"description\":\"kitchen knife\",\"names\":[\"hocho\",\"knife\"],\"tags\":[\"cut\",\"chop\"]},{\"emoji\":\"⚔️\",\"category\":\"objects\",\"description\":\"crossed swords\",\"names\":[\"crossed_swords\"],\"tags\":[]},{\"emoji\":\"🚬\",\"category\":\"objects\",\"description\":\"cigarette\",\"names\":[\"smoking\"],\"tags\":[\"cigarette\"]},{\"emoji\":\"⚰️\",\"category\":\"objects\",\"description\":\"coffin\",\"names\":[\"coffin\"],\"tags\":[\"funeral\"]},{\"emoji\":\"⚱️\",\"category\":\"objects\",\"description\":\"funeral urn\",\"names\":[\"funeral_urn\"],\"tags\":[]},{\"emoji\":\"🔮\",\"category\":\"objects\",\"description\":\"crystal ball\",\"names\":[\"crystal_ball\"],\"tags\":[\"fortune\"]},{\"emoji\":\"💈\",\"category\":\"objects\",\"description\":\"barber pole\",\"names\":[\"barber\"],\"tags\":[]},{\"emoji\":\"⚗️\",\"category\":\"objects\",\"description\":\"alembic\",\"names\":[\"alembic\"],\"tags\":[]},{\"emoji\":\"🔭\",\"category\":\"objects\",\"description\":\"telescope\",\"names\":[\"telescope\"],\"tags\":[]},{\"emoji\":\"🔬\",\"category\":\"objects\",\"description\":\"microscope\",\"names\":[\"microscope\"],\"tags\":[\"science\",\"laboratory\",\"investigate\"]},{\"emoji\":\"💊\",\"category\":\"objects\",\"description\":\"pill\",\"names\":[\"pill\"],\"tags\":[\"health\",\"medicine\"]},{\"emoji\":\"💉\",\"category\":\"objects\",\"description\":\"syringe\",\"names\":[\"syringe\"],\"tags\":[\"health\",\"hospital\",\"needle\"]},{\"emoji\":\"🚽\",\"category\":\"objects\",\"description\":\"toilet\",\"names\":[\"toilet\"],\"tags\":[\"wc\"]},{\"emoji\":\"🚰\",\"category\":\"objects\",\"description\":\"potable water\",\"names\":[\"potable_water\"],\"tags\":[]},{\"emoji\":\"🚿\",\"category\":\"objects\",\"description\":\"shower\",\"names\":[\"shower\"],\"tags\":[\"bath\"]},{\"emoji\":\"🛁\",\"category\":\"objects\",\"description\":\"bathtub\",\"names\":[\"bathtub\"],\"tags\":[]},{\"emoji\":\"🛀\",\"category\":\"objects\",\"description\":\"person taking bath\",\"names\":[\"bath\"],\"tags\":[\"shower\"]},{\"emoji\":\"🔑\",\"category\":\"objects\",\"description\":\"key\",\"names\":[\"key\"],\"tags\":[\"lock\",\"password\"]},{\"emoji\":\"🚪\",\"category\":\"objects\",\"description\":\"door\",\"names\":[\"door\"],\"tags\":[]},{\"emoji\":\"🎁\",\"category\":\"objects\",\"description\":\"wrapped gift\",\"names\":[\"gift\"],\"tags\":[\"present\",\"birthday\",\"christmas\"]},{\"emoji\":\"🎈\",\"category\":\"objects\",\"description\":\"balloon\",\"names\":[\"balloon\"],\"tags\":[\"party\",\"birthday\"]},{\"emoji\":\"🎏\",\"category\":\"objects\",\"description\":\"carp streamer\",\"names\":[\"flags\"],\"tags\":[]},{\"emoji\":\"🎀\",\"category\":\"objects\",\"description\":\"ribbon\",\"names\":[\"ribbon\"],\"tags\":[]},{\"emoji\":\"🎊\",\"category\":\"objects\",\"description\":\"confetti ball\",\"names\":[\"confetti_ball\"],\"tags\":[]},{\"emoji\":\"🎉\",\"category\":\"objects\",\"description\":\"party popper\",\"names\":[\"tada\"],\"tags\":[\"hooray\",\"party\"]},{\"emoji\":\"🎎\",\"category\":\"objects\",\"description\":\"Japanese dolls\",\"names\":[\"dolls\"],\"tags\":[]},{\"emoji\":\"🏮\",\"category\":\"objects\",\"description\":\"red paper lantern\",\"names\":[\"izakaya_lantern\",\"lantern\"],\"tags\":[]},{\"emoji\":\"✉️\",\"category\":\"objects\",\"description\":\"envelope\",\"names\":[\"email\",\"envelope\"],\"tags\":[\"letter\"]},{\"emoji\":\"📩\",\"category\":\"objects\",\"description\":\"envelope with arrow\",\"names\":[\"envelope_with_arrow\"],\"tags\":[]},{\"emoji\":\"📨\",\"category\":\"objects\",\"description\":\"incoming envelope\",\"names\":[\"incoming_envelope\"],\"tags\":[]},{\"emoji\":\"📧\",\"category\":\"objects\",\"description\":\"e-mail\",\"names\":[\"e-mail\"],\"tags\":[]},{\"emoji\":\"💌\",\"category\":\"objects\",\"description\":\"love letter\",\"names\":[\"love_letter\"],\"tags\":[\"email\",\"envelope\"]},{\"emoji\":\"📥\",\"category\":\"objects\",\"description\":\"inbox tray\",\"names\":[\"inbox_tray\"],\"tags\":[]},{\"emoji\":\"📤\",\"category\":\"objects\",\"description\":\"outbox tray\",\"names\":[\"outbox_tray\"],\"tags\":[]},{\"emoji\":\"📦\",\"category\":\"objects\",\"description\":\"package\",\"names\":[\"package\"],\"tags\":[\"shipping\"]},{\"emoji\":\"📪\",\"category\":\"objects\",\"description\":\"closed mailbox with lowered flag\",\"names\":[\"mailbox_closed\"],\"tags\":[]},{\"emoji\":\"📫\",\"category\":\"objects\",\"description\":\"closed mailbox with raised flag\",\"names\":[\"mailbox\"],\"tags\":[]},{\"emoji\":\"📬\",\"category\":\"objects\",\"description\":\"open mailbox with raised flag\",\"names\":[\"mailbox_with_mail\"],\"tags\":[]},{\"emoji\":\"📭\",\"category\":\"objects\",\"description\":\"open mailbox with lowered flag\",\"names\":[\"mailbox_with_no_mail\"],\"tags\":[]},{\"emoji\":\"📮\",\"category\":\"objects\",\"description\":\"postbox\",\"names\":[\"postbox\"],\"tags\":[]},{\"emoji\":\"📯\",\"category\":\"objects\",\"description\":\"postal horn\",\"names\":[\"postal_horn\"],\"tags\":[]},{\"emoji\":\"📜\",\"category\":\"objects\",\"description\":\"scroll\",\"names\":[\"scroll\"],\"tags\":[\"document\"]},{\"emoji\":\"📃\",\"category\":\"objects\",\"description\":\"page with curl\",\"names\":[\"page_with_curl\"],\"tags\":[]},{\"emoji\":\"📄\",\"category\":\"objects\",\"description\":\"page facing up\",\"names\":[\"page_facing_up\"],\"tags\":[\"document\"]},{\"emoji\":\"📑\",\"category\":\"objects\",\"description\":\"bookmark tabs\",\"names\":[\"bookmark_tabs\"],\"tags\":[]},{\"emoji\":\"📊\",\"category\":\"objects\",\"description\":\"bar chart\",\"names\":[\"bar_chart\"],\"tags\":[\"stats\",\"metrics\"]},{\"emoji\":\"📈\",\"category\":\"objects\",\"description\":\"chart increasing\",\"names\":[\"chart_with_upwards_trend\"],\"tags\":[\"graph\",\"metrics\"]},{\"emoji\":\"📉\",\"category\":\"objects\",\"description\":\"chart decreasing\",\"names\":[\"chart_with_downwards_trend\"],\"tags\":[\"graph\",\"metrics\"]},{\"emoji\":\"📆\",\"category\":\"objects\",\"description\":\"tear-off calendar\",\"names\":[\"calendar\"],\"tags\":[\"schedule\"]},{\"emoji\":\"📅\",\"category\":\"objects\",\"description\":\"calendar\",\"names\":[\"date\"],\"tags\":[\"calendar\",\"schedule\"]},{\"emoji\":\"📇\",\"category\":\"objects\",\"description\":\"card index\",\"names\":[\"card_index\"],\"tags\":[]},{\"emoji\":\"📋\",\"category\":\"objects\",\"description\":\"clipboard\",\"names\":[\"clipboard\"],\"tags\":[]},{\"emoji\":\"📁\",\"category\":\"objects\",\"description\":\"file folder\",\"names\":[\"file_folder\"],\"tags\":[\"directory\"]},{\"emoji\":\"📂\",\"category\":\"objects\",\"description\":\"open file folder\",\"names\":[\"open_file_folder\"],\"tags\":[]},{\"emoji\":\"📰\",\"category\":\"objects\",\"description\":\"newspaper\",\"names\":[\"newspaper\"],\"tags\":[\"press\"]},{\"emoji\":\"📓\",\"category\":\"objects\",\"description\":\"notebook\",\"names\":[\"notebook\"],\"tags\":[]},{\"emoji\":\"📔\",\"category\":\"objects\",\"description\":\"notebook with decorative cover\",\"names\":[\"notebook_with_decorative_cover\"],\"tags\":[]},{\"emoji\":\"📒\",\"category\":\"objects\",\"description\":\"ledger\",\"names\":[\"ledger\"],\"tags\":[]},{\"emoji\":\"📕\",\"category\":\"objects\",\"description\":\"closed book\",\"names\":[\"closed_book\"],\"tags\":[]},{\"emoji\":\"📗\",\"category\":\"objects\",\"description\":\"green book\",\"names\":[\"green_book\"],\"tags\":[]},{\"emoji\":\"📘\",\"category\":\"objects\",\"description\":\"blue book\",\"names\":[\"blue_book\"],\"tags\":[]},{\"emoji\":\"📙\",\"category\":\"objects\",\"description\":\"orange book\",\"names\":[\"orange_book\"],\"tags\":[]},{\"emoji\":\"📚\",\"category\":\"objects\",\"description\":\"books\",\"names\":[\"books\"],\"tags\":[\"library\"]},{\"emoji\":\"📖\",\"category\":\"objects\",\"description\":\"open book\",\"names\":[\"book\",\"open_book\"],\"tags\":[]},{\"emoji\":\"🔖\",\"category\":\"objects\",\"description\":\"bookmark\",\"names\":[\"bookmark\"],\"tags\":[]},{\"emoji\":\"🔗\",\"category\":\"objects\",\"description\":\"link\",\"names\":[\"link\"],\"tags\":[]},{\"emoji\":\"📎\",\"category\":\"objects\",\"description\":\"paperclip\",\"names\":[\"paperclip\"],\"tags\":[]},{\"emoji\":\"📐\",\"category\":\"objects\",\"description\":\"triangular ruler\",\"names\":[\"triangular_ruler\"],\"tags\":[]},{\"emoji\":\"📏\",\"category\":\"objects\",\"description\":\"straight ruler\",\"names\":[\"straight_ruler\"],\"tags\":[]},{\"emoji\":\"📌\",\"category\":\"objects\",\"description\":\"pushpin\",\"names\":[\"pushpin\"],\"tags\":[\"location\"]},{\"emoji\":\"📍\",\"category\":\"objects\",\"description\":\"round pushpin\",\"names\":[\"round_pushpin\"],\"tags\":[\"location\"]},{\"emoji\":\"✂️\",\"category\":\"objects\",\"description\":\"scissors\",\"names\":[\"scissors\"],\"tags\":[\"cut\"]},{\"emoji\":\"✒️\",\"category\":\"objects\",\"description\":\"black nib\",\"names\":[\"black_nib\"],\"tags\":[]},{\"emoji\":\"📝\",\"category\":\"objects\",\"description\":\"memo\",\"names\":[\"memo\",\"pencil\"],\"tags\":[\"document\",\"note\"]},{\"emoji\":\"✏️\",\"category\":\"objects\",\"description\":\"pencil\",\"names\":[\"pencil2\"],\"tags\":[]},{\"emoji\":\"🔍\",\"category\":\"objects\",\"description\":\"left-pointing magnifying glass\",\"names\":[\"mag\"],\"tags\":[\"search\",\"zoom\"]},{\"emoji\":\"🔎\",\"category\":\"objects\",\"description\":\"right-pointing magnifying glass\",\"names\":[\"mag_right\"],\"tags\":[]},{\"emoji\":\"🔏\",\"category\":\"objects\",\"description\":\"locked with pen\",\"names\":[\"lock_with_ink_pen\"],\"tags\":[]},{\"emoji\":\"🔐\",\"category\":\"objects\",\"description\":\"locked with key\",\"names\":[\"closed_lock_with_key\"],\"tags\":[\"security\"]},{\"emoji\":\"🔒\",\"category\":\"objects\",\"description\":\"locked\",\"names\":[\"lock\"],\"tags\":[\"security\",\"private\"]},{\"emoji\":\"🔓\",\"category\":\"objects\",\"description\":\"unlocked\",\"names\":[\"unlock\"],\"tags\":[\"security\"]},{\"emoji\":\"❤️\",\"category\":\"symbols\",\"description\":\"red heart\",\"names\":[\"heart\"],\"tags\":[\"love\"]},{\"emoji\":\"💛\",\"category\":\"symbols\",\"description\":\"yellow heart\",\"names\":[\"yellow_heart\"],\"tags\":[]},{\"emoji\":\"💚\",\"category\":\"symbols\",\"description\":\"green heart\",\"names\":[\"green_heart\"],\"tags\":[]},{\"emoji\":\"💙\",\"category\":\"symbols\",\"description\":\"blue heart\",\"names\":[\"blue_heart\"],\"tags\":[]},{\"emoji\":\"💜\",\"category\":\"symbols\",\"description\":\"purple heart\",\"names\":[\"purple_heart\"],\"tags\":[]},{\"emoji\":\"💔\",\"category\":\"symbols\",\"description\":\"broken heart\",\"names\":[\"broken_heart\"],\"tags\":[]},{\"emoji\":\"❣️\",\"category\":\"symbols\",\"description\":\"heavy heart exclamation\",\"names\":[\"heavy_heart_exclamation\"],\"tags\":[]},{\"emoji\":\"💕\",\"category\":\"symbols\",\"description\":\"two hearts\",\"names\":[\"two_hearts\"],\"tags\":[]},{\"emoji\":\"💞\",\"category\":\"symbols\",\"description\":\"revolving hearts\",\"names\":[\"revolving_hearts\"],\"tags\":[]},{\"emoji\":\"💓\",\"category\":\"symbols\",\"description\":\"beating heart\",\"names\":[\"heartbeat\"],\"tags\":[]},{\"emoji\":\"💗\",\"category\":\"symbols\",\"description\":\"growing heart\",\"names\":[\"heartpulse\"],\"tags\":[]},{\"emoji\":\"💖\",\"category\":\"symbols\",\"description\":\"sparkling heart\",\"names\":[\"sparkling_heart\"],\"tags\":[]},{\"emoji\":\"💘\",\"category\":\"symbols\",\"description\":\"heart with arrow\",\"names\":[\"cupid\"],\"tags\":[\"love\",\"heart\"]},{\"emoji\":\"💝\",\"category\":\"symbols\",\"description\":\"heart with ribbon\",\"names\":[\"gift_heart\"],\"tags\":[\"chocolates\"]},{\"emoji\":\"💟\",\"category\":\"symbols\",\"description\":\"heart decoration\",\"names\":[\"heart_decoration\"],\"tags\":[]},{\"emoji\":\"☮️\",\"category\":\"symbols\",\"description\":\"peace symbol\",\"names\":[\"peace_symbol\"],\"tags\":[]},{\"emoji\":\"✝️\",\"category\":\"symbols\",\"description\":\"latin cross\",\"names\":[\"latin_cross\"],\"tags\":[]},{\"emoji\":\"☪️\",\"category\":\"symbols\",\"description\":\"star and crescent\",\"names\":[\"star_and_crescent\"],\"tags\":[]},{\"emoji\":\"☸️\",\"category\":\"symbols\",\"description\":\"wheel of dharma\",\"names\":[\"wheel_of_dharma\"],\"tags\":[]},{\"emoji\":\"✡️\",\"category\":\"symbols\",\"description\":\"star of David\",\"names\":[\"star_of_david\"],\"tags\":[]},{\"emoji\":\"🔯\",\"category\":\"symbols\",\"description\":\"dotted six-pointed star\",\"names\":[\"six_pointed_star\"],\"tags\":[]},{\"emoji\":\"☯️\",\"category\":\"symbols\",\"description\":\"yin yang\",\"names\":[\"yin_yang\"],\"tags\":[]},{\"emoji\":\"☦️\",\"category\":\"symbols\",\"description\":\"orthodox cross\",\"names\":[\"orthodox_cross\"],\"tags\":[]},{\"emoji\":\"⛎\",\"category\":\"symbols\",\"description\":\"Ophiuchus\",\"names\":[\"ophiuchus\"],\"tags\":[]},{\"emoji\":\"♈️\",\"category\":\"symbols\",\"description\":\"Aries\",\"names\":[\"aries\"],\"tags\":[]},{\"emoji\":\"♉️\",\"category\":\"symbols\",\"description\":\"Taurus\",\"names\":[\"taurus\"],\"tags\":[]},{\"emoji\":\"♊️\",\"category\":\"symbols\",\"description\":\"Gemini\",\"names\":[\"gemini\"],\"tags\":[]},{\"emoji\":\"♋️\",\"category\":\"symbols\",\"description\":\"Cancer\",\"names\":[\"cancer\"],\"tags\":[]},{\"emoji\":\"♌️\",\"category\":\"symbols\",\"description\":\"Leo\",\"names\":[\"leo\"],\"tags\":[]},{\"emoji\":\"♍️\",\"category\":\"symbols\",\"description\":\"Virgo\",\"names\":[\"virgo\"],\"tags\":[]},{\"emoji\":\"♎️\",\"category\":\"symbols\",\"description\":\"Libra\",\"names\":[\"libra\"],\"tags\":[]},{\"emoji\":\"♏️\",\"category\":\"symbols\",\"description\":\"Scorpius\",\"names\":[\"scorpius\"],\"tags\":[]},{\"emoji\":\"♐️\",\"category\":\"symbols\",\"description\":\"Sagittarius\",\"names\":[\"sagittarius\"],\"tags\":[]},{\"emoji\":\"♑️\",\"category\":\"symbols\",\"description\":\"Capricorn\",\"names\":[\"capricorn\"],\"tags\":[]},{\"emoji\":\"♒️\",\"category\":\"symbols\",\"description\":\"Aquarius\",\"names\":[\"aquarius\"],\"tags\":[]},{\"emoji\":\"♓️\",\"category\":\"symbols\",\"description\":\"Pisces\",\"names\":[\"pisces\"],\"tags\":[]},{\"emoji\":\"🆔\",\"category\":\"symbols\",\"description\":\"ID button\",\"names\":[\"id\"],\"tags\":[]},{\"emoji\":\"⚛️\",\"category\":\"symbols\",\"description\":\"atom symbol\",\"names\":[\"atom_symbol\"],\"tags\":[]},{\"emoji\":\"🉑\",\"category\":\"symbols\",\"description\":\"Japanese “acceptable” button\",\"names\":[\"accept\"],\"tags\":[]},{\"emoji\":\"☢️\",\"category\":\"symbols\",\"description\":\"radioactive\",\"names\":[\"radioactive\"],\"tags\":[]},{\"emoji\":\"☣️\",\"category\":\"symbols\",\"description\":\"biohazard\",\"names\":[\"biohazard\"],\"tags\":[]},{\"emoji\":\"📴\",\"category\":\"symbols\",\"description\":\"mobile phone off\",\"names\":[\"mobile_phone_off\"],\"tags\":[\"mute\",\"off\"]},{\"emoji\":\"📳\",\"category\":\"symbols\",\"description\":\"vibration mode\",\"names\":[\"vibration_mode\"],\"tags\":[]},{\"emoji\":\"🈶\",\"category\":\"symbols\",\"description\":\"Japanese “not free of charge” button\",\"names\":[\"u6709\"],\"tags\":[]},{\"emoji\":\"🈚️\",\"category\":\"symbols\",\"description\":\"Japanese “free of charge” button\",\"names\":[\"u7121\"],\"tags\":[]},{\"emoji\":\"🈸\",\"category\":\"symbols\",\"description\":\"Japanese “application” button\",\"names\":[\"u7533\"],\"tags\":[]},{\"emoji\":\"🈺\",\"category\":\"symbols\",\"description\":\"Japanese “open for business” button\",\"names\":[\"u55b6\"],\"tags\":[]},{\"emoji\":\"🈷️\",\"category\":\"symbols\",\"description\":\"Japanese “monthly amount” button\",\"names\":[\"u6708\"],\"tags\":[]},{\"emoji\":\"✴️\",\"category\":\"symbols\",\"description\":\"eight-pointed star\",\"names\":[\"eight_pointed_black_star\"],\"tags\":[]},{\"emoji\":\"🆚\",\"category\":\"symbols\",\"description\":\"VS button\",\"names\":[\"vs\"],\"tags\":[]},{\"emoji\":\"💮\",\"category\":\"symbols\",\"description\":\"white flower\",\"names\":[\"white_flower\"],\"tags\":[]},{\"emoji\":\"🉐\",\"category\":\"symbols\",\"description\":\"Japanese “bargain” button\",\"names\":[\"ideograph_advantage\"],\"tags\":[]},{\"emoji\":\"㊙️\",\"category\":\"symbols\",\"description\":\"Japanese “secret” button\",\"names\":[\"secret\"],\"tags\":[]},{\"emoji\":\"㊗️\",\"category\":\"symbols\",\"description\":\"Japanese “congratulations” button\",\"names\":[\"congratulations\"],\"tags\":[]},{\"emoji\":\"🈴\",\"category\":\"symbols\",\"description\":\"Japanese “passing grade” button\",\"names\":[\"u5408\"],\"tags\":[]},{\"emoji\":\"🈵\",\"category\":\"symbols\",\"description\":\"Japanese “no vacancy” button\",\"names\":[\"u6e80\"],\"tags\":[]},{\"emoji\":\"🈹\",\"category\":\"symbols\",\"description\":\"Japanese “discount” button\",\"names\":[\"u5272\"],\"tags\":[]},{\"emoji\":\"🈲\",\"category\":\"symbols\",\"description\":\"Japanese “prohibited” button\",\"names\":[\"u7981\"],\"tags\":[]},{\"emoji\":\"🅰️\",\"category\":\"symbols\",\"description\":\"A button (blood type)\",\"names\":[\"a\"],\"tags\":[]},{\"emoji\":\"🅱️\",\"category\":\"symbols\",\"description\":\"B button (blood type)\",\"names\":[\"b\"],\"tags\":[]},{\"emoji\":\"🆎\",\"category\":\"symbols\",\"description\":\"AB button (blood type)\",\"names\":[\"ab\"],\"tags\":[]},{\"emoji\":\"🆑\",\"category\":\"symbols\",\"description\":\"CL button\",\"names\":[\"cl\"],\"tags\":[]},{\"emoji\":\"🅾️\",\"category\":\"symbols\",\"description\":\"O button (blood type)\",\"names\":[\"o2\"],\"tags\":[]},{\"emoji\":\"🆘\",\"category\":\"symbols\",\"description\":\"SOS button\",\"names\":[\"sos\"],\"tags\":[\"help\",\"emergency\"]},{\"emoji\":\"❌\",\"category\":\"symbols\",\"description\":\"cross mark\",\"names\":[\"x\"],\"tags\":[]},{\"emoji\":\"⭕️\",\"category\":\"symbols\",\"description\":\"heavy large circle\",\"names\":[\"o\"],\"tags\":[]},{\"emoji\":\"⛔️\",\"category\":\"symbols\",\"description\":\"no entry\",\"names\":[\"no_entry\"],\"tags\":[\"limit\"]},{\"emoji\":\"📛\",\"category\":\"symbols\",\"description\":\"name badge\",\"names\":[\"name_badge\"],\"tags\":[]},{\"emoji\":\"🚫\",\"category\":\"symbols\",\"description\":\"prohibited\",\"names\":[\"no_entry_sign\"],\"tags\":[\"block\",\"forbidden\"]},{\"emoji\":\"💯\",\"category\":\"symbols\",\"description\":\"hundred points\",\"names\":[\"100\"],\"tags\":[\"score\",\"perfect\"]},{\"emoji\":\"💢\",\"category\":\"symbols\",\"description\":\"anger symbol\",\"names\":[\"anger\"],\"tags\":[\"angry\"]},{\"emoji\":\"♨️\",\"category\":\"symbols\",\"description\":\"hot springs\",\"names\":[\"hotsprings\"],\"tags\":[]},{\"emoji\":\"🚷\",\"category\":\"symbols\",\"description\":\"no pedestrians\",\"names\":[\"no_pedestrians\"],\"tags\":[]},{\"emoji\":\"🚯\",\"category\":\"symbols\",\"description\":\"no littering\",\"names\":[\"do_not_litter\"],\"tags\":[]},{\"emoji\":\"🚳\",\"category\":\"symbols\",\"description\":\"no bicycles\",\"names\":[\"no_bicycles\"],\"tags\":[]},{\"emoji\":\"🚱\",\"category\":\"symbols\",\"description\":\"non-potable water\",\"names\":[\"non-potable_water\"],\"tags\":[]},{\"emoji\":\"🔞\",\"category\":\"symbols\",\"description\":\"no one under eighteen\",\"names\":[\"underage\"],\"tags\":[]},{\"emoji\":\"📵\",\"category\":\"symbols\",\"description\":\"no mobile phones\",\"names\":[\"no_mobile_phones\"],\"tags\":[]},{\"emoji\":\"🚭\",\"category\":\"symbols\",\"description\":\"no smoking\",\"names\":[\"no_smoking\"],\"tags\":[]},{\"emoji\":\"❗️\",\"category\":\"symbols\",\"description\":\"exclamation mark\",\"names\":[\"exclamation\",\"heavy_exclamation_mark\"],\"tags\":[\"bang\"]},{\"emoji\":\"❕\",\"category\":\"symbols\",\"description\":\"white exclamation mark\",\"names\":[\"grey_exclamation\"],\"tags\":[]},{\"emoji\":\"❓\",\"category\":\"symbols\",\"description\":\"question mark\",\"names\":[\"question\"],\"tags\":[\"confused\"]},{\"emoji\":\"❔\",\"category\":\"symbols\",\"description\":\"white question mark\",\"names\":[\"grey_question\"],\"tags\":[]},{\"emoji\":\"🔅\",\"category\":\"symbols\",\"description\":\"dim button\",\"names\":[\"low_brightness\"],\"tags\":[]},{\"emoji\":\"🔆\",\"category\":\"symbols\",\"description\":\"bright button\",\"names\":[\"high_brightness\"],\"tags\":[]},{\"emoji\":\"〽️\",\"category\":\"symbols\",\"description\":\"part alternation mark\",\"names\":[\"part_alternation_mark\"],\"tags\":[]},{\"emoji\":\"⚠️\",\"category\":\"symbols\",\"description\":\"warning\",\"names\":[\"warning\"],\"tags\":[\"wip\"]},{\"emoji\":\"🚸\",\"category\":\"symbols\",\"description\":\"children crossing\",\"names\":[\"children_crossing\"],\"tags\":[]},{\"emoji\":\"🔱\",\"category\":\"symbols\",\"description\":\"trident emblem\",\"names\":[\"trident\"],\"tags\":[]},{\"emoji\":\"⚜️\",\"category\":\"symbols\",\"description\":\"fleur-de-lis\",\"names\":[\"fleur_de_lis\"],\"tags\":[]},{\"emoji\":\"🔰\",\"category\":\"symbols\",\"description\":\"Japanese symbol for beginner\",\"names\":[\"beginner\"],\"tags\":[]},{\"emoji\":\"♻️\",\"category\":\"symbols\",\"description\":\"recycling symbol\",\"names\":[\"recycle\"],\"tags\":[\"environment\",\"green\"]},{\"emoji\":\"✅\",\"category\":\"symbols\",\"description\":\"white heavy check mark\",\"names\":[\"white_check_mark\"],\"tags\":[]},{\"emoji\":\"🈯️\",\"category\":\"symbols\",\"description\":\"Japanese “reserved” button\",\"names\":[\"u6307\"],\"tags\":[]},{\"emoji\":\"💹\",\"category\":\"symbols\",\"description\":\"chart increasing with yen\",\"names\":[\"chart\"],\"tags\":[]},{\"emoji\":\"❇️\",\"category\":\"symbols\",\"description\":\"sparkle\",\"names\":[\"sparkle\"],\"tags\":[]},{\"emoji\":\"✳️\",\"category\":\"symbols\",\"description\":\"eight-spoked asterisk\",\"names\":[\"eight_spoked_asterisk\"],\"tags\":[]},{\"emoji\":\"❎\",\"category\":\"symbols\",\"description\":\"cross mark button\",\"names\":[\"negative_squared_cross_mark\"],\"tags\":[]},{\"emoji\":\"🌐\",\"category\":\"symbols\",\"description\":\"globe with meridians\",\"names\":[\"globe_with_meridians\"],\"tags\":[\"world\",\"global\",\"international\"]},{\"emoji\":\"💠\",\"category\":\"symbols\",\"description\":\"diamond with a dot\",\"names\":[\"diamond_shape_with_a_dot_inside\"],\"tags\":[]},{\"emoji\":\"Ⓜ️\",\"category\":\"symbols\",\"description\":\"circled M\",\"names\":[\"m\"],\"tags\":[]},{\"emoji\":\"🌀\",\"category\":\"symbols\",\"description\":\"cyclone\",\"names\":[\"cyclone\"],\"tags\":[\"swirl\"]},{\"emoji\":\"💤\",\"category\":\"symbols\",\"description\":\"zzz\",\"names\":[\"zzz\"],\"tags\":[\"sleeping\"]},{\"emoji\":\"🏧\",\"category\":\"symbols\",\"description\":\"ATM sign\",\"names\":[\"atm\"],\"tags\":[]},{\"emoji\":\"🚾\",\"category\":\"symbols\",\"description\":\"water closet\",\"names\":[\"wc\"],\"tags\":[\"toilet\",\"restroom\"]},{\"emoji\":\"♿️\",\"category\":\"symbols\",\"description\":\"wheelchair symbol\",\"names\":[\"wheelchair\"],\"tags\":[\"accessibility\"]},{\"emoji\":\"🅿️\",\"category\":\"symbols\",\"description\":\"P button\",\"names\":[\"parking\"],\"tags\":[]},{\"emoji\":\"🈳\",\"category\":\"symbols\",\"description\":\"Japanese “vacancy” button\",\"names\":[\"u7a7a\"],\"tags\":[]},{\"emoji\":\"🈂️\",\"category\":\"symbols\",\"description\":\"Japanese “service charge” button\",\"names\":[\"sa\"],\"tags\":[]},{\"emoji\":\"🛂\",\"category\":\"symbols\",\"description\":\"passport control\",\"names\":[\"passport_control\"],\"tags\":[]},{\"emoji\":\"🛃\",\"category\":\"symbols\",\"description\":\"customs\",\"names\":[\"customs\"],\"tags\":[]},{\"emoji\":\"🛄\",\"category\":\"symbols\",\"description\":\"baggage claim\",\"names\":[\"baggage_claim\"],\"tags\":[\"airport\"]},{\"emoji\":\"🛅\",\"category\":\"symbols\",\"description\":\"left luggage\",\"names\":[\"left_luggage\"],\"tags\":[]},{\"emoji\":\"🚹\",\"category\":\"symbols\",\"description\":\"men’s room\",\"names\":[\"mens\"],\"tags\":[]},{\"emoji\":\"🚺\",\"category\":\"symbols\",\"description\":\"women’s room\",\"names\":[\"womens\"],\"tags\":[]},{\"emoji\":\"🚼\",\"category\":\"symbols\",\"description\":\"baby symbol\",\"names\":[\"baby_symbol\"],\"tags\":[]},{\"emoji\":\"🚻\",\"category\":\"symbols\",\"description\":\"restroom\",\"names\":[\"restroom\"],\"tags\":[\"toilet\"]},{\"emoji\":\"🚮\",\"category\":\"symbols\",\"description\":\"litter in bin sign\",\"names\":[\"put_litter_in_its_place\"],\"tags\":[]},{\"emoji\":\"🎦\",\"category\":\"symbols\",\"description\":\"cinema\",\"names\":[\"cinema\"],\"tags\":[\"film\",\"movie\"]},{\"emoji\":\"📶\",\"category\":\"symbols\",\"description\":\"antenna bars\",\"names\":[\"signal_strength\"],\"tags\":[\"wifi\"]},{\"emoji\":\"🈁\",\"category\":\"symbols\",\"description\":\"Japanese “here” button\",\"names\":[\"koko\"],\"tags\":[]},{\"emoji\":\"🔣\",\"category\":\"symbols\",\"description\":\"input symbols\",\"names\":[\"symbols\"],\"tags\":[]},{\"emoji\":\"ℹ️\",\"category\":\"symbols\",\"description\":\"information\",\"names\":[\"information_source\"],\"tags\":[]},{\"emoji\":\"🔤\",\"category\":\"symbols\",\"description\":\"input latin letters\",\"names\":[\"abc\"],\"tags\":[\"alphabet\"]},{\"emoji\":\"🔡\",\"category\":\"symbols\",\"description\":\"input latin lowercase\",\"names\":[\"abcd\"],\"tags\":[]},{\"emoji\":\"🔠\",\"category\":\"symbols\",\"description\":\"input latin uppercase\",\"names\":[\"capital_abcd\"],\"tags\":[\"letters\"]},{\"emoji\":\"🆖\",\"category\":\"symbols\",\"description\":\"NG button\",\"names\":[\"ng\"],\"tags\":[]},{\"emoji\":\"🆗\",\"category\":\"symbols\",\"description\":\"OK button\",\"names\":[\"ok\"],\"tags\":[\"yes\"]},{\"emoji\":\"🆙\",\"category\":\"symbols\",\"description\":\"UP! button\",\"names\":[\"up\"],\"tags\":[]},{\"emoji\":\"🆒\",\"category\":\"symbols\",\"description\":\"COOL button\",\"names\":[\"cool\"],\"tags\":[]},{\"emoji\":\"🆕\",\"category\":\"symbols\",\"description\":\"NEW button\",\"names\":[\"new\"],\"tags\":[\"fresh\"]},{\"emoji\":\"🆓\",\"category\":\"symbols\",\"description\":\"FREE button\",\"names\":[\"free\"],\"tags\":[]},{\"emoji\":\"🔟\",\"category\":\"symbols\",\"description\":\"keycap 10\",\"names\":[\"keycap_ten\"],\"tags\":[]},{\"emoji\":\"🔢\",\"category\":\"symbols\",\"description\":\"input numbers\",\"names\":[\"1234\"],\"tags\":[\"numbers\"]},{\"emoji\":\"▶️\",\"category\":\"symbols\",\"description\":\"play button\",\"names\":[\"arrow_forward\"],\"tags\":[]},{\"emoji\":\"⏩\",\"category\":\"symbols\",\"description\":\"fast-forward button\",\"names\":[\"fast_forward\"],\"tags\":[]},{\"emoji\":\"⏪\",\"category\":\"symbols\",\"description\":\"fast reverse button\",\"names\":[\"rewind\"],\"tags\":[]},{\"emoji\":\"⏫\",\"category\":\"symbols\",\"description\":\"fast up button\",\"names\":[\"arrow_double_up\"],\"tags\":[]},{\"emoji\":\"⏬\",\"category\":\"symbols\",\"description\":\"fast down button\",\"names\":[\"arrow_double_down\"],\"tags\":[]},{\"emoji\":\"◀️\",\"category\":\"symbols\",\"description\":\"reverse button\",\"names\":[\"arrow_backward\"],\"tags\":[]},{\"emoji\":\"🔼\",\"category\":\"symbols\",\"description\":\"up button\",\"names\":[\"arrow_up_small\"],\"tags\":[]},{\"emoji\":\"🔽\",\"category\":\"symbols\",\"description\":\"down button\",\"names\":[\"arrow_down_small\"],\"tags\":[]},{\"emoji\":\"➡️\",\"category\":\"symbols\",\"description\":\"right arrow\",\"names\":[\"arrow_right\"],\"tags\":[]},{\"emoji\":\"⬅️\",\"category\":\"symbols\",\"description\":\"left arrow\",\"names\":[\"arrow_left\"],\"tags\":[]},{\"emoji\":\"⬆️\",\"category\":\"symbols\",\"description\":\"up arrow\",\"names\":[\"arrow_up\"],\"tags\":[]},{\"emoji\":\"⬇️\",\"category\":\"symbols\",\"description\":\"down arrow\",\"names\":[\"arrow_down\"],\"tags\":[]},{\"emoji\":\"↘️\",\"category\":\"symbols\",\"description\":\"down-right arrow\",\"names\":[\"arrow_lower_right\"],\"tags\":[]},{\"emoji\":\"↖️\",\"category\":\"symbols\",\"description\":\"up-left arrow\",\"names\":[\"arrow_upper_left\"],\"tags\":[]},{\"emoji\":\"↪️\",\"category\":\"symbols\",\"description\":\"left arrow curving right\",\"names\":[\"arrow_right_hook\"],\"tags\":[]},{\"emoji\":\"↩️\",\"category\":\"symbols\",\"description\":\"right arrow curving left\",\"names\":[\"leftwards_arrow_with_hook\"],\"tags\":[\"return\"]},{\"emoji\":\"⤴️\",\"category\":\"symbols\",\"description\":\"right arrow curving up\",\"names\":[\"arrow_heading_up\"],\"tags\":[]},{\"emoji\":\"⤵️\",\"category\":\"symbols\",\"description\":\"right arrow curving down\",\"names\":[\"arrow_heading_down\"],\"tags\":[]},{\"emoji\":\"🔀\",\"category\":\"symbols\",\"description\":\"shuffle tracks button\",\"names\":[\"twisted_rightwards_arrows\"],\"tags\":[\"shuffle\"]},{\"emoji\":\"🔁\",\"category\":\"symbols\",\"description\":\"repeat button\",\"names\":[\"repeat\"],\"tags\":[\"loop\"]},{\"emoji\":\"🔂\",\"category\":\"symbols\",\"description\":\"repeat single button\",\"names\":[\"repeat_one\"],\"tags\":[]},{\"emoji\":\"🔄\",\"category\":\"symbols\",\"description\":\"anticlockwise arrows button\",\"names\":[\"arrows_counterclockwise\"],\"tags\":[\"sync\"]},{\"emoji\":\"🔃\",\"category\":\"symbols\",\"description\":\"clockwise vertical arrows\",\"names\":[\"arrows_clockwise\"],\"tags\":[]},{\"emoji\":\"🎵\",\"category\":\"symbols\",\"description\":\"musical note\",\"names\":[\"musical_note\"],\"tags\":[]},{\"emoji\":\"🎶\",\"category\":\"symbols\",\"description\":\"musical notes\",\"names\":[\"notes\"],\"tags\":[\"music\"]},{\"emoji\":\"➕\",\"category\":\"symbols\",\"description\":\"heavy plus sign\",\"names\":[\"heavy_plus_sign\"],\"tags\":[]},{\"emoji\":\"➖\",\"category\":\"symbols\",\"description\":\"heavy minus sign\",\"names\":[\"heavy_minus_sign\"],\"tags\":[]},{\"emoji\":\"➗\",\"category\":\"symbols\",\"description\":\"heavy division sign\",\"names\":[\"heavy_division_sign\"],\"tags\":[]},{\"emoji\":\"✖️\",\"category\":\"symbols\",\"description\":\"heavy multiplication x\",\"names\":[\"heavy_multiplication_x\"],\"tags\":[]},{\"emoji\":\"💲\",\"category\":\"symbols\",\"description\":\"heavy dollar sign\",\"names\":[\"heavy_dollar_sign\"],\"tags\":[]},{\"emoji\":\"💱\",\"category\":\"symbols\",\"description\":\"currency exchange\",\"names\":[\"currency_exchange\"],\"tags\":[]},{\"emoji\":\"〰️\",\"category\":\"symbols\",\"description\":\"wavy dash\",\"names\":[\"wavy_dash\"],\"tags\":[]},{\"emoji\":\"➰\",\"category\":\"symbols\",\"description\":\"curly loop\",\"names\":[\"curly_loop\"],\"tags\":[]},{\"emoji\":\"➿\",\"category\":\"symbols\",\"description\":\"double curly loop\",\"names\":[\"loop\"],\"tags\":[]},{\"emoji\":\"🔚\",\"category\":\"symbols\",\"description\":\"END arrow\",\"names\":[\"end\"],\"tags\":[]},{\"emoji\":\"🔙\",\"category\":\"symbols\",\"description\":\"BACK arrow\",\"names\":[\"back\"],\"tags\":[]},{\"emoji\":\"🔛\",\"category\":\"symbols\",\"description\":\"ON! arrow\",\"names\":[\"on\"],\"tags\":[]},{\"emoji\":\"🔝\",\"category\":\"symbols\",\"description\":\"TOP arrow\",\"names\":[\"top\"],\"tags\":[]},{\"emoji\":\"🔜\",\"category\":\"symbols\",\"description\":\"SOON arrow\",\"names\":[\"soon\"],\"tags\":[]},{\"emoji\":\"✔️\",\"category\":\"symbols\",\"description\":\"heavy check mark\",\"names\":[\"heavy_check_mark\"],\"tags\":[]},{\"emoji\":\"☑️\",\"category\":\"symbols\",\"description\":\"ballot box with check\",\"names\":[\"ballot_box_with_check\"],\"tags\":[]},{\"emoji\":\"🔘\",\"category\":\"symbols\",\"description\":\"radio button\",\"names\":[\"radio_button\"],\"tags\":[]},{\"emoji\":\"⚪️\",\"category\":\"symbols\",\"description\":\"white circle\",\"names\":[\"white_circle\"],\"tags\":[]},{\"emoji\":\"⚫️\",\"category\":\"symbols\",\"description\":\"black circle\",\"names\":[\"black_circle\"],\"tags\":[]},{\"emoji\":\"🔴\",\"category\":\"symbols\",\"description\":\"red circle\",\"names\":[\"red_circle\"],\"tags\":[]},{\"emoji\":\"🔵\",\"category\":\"symbols\",\"description\":\"blue circle\",\"names\":[\"large_blue_circle\"],\"tags\":[]},{\"emoji\":\"🔺\",\"category\":\"symbols\",\"description\":\"red triangle pointed up\",\"names\":[\"small_red_triangle\"],\"tags\":[]},{\"emoji\":\"🔻\",\"category\":\"symbols\",\"description\":\"red triangle pointed down\",\"names\":[\"small_red_triangle_down\"],\"tags\":[]},{\"emoji\":\"🔸\",\"category\":\"symbols\",\"description\":\"small orange diamond\",\"names\":[\"small_orange_diamond\"],\"tags\":[]},{\"emoji\":\"🔹\",\"category\":\"symbols\",\"description\":\"small blue diamond\",\"names\":[\"small_blue_diamond\"],\"tags\":[]},{\"emoji\":\"🔶\",\"category\":\"symbols\",\"description\":\"large orange diamond\",\"names\":[\"large_orange_diamond\"],\"tags\":[]},{\"emoji\":\"🔷\",\"category\":\"symbols\",\"description\":\"large blue diamond\",\"names\":[\"large_blue_diamond\"],\"tags\":[]},{\"emoji\":\"🔳\",\"category\":\"symbols\",\"description\":\"white square button\",\"names\":[\"white_square_button\"],\"tags\":[]},{\"emoji\":\"🔲\",\"category\":\"symbols\",\"description\":\"black square button\",\"names\":[\"black_square_button\"],\"tags\":[]},{\"emoji\":\"▪️\",\"category\":\"symbols\",\"description\":\"black small square\",\"names\":[\"black_small_square\"],\"tags\":[]},{\"emoji\":\"▫️\",\"category\":\"symbols\",\"description\":\"white small square\",\"names\":[\"white_small_square\"],\"tags\":[]},{\"emoji\":\"◾️\",\"category\":\"symbols\",\"description\":\"black medium-small square\",\"names\":[\"black_medium_small_square\"],\"tags\":[]},{\"emoji\":\"◽️\",\"category\":\"symbols\",\"description\":\"white medium-small square\",\"names\":[\"white_medium_small_square\"],\"tags\":[]},{\"emoji\":\"◼️\",\"category\":\"symbols\",\"description\":\"black medium square\",\"names\":[\"black_medium_square\"],\"tags\":[]},{\"emoji\":\"◻️\",\"category\":\"symbols\",\"description\":\"white medium square\",\"names\":[\"white_medium_square\"],\"tags\":[]},{\"emoji\":\"⬛️\",\"category\":\"symbols\",\"description\":\"black large square\",\"names\":[\"black_large_square\"],\"tags\":[]},{\"emoji\":\"⬜️\",\"category\":\"symbols\",\"description\":\"white large square\",\"names\":[\"white_large_square\"],\"tags\":[]},{\"emoji\":\"🔈\",\"category\":\"symbols\",\"description\":\"speaker low volume\",\"names\":[\"speaker\"],\"tags\":[]},{\"emoji\":\"🔇\",\"category\":\"symbols\",\"description\":\"muted speaker\",\"names\":[\"mute\"],\"tags\":[\"sound\",\"volume\"]},{\"emoji\":\"🔉\",\"category\":\"symbols\",\"description\":\"speaker medium volume\",\"names\":[\"sound\"],\"tags\":[\"volume\"]},{\"emoji\":\"🔊\",\"category\":\"symbols\",\"description\":\"speaker high volume\",\"names\":[\"loud_sound\"],\"tags\":[\"volume\"]},{\"emoji\":\"🔔\",\"category\":\"symbols\",\"description\":\"bell\",\"names\":[\"bell\"],\"tags\":[\"sound\",\"notification\"]},{\"emoji\":\"🔕\",\"category\":\"symbols\",\"description\":\"bell with slash\",\"names\":[\"no_bell\"],\"tags\":[\"volume\",\"off\"]},{\"emoji\":\"📣\",\"category\":\"symbols\",\"description\":\"megaphone\",\"names\":[\"mega\"],\"tags\":[]},{\"emoji\":\"📢\",\"category\":\"symbols\",\"description\":\"loudspeaker\",\"names\":[\"loudspeaker\"],\"tags\":[\"announcement\"]},{\"emoji\":\"💬\",\"category\":\"symbols\",\"description\":\"speech balloon\",\"names\":[\"speech_balloon\"],\"tags\":[\"comment\"]},{\"emoji\":\"💭\",\"category\":\"symbols\",\"description\":\"thought balloon\",\"names\":[\"thought_balloon\"],\"tags\":[\"thinking\"]},{\"emoji\":\"🗯\",\"category\":\"symbols\",\"description\":\"right anger bubble\",\"names\":[\"right_anger_bubble\"],\"tags\":[]},{\"emoji\":\"♠️\",\"category\":\"symbols\",\"description\":\"spade suit\",\"names\":[\"spades\"],\"tags\":[]},{\"emoji\":\"♣️\",\"category\":\"symbols\",\"description\":\"club suit\",\"names\":[\"clubs\"],\"tags\":[]},{\"emoji\":\"♥️\",\"category\":\"symbols\",\"description\":\"heart suit\",\"names\":[\"hearts\"],\"tags\":[]},{\"emoji\":\"♦️\",\"category\":\"symbols\",\"description\":\"diamond suit\",\"names\":[\"diamonds\"],\"tags\":[]},{\"emoji\":\"🃏\",\"category\":\"symbols\",\"description\":\"joker\",\"names\":[\"black_joker\"],\"tags\":[]},{\"emoji\":\"🎴\",\"category\":\"symbols\",\"description\":\"flower playing cards\",\"names\":[\"flower_playing_cards\"],\"tags\":[]},{\"emoji\":\"🀄️\",\"category\":\"symbols\",\"description\":\"mahjong red dragon\",\"names\":[\"mahjong\"],\"tags\":[]},{\"emoji\":\"🕐\",\"category\":\"symbols\",\"description\":\"one o’clock\",\"names\":[\"clock1\"],\"tags\":[]},{\"emoji\":\"🕑\",\"category\":\"symbols\",\"description\":\"two o’clock\",\"names\":[\"clock2\"],\"tags\":[]},{\"emoji\":\"🕒\",\"category\":\"symbols\",\"description\":\"three o’clock\",\"names\":[\"clock3\"],\"tags\":[]},{\"emoji\":\"🕓\",\"category\":\"symbols\",\"description\":\"four o’clock\",\"names\":[\"clock4\"],\"tags\":[]},{\"emoji\":\"🕔\",\"category\":\"symbols\",\"description\":\"five o’clock\",\"names\":[\"clock5\"],\"tags\":[]},{\"emoji\":\"🕕\",\"category\":\"symbols\",\"description\":\"six o’clock\",\"names\":[\"clock6\"],\"tags\":[]},{\"emoji\":\"🕖\",\"category\":\"symbols\",\"description\":\"seven o’clock\",\"names\":[\"clock7\"],\"tags\":[]},{\"emoji\":\"🕗\",\"category\":\"symbols\",\"description\":\"eight o’clock\",\"names\":[\"clock8\"],\"tags\":[]},{\"emoji\":\"🕘\",\"category\":\"symbols\",\"description\":\"nine o’clock\",\"names\":[\"clock9\"],\"tags\":[]},{\"emoji\":\"🕙\",\"category\":\"symbols\",\"description\":\"ten o’clock\",\"names\":[\"clock10\"],\"tags\":[]},{\"emoji\":\"🕚\",\"category\":\"symbols\",\"description\":\"eleven o’clock\",\"names\":[\"clock11\"],\"tags\":[]},{\"emoji\":\"🕛\",\"category\":\"symbols\",\"description\":\"twelve o’clock\",\"names\":[\"clock12\"],\"tags\":[]},{\"emoji\":\"🕜\",\"category\":\"symbols\",\"description\":\"one-thirty\",\"names\":[\"clock130\"],\"tags\":[]},{\"emoji\":\"🕝\",\"category\":\"symbols\",\"description\":\"two-thirty\",\"names\":[\"clock230\"],\"tags\":[]},{\"emoji\":\"🕞\",\"category\":\"symbols\",\"description\":\"three-thirty\",\"names\":[\"clock330\"],\"tags\":[]},{\"emoji\":\"🕟\",\"category\":\"symbols\",\"description\":\"four-thirty\",\"names\":[\"clock430\"],\"tags\":[]},{\"emoji\":\"🕠\",\"category\":\"symbols\",\"description\":\"five-thirty\",\"names\":[\"clock530\"],\"tags\":[]},{\"emoji\":\"🕡\",\"category\":\"symbols\",\"description\":\"six-thirty\",\"names\":[\"clock630\"],\"tags\":[]},{\"emoji\":\"🕢\",\"category\":\"symbols\",\"description\":\"seven-thirty\",\"names\":[\"clock730\"],\"tags\":[]},{\"emoji\":\"🕣\",\"category\":\"symbols\",\"description\":\"eight-thirty\",\"names\":[\"clock830\"],\"tags\":[]},{\"emoji\":\"🕤\",\"category\":\"symbols\",\"description\":\"nine-thirty\",\"names\":[\"clock930\"],\"tags\":[]},{\"emoji\":\"🕥\",\"category\":\"symbols\",\"description\":\"ten-thirty\",\"names\":[\"clock1030\"],\"tags\":[]},{\"emoji\":\"🕦\",\"category\":\"symbols\",\"description\":\"eleven-thirty\",\"names\":[\"clock1130\"],\"tags\":[]},{\"emoji\":\"🕧\",\"category\":\"symbols\",\"description\":\"twelve-thirty\",\"names\":[\"clock1230\"],\"tags\":[]}]");/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='';

var mobileRequest = obj.get('RequestFromMobileDevice');

__p+='\r\n'+
((__t=( obj.icons ))==null?'':__t)+
'\r\n<div class="purechat-flyout-container"></div>\r\n<div class="purechat-expanded">\r\n	<div class="purechat-collapsed-outer">\r\n		<div class="purechat-widget-inner purechat-clearfix">\r\n			<div class="purechat-widget-content-wrapper">\r\n				<div class="purechat-widget-header">\r\n					<span class="purechat-widget-room-avatar"></span>\r\n					<div class="purechat-menu purechat-btn-toolbar">\r\n						<button data-trigger="restartChat" class="purechat-btn purechat-btn-mini purechat-btn-restart purechat-display-inline-block" title="Start a new chat">\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-re-queue"></use>\r\n							</svg>\r\n						</button>\r\n						';
 if(!obj.get('isDirectAccess')) { 
__p+='\r\n						<button data-trigger="collapse" class="purechat-btn purechat-btn-mini purechat-actions purechat-btn-collapse purechat-display-inline-block" title="Collapse Widget">\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
''+
((__t=( obj.arrowClass() ))==null?'':__t)+
'"></use>\r\n							</svg>\r\n						</button>\r\n						';
 } 
__p+='\r\n						<button data-trigger="closeChat" class="purechat-btn purechat-btn-mini purechat-btn-close purechat-display-inline-block" title="Close chat session">\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-close"></use>\r\n							</svg>\r\n						</button>\r\n					</div>\r\n					<div class="purechat-widget-title">\r\n						';
 if (obj.isMobile()) { 
__p+='\r\n						<a class="purechat-show-personal-details" href="#">\r\n							<i class="fa fa-chevron-left"></i>\r\n						</a>&nbsp;\r\n						';
 } 
__p+='\r\n						<span class="purechat-widget-title-link"></span>\r\n					</div>\r\n				</div>\r\n				<div class="purechat-content-wrapper purechat-clearfix">\r\n					<div class="purechat-file-overlay purechat-display-none">\r\n						<div class="purechat-file-overlay-instructions">\r\n							Drag Here to Send\r\n						</div>\r\n					</div>\r\n					<div class="purechat-content"></div>\r\n					<div class="purechat-footer">\r\n						';
 if (!obj.get('RemoveBranding')) { 
__p+='\r\n                            ';
 if(obj.isMobile()) { 
__p+='\r\n                                <div class="'+
((__t=( obj.localCssName('purechat-poweredby-container') ))==null?'':__t)+
'">\r\n                                    <div class="'+
((__t=( obj.localCssName('purechat-poweredby') ))==null?'':__t)+
'">\r\n                                        <span class="'+
((__t=( obj.localCssName('purechat-poweredby-text') ))==null?'':__t)+
'">'+
((__t=( obj.getResource('poweredby') ))==null?'':_.escape(__t))+
' </span>\r\n                                        <a class="'+
((__t=( obj.localCssName('purechat-poweredby-link') ))==null?'':__t)+
'" rel="noopener" target="_blank" href="'+
((__t=( obj.poweredByUrl() ))==null?'':__t)+
'">Pure Chat</a>\r\n                                    </div>\r\n                                </div>\r\n                                ';
 if(obj.showPlaySoundCheckbox()) { 
__p+='\r\n                                <button class="purechat-toggle-audio-notifications">\r\n                                    <svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n                                        <use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#'+
((__t=( obj.playSoundOnNewMessage() ? 'pc-svgicon-sound' : 'pc-svgicon-no-sound' ))==null?'':__t)+
'"></use>\r\n                                    </svg>\r\n                                </button>\r\n                                ';
 } 
__p+='\r\n                            ';
 } else { 
__p+='\r\n                                <div class="'+
((__t=( obj.localCssName('purechat-poweredby-container') ))==null?'':__t)+
'">\r\n                                    <div class="'+
((__t=( obj.localCssName('purechat-poweredby') ))==null?'':__t)+
'">\r\n                                        <span class="'+
((__t=( obj.localCssName('purechat-poweredby-text') ))==null?'':__t)+
'">'+
((__t=( obj.getResource('poweredby') ))==null?'':_.escape(__t))+
' </span>\r\n                                        <a class="'+
((__t=( obj.localCssName('purechat-poweredby-link') ))==null?'':__t)+
'" rel="noopener" target="_blank" href="'+
((__t=( obj.poweredByUrl() ))==null?'':__t)+
'">Pure Chat</a>\r\n                                    </div>\r\n                                </div>\r\n                                ';
 if(obj.showPlaySoundCheckbox()) { 
__p+='\r\n                                <button class="purechat-toggle-audio-notifications">\r\n                                    <svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n                                        <use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#'+
((__t=( obj.playSoundOnNewMessage() ? 'pc-svgicon-sound' : 'pc-svgicon-no-sound' ))==null?'':__t)+
'"></use>\r\n                                    </svg>\r\n                                </button>\r\n                                ';
 } 
__p+='\r\n                                <button data-trigger="popOutChat" class="purechat-btn-pop-out purechat-display-inline-block" title="Pop out">\r\n                                    <svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n                                        <use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-expand"></use>\r\n                                    </svg>\r\n                                </button>\r\n                            ';
 } 
__p+='\r\n						';
 } else { 
__p+='\r\n							';
 if(obj.showPlaySoundCheckbox()) { 
__p+='\r\n							<button class="purechat-toggle-audio-notifications">\r\n								<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n									<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#'+
((__t=( obj.playSoundOnNewMessage() ? 'pc-svgicon-sound' : 'pc-svgicon-no-sound' ))==null?'':__t)+
'"></use>\r\n								</svg>\r\n							</button>\r\n							';
 } 
__p+='\r\n							<button data-trigger="popOutChat" class="purechat-btn-pop-out purechat-display-inline-block" title="Pop out">\r\n								<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n									<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-expand"></use>\r\n								</svg>\r\n							</button>\r\n						';
 } 
__p+='\r\n					</div>\r\n				</div>\r\n			</div>\r\n		</div>\r\n	</div>\r\n</div>\r\n<div class="purechat-collapsed '+
((__t=( (obj.get('CollapsedWidgetImageUrl') ? 'purechat-collapsed-image' : 'purechat-collapsed-default') ))==null?'':__t)+
'">\r\n	<div class="purechat-collapsed-image" data-trigger="expand">\r\n		<span class="purechat-missed-message-count purechat-badge purechat-display-none"></span>\r\n	</div>\r\n	<div class="purechat-message-preview purechat-message-note purechat-animate purechat-display-none">\r\n		<div class="purechat-message-preview-text"></div>\r\n	</div>\r\n	<div class="purechat-collapsed-outer purechat-display-none">\r\n		<div class="purechat-widget-inner purechat-clearfix">\r\n			<button data-trigger="collapse" class="purechat-btn purechat-btn-mini purechat-actions purechat-btn-collapse purechat-display-none">\r\n				<span class="purechat-missed-message-count purechat-badge purechat-display-none"></span>\r\n				<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n					<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
''+
((__t=( obj.superMinimizeArrowClass() ))==null?'':__t)+
'"></use>\r\n				</svg>\r\n			</button>\r\n			<div class="purechat-widget-header">\r\n				<div class="purechat-menu purechat-btn-toolbar">\r\n					';
 if (!obj.get('isDirectAccess')) { 
__p+='\r\n						<button type="button" class="purechat-start-chat purechat-btn purechat-btn-mini purechat-display-none" title="Show Chat" data-trigger="expand">\r\n							<span class="purechat-missed-message-count purechat-badge purechat-display-none"></span>\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon '+
((__t=( obj.collapsedIconClass() ))==null?'':__t)+
'">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-chat"></use>\r\n							</svg>\r\n						</button>\r\n						';
 if (obj.get('ShowEmailButton') && !obj.get('IPIsBanned')) { 
__p+='\r\n						<button type="button" class="purechat-btn purechat-btn-mini" title="Show Email" data-trigger="showEmail">\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon '+
((__t=( obj.collapsedIconClass() ))==null?'':__t)+
'">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-email"></use>\r\n							</svg>\r\n						</button>\r\n						';
 } 
__p+='\r\n						';
 if (obj.get('ShowPhoneButton')) { 
__p+='\r\n						<button type="button" class="purechat-btn purechat-btn-mini" title="Show Phone Number" data-trigger="showPhoneNumber">\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon '+
((__t=( obj.collapsedIconClass() ))==null?'':__t)+
'">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-phone"></use>\r\n							</svg>\r\n						</button>\r\n						';
 } 
__p+='\r\n						';
 if (obj.get('ShowTwitterButton')) { 
__p+='\r\n						<button type="button" class="purechat-btn purechat-btn-mini" title="Show Twitter Feed" data-trigger="showTwitter">\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon '+
((__t=( obj.collapsedIconClass() ))==null?'':__t)+
'">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-twitter"></use>\r\n							</svg>\r\n							<div class="purechat-loading purechat-display-none"></div>\r\n						</button>\r\n						';
 } 
__p+='\r\n						';
 if (obj.get('ShowAddressButton')) { 
__p+='\r\n						<button type="button" class="purechat-btn purechat-btn-mini" title="Show Address" data-trigger="showAddress">\r\n							<svg viewBox="0 0 216 216" class="pc-svgicon '+
((__t=( obj.collapsedIconClass() ))==null?'':__t)+
'">\r\n								<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-location"></use>\r\n							</svg>\r\n						</button>\r\n						';
 } 
__p+='\r\n					';
 } 
__p+='\r\n					';
 if(!obj.get('isDirectAccess') && obj.get('ShowMinimizeWidgetButton') && !obj.isMobile()) { 
__p+='\r\n					<button type="button" data-trigger="superMinimize" class="purechat-btn purechat-btn-mini purechat-actions purechat-super-minimize-link-button">\r\n						<svg viewBox="0 0 216 216" class="pc-svgicon '+
((__t=( obj.collapsedIconClass() ))==null?'':__t)+
'">\r\n							<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
''+
((__t=( obj.arrowClass() ))==null?'':__t)+
'"></use>\r\n						</svg>\r\n					</button>\r\n					';
 } 
__p+='\r\n				</div>\r\n				<div class="purechat-widget-title">\r\n					<span class="purechat-widget-title-link" data-trigger="collapsedClick">'+
((__t=( obj.getResource(obj.operatorsAvailable ? 'title_initial' : 'title_unavailable_initial') ))==null?'':_.escape(__t))+
'</span>\r\n				</div>\r\n			</div>\r\n		</div>\r\n	</div>\r\n</div>\r\n<div class="purechat-mobile-overlay purechat-display-none"></div>\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+=''+
((__t=( obj.icons ))==null?'':__t)+
'\r\n<div class="purechat-flyout-container"></div>\r\n<div class="purechat-expanded">\r\n	<div class="purechat-widget-inner purechat-clearfix">\r\n		<div class="purechat-widget-header">\r\n			<span class="purechat-widget-room-avatar"></span>\r\n			<div class="purechat-menu purechat-btn-toolbar">\r\n				<button data-trigger="restartChat" class="purechat-btn purechat-btn-mini purechat-btn-restart" title="Start a new chat">\r\n					<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n						<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-re-queue"></use>\r\n					</svg>\r\n				</button>\r\n				<button data-trigger="closeChat" class="purechat-btn purechat-btn-mini purechat-btn-close" title="Close chat session">\r\n					<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n						<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-close"></use>\r\n					</svg>\r\n				</button>\r\n\r\n			</div>\r\n			<div class="purechat-widget-title">\r\n				<span class="purechat-widget-title-link"></span>\r\n			</div>\r\n		</div>\r\n		<div class="purechat-content-wrapper purechat-clearfix">\r\n			<div class="purechat-file-overlay purechat-display-none">\r\n				<div class="purechat-file-overlay-instructions">\r\n					<img src="' + __webpack_require__(568) + '" alt="Upload File" />\r\n					Drag Here to Send\r\n				</div>\r\n			</div>\r\n			<div class="purechat-content"></div>\r\n			<div class="purechat-footer">\r\n				';
 if(!obj.get('RemoveBranding')) { 
__p+='\r\n				<div class="purechat-poweredby-container">\r\n					<div class="purechat-poweredby">\r\n						<span class="purechat-poweredby-text">'+
((__t=( obj.getResource('poweredby') ))==null?'':_.escape(__t))+
' </span>\r\n						<a class="purechat-poweredby-link" target="_blank" rel="noopener" href="'+
((__t=( obj.poweredByUrl() ))==null?'':__t)+
'">Pure Chat</a>\r\n					</div>\r\n				</div>\r\n				';
 } 
__p+='\r\n				';
 if(obj.showPlaySoundCheckbox()) { 
__p+='\r\n				<button class="purechat-toggle-audio-notifications '+
((__t=( obj.get('RemoveBranding') ? 'purechat-kill-positioning' : '' ))==null?'':__t)+
'">\r\n					<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n						<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#'+
((__t=( obj.playSoundOnNewMessage() ? 'pc-svgicon-sound' : 'pc-svgicon-no-sound' ))==null?'':__t)+
'"></use>\r\n					</svg>\r\n				</button>\r\n				';
 } 
__p+='\r\n			</div>\r\n		</div>\r\n	</div>\r\n</div>\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))module.exports = __webpack_require__.p + "files.65b09576c1d80e1c2896.png";module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+=''+
((__t=( obj.icons ))==null?'':__t)+
'\r\n<div class="purechat-widget-inner purechat-clearfix">\r\n	<div class="purechat-content-wrapper">\r\n		<div class="purechat-content"></div>\r\n		<div class="purechat-poweredby-container"></div>\r\n		<div class="purechat-file-overlay purechat-display-none">\r\n			<div class="purechat-file-overlay-instructions">\r\n				<img src="' + __webpack_require__(568) + '" alt="Upload File" />\r\n				Drag Here to Send\r\n			</div>\r\n		</div>\r\n	</div>\r\n</div>';
}
return __p;
};
/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+=''+
((__t=( obj.icons ))==null?'':__t)+
'\r\n<div class="purechat-flyout-container"></div>\r\n<div class="purechat-window purechat-expanded">\r\n	<div class="purechat-widget-inner purechat-clearfix">\r\n		<div class="purechat-widget-header">\r\n			<span class="purechat-widget-room-avatar"></span>\r\n			<div class="purechat-menu purechat-btn-toolbar">\r\n				<button data-trigger="restartChat" class="purechat-btn purechat-btn-mini purechat-btn-restart" title="Start a new chat">\r\n					<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n						<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-re-queue"></use>\r\n					</svg>\r\n				</button>\r\n				<button data-trigger="closeChat" class="purechat-btn purechat-btn-mini purechat-btn-close" title="Close chat session">\r\n					<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-lg">\r\n						<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-close"></use>\r\n					</svg>\r\n				</button>\r\n			</div>\r\n			<div class="purechat-widget-title">\r\n				';
 if(obj.get('RequestFromMobileDevice') && obj.get('AllowWidgetOnMobile')) { 
__p+='\r\n				<span class="purechat-widget-title-link">PureChat</span>\r\n				';
 }
				else { 
__p+='\r\n				<span class="purechat-widget-title-link">PureChat</span>\r\n				';
 } 
__p+='\r\n			</div>\r\n		</div>\r\n\r\n		<div class="purechat-content-wrapper">\r\n			<div class="purechat-file-overlay purechat-display-none">\r\n				<div class="purechat-file-overlay-instructions">\r\n					<img src="' + __webpack_require__(568) + '" alt="Upload File" />\r\n					Drag Here to Send\r\n				</div>\r\n			</div>\r\n			<div class="purechat-content"></div>\r\n			<div class="purechat-footer">\r\n				';
 if(!obj.get('RemoveBranding')) { 
__p+='\r\n				<div class="purechat-poweredby-container">\r\n					<div class="purechat-poweredby">\r\n						<span class="purechat-poweredby-text">'+
((__t=( obj.getResource('poweredby') ))==null?'':_.escape(__t))+
' </span>\r\n						<a class="purechat-poweredby-link" target="_blank" rel="noopener" href="'+
((__t=( obj.poweredByUrl() ))==null?'':__t)+
'">Pure Chat</a>\r\n					</div>\r\n				</div>\r\n				';
 } 
__p+='\r\n				';
 if(obj.showPlaySoundCheckbox()) { 
__p+='\r\n				<button class="purechat-toggle-audio-notifications">\r\n					<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-sm">\r\n						<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#'+
((__t=( obj.playSoundOnNewMessage() ? 'pc-svgicon-sound' : 'pc-svgicon-no-sound' ))==null?'':__t)+
'"></use>\r\n					</svg>\r\n				</button>\r\n				';
 } 
__p+='\r\n			</div>\r\n		</div>\r\n	</div>\r\n</div>\r\n<div class="purechat-widget purechat-collapsed">\r\n	';
 if(obj.get('CollapsedWidgetImageUrl')){ 
__p+='\r\n	<img src="'+
((__t=( obj.get('CollapsedWidgetImageUrl') ))==null?'':__t)+
'" data-trigger="expand"/>\r\n	';
 } else { 
__p+='\r\n	<div class="purechat-widget-inner purechat-clearfix">\r\n		<div class="purechat-widget-header">\r\n			<div class="purechat-menu purechat-btn-toolbar">\r\n				<button data-trigger="expand" class="purechat-btn purechat-btn-mini purechat-actions purechat-btn-expand" title="Expand Widget">\r\n					<i class="pc-icon-plus">+</i>\r\n				</button>\r\n				<button data-trigger="collapse" class="purechat-btn purechat-btn-mini purechat-actions purechat-btn-collapse" title="Collapse Widget">\r\n					<i class="pc-icon-minus">-</i>\r\n				</button>\r\n			</div>\r\n			<div class="purechat-widget-title">\r\n				<span class="purechat-widget-title-link">PureChat</span>\r\n			</div>\r\n		</div>\r\n	</div>\r\n	';
 } 
__p+='\r\n</div>\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<svg id="pc-svgicon" style="position: absolute; height: 0; width: 0">\r\n	<defs>\r\n		<g id="pc-svgicon-download">\r\n			<path d="M198.4,32.3h-62v14.2h56.3v112.9H23.3V46.5h61.1V32.3H17.6c-4.7,0-8.5,3.8-8.5,8.5v124.3\r\n				c0,4.7,3.8,8.5,8.5,8.5h83.3v17.6H74.5c-3.9,0-7.1,3.2-7.1,7.1s3.2,7.1,7.1,7.1h67.1c3.9,0,7.1-3.2,7.1-7.1s-3.2-7.1-7.1-7.1h-26.4\r\n				v-17.6h83.3c4.7,0,8.5-3.8,8.5-8.5V40.8C206.9,36.1,203.1,32.3,198.4,32.3z" />\r\n			<path d="M141.8,59.3c-1.9,0-3.7,0.7-5.1,2.2l-20.8,21.8V17.6c0-3.9-3.2-7.1-7.1-7.1s-7.1,3.2-7.1,7.1\r\n				v66.3L79.2,61.3c-1.4-1.4-3.2-2.1-5-2.1s-3.6,0.7-5,2.1c-2.8,2.8-2.8,7.3,0,10l34.7,34.7c0,0,0.1,0,0.1,0.1c0,0,0,0,0.1,0.1\r\n				c0.1,0.1,0.2,0.2,0.4,0.3c0.2,0.2,0.4,0.3,0.6,0.5c0,0,0.1,0,0.1,0.1c0.2,0.1,0.4,0.2,0.5,0.3c0.2,0.1,0.4,0.2,0.6,0.3\r\n				c0,0,0.1,0,0.1,0c0.2,0.1,0.4,0.1,0.6,0.2c0.2,0.1,0.4,0.1,0.6,0.2c0,0,0.1,0,0.1,0c0.2,0,0.5,0,0.7,0.1c0.2,0,0.4,0.1,0.7,0\r\n				c0.2,0,0.5,0,0.7-0.1c0.2,0,0.4,0,0.6-0.1c0,0,0.1,0,0.1,0c0.2,0,0.4-0.1,0.6-0.2c0.2-0.1,0.4-0.1,0.6-0.2c0,0,0.1,0,0.1,0\r\n				c0.2-0.1,0.4-0.2,0.6-0.3c0.2-0.1,0.4-0.2,0.5-0.3c0,0,0,0,0.1,0c0.2-0.1,0.3-0.2,0.4-0.4c0.2-0.2,0.4-0.3,0.6-0.5c0,0,0,0,0.1-0.1\r\n				l33-34.7c2.7-2.8,2.6-7.3-0.2-10C145.4,59.9,143.6,59.3,141.8,59.3z" />\r\n		</g>\r\n		<g id="pc-svgicon-photo">\r\n			<path d="M192.8,43.3v131.5H23l0.1-131.5C23.1,43.3,192.8,43.3,192.8,43.3z M16.7,30.6\r\n				c-0.1,0-0.2,0-0.4,0c-0.2,0-0.4,0-0.7,0.1c-0.2,0-0.4,0.1-0.6,0.1c-0.2,0.1-0.4,0.1-0.6,0.2c-0.2,0.1-0.4,0.2-0.6,0.2\r\n				c-0.2,0.1-0.4,0.2-0.5,0.3c-0.2,0.1-0.3,0.2-0.5,0.3c-0.2,0.1-0.3,0.2-0.5,0.4c-0.2,0.1-0.3,0.3-0.5,0.5c-0.1,0.1-0.2,0.2-0.3,0.3\r\n				c0,0.1-0.1,0.1-0.1,0.2c-0.1,0.2-0.2,0.4-0.4,0.6c-0.1,0.2-0.2,0.3-0.3,0.5s-0.1,0.4-0.2,0.6c-0.1,0.2-0.1,0.4-0.2,0.6\r\n				c0,0.2-0.1,0.4-0.1,0.6c0,0.2-0.1,0.5-0.1,0.7c0,0.1,0,0.1,0,0.2v144.1c0,3.5,2.8,6.3,6.3,6.3H199c3.5,0,6.3-2.8,6.3-6.3V37\r\n				c0-3.5-2.8-6.3-6.3-6.3L16.7,30.6z" />\r\n			<path d="M178.9,147.5l-31.8-68c-0.7-1.5-2.1-2.6-3.7-2.8c-1.6-0.3-3.3,0.3-4.4,1.5l-31.2,37.2l-7.4-6.6\r\n				c2-4.2,3-8.8,3-13.5c0-17.6-14.3-32-32-32s-32,14.3-32,32c0,11.7,6.4,22.2,16.3,27.8L40.9,147c-1,1.5-1,3.5-0.1,5.1\r\n				s2.6,2.6,4.4,2.6h129.3c1.7,0,3.3-0.9,4.2-2.3C179.5,150.8,179.6,149,178.9,147.5z M71.2,73.3c12.1,0,22,9.9,22,22\r\n				c0,2.2-0.3,4.3-0.9,6.4l-11-9.8c-1.1-1-2.6-1.4-4.1-1.2c-1.5,0.2-2.8,1.1-3.5,2.3l-13.3,21.5c-6.8-3.8-11.2-11.1-11.2-19.1\r\n				C49.2,83.1,59.1,73.3,71.2,73.3z M54,144.6L79,104l25.7,22.1c2,1.7,5,1.5,6.9-0.4l29.5-35.3l25.4,54.2H54z" />\r\n		</g>\r\n		<g id="pc-svgicon-chat">\r\n			<path d="M194.2,32h-172c-4.7,0-8.2,3.6-8.2,8.2v98.3c0,4.7,3.6,8.2,8.2,8.2h81c11.3,11.3,27,27,32.5,32.5\r\n				c6.6,6.6,16.1,8,16.1-3.3c0-6.1,0-19.5,0-29.1h42.3c4.7,0,8.2-3.6,8.2-8.2V40.2C202.4,35.8,198.5,32,194.2,32z"/>\r\n		</g>\r\n		<g id="pc-svgicon-email">\r\n			<path d="M188.5,39.8c6.9,0,13.7,7.3,13.7,13.7v104.8c0,8.8-6,13.7-13.7,13.7H27.4c-7,0-13.7-4-13.7-13.7\r\n				c0,0-0.2-99.5,0-105c0.2-5.5,7.6-13.4,13.5-13.4L188.5,39.8L188.5,39.8z M40.2,63.7c-3.8-1.8-8.2-0.5-10.2,3.1\r\n				c-1.8,3.8-0.5,8.2,3.1,10.2l71.4,53.7c2.3,1.2,4.9,1.2,7,0l71.8-53.9c3.8-1.8,5-6.5,3.1-10.2c-1.8-3.8-6.5-5-10.2-3.1l-68.2,52\r\n				L40.2,63.7z"/>\r\n		</g>\r\n		<g id="pc-svgicon-phone">\r\n			<path d="M185.7,184.5c9.9-19.3-14.8-43.6-27.1-50.3c-3.5-1.8-7.8-3-11.5-3c-2.2,0-17.5,16.1-17.7,16.1\r\n				c-3.8,0-20.4-14.9-28.8-28.7c-9.7-16.1-21.9-31.2-19.8-35.4c0.4-0.7,3-2.1,4.8-2.9c5.5-2.6,22.4-6.6,22.4-17.3\r\n				c-0.1-18.1-6.3-31.5-19.5-43.9c-5-5-10.9-7.5-16.7-7.5c-2.3,0-4.8,0.4-7,1.4c-4.7,1.5-9.4,4.8-10.5,5.5\r\n				C44,24.6,40.9,31.9,37.9,44.1c-2.6,11-3.7,23.1,0.6,39.7c7,26.8,20.5,56.3,38.3,78.5c19.9,25.1,43.1,32.8,61.6,38.9\r\n				C155,206.5,182.7,190.4,185.7,184.5z"/>\r\n		</g>\r\n		<g id="pc-svgicon-twitter">\r\n			<path d="M199.9,31.5c0,0-13,8.1-25.3,10.1c0,0-19.6-21.8-49.5-7c-8.4,4.1-25.4,20.7-18.2,43.8c0,0-43.8,1.7-82.7-41.8\r\n				c0,0-18.7,29.8,12.5,53c0,0-13.6-1.3-18.2-4.6c0,0-4,26.6,30.7,39.4c0,0-10.4,2.8-16.6,0c0,0,7,26.1,36.4,28.1\r\n				c0,0-20.2,21.6-58.2,17.2c0,0,70.1,44.6,134.3-9.2c0,0,43.8-34.5,40-92.4c0,0,11.7-6.6,19.9-20.4c0,0-6.6,5.9-21.8,5.7\r\n				C183.3,53,196.8,44.8,199.9,31.5z"/>\r\n		</g>\r\n		<g id="pc-svgicon-location">\r\n			<path d="M108,10c-40,0-72.5,32.9-72.5,73.5S108,206,108,206s72.5-81.8,72.5-122.5C180.7,42.9,148.2,10,108,10z\r\n				 M144.5,81.9c0,20.7-16.6,37.7-37.2,37.7s-37.2-16.9-37.2-37.7s16.7-37.7,37.3-37.7C127.9,44.2,144.5,61.1,144.5,81.9z"/>\r\n		</g>\r\n		<g id="pc-svgicon-expand">\r\n			<path d="M199.7,101.4c-4.5,0-8.1,3.6-8.1,8.1v64c0,10.2-8.4,18.7-18.7,18.7H43.2\r\n				c-10.2,0-18.7-8.4-18.7-18.7V42.4c0-10.2,8.4-18.7,18.7-18.7h66c4.5,0,8.1-3.6,8.1-8.1s-3.6-8.1-8.1-8.1h-66c-19.3,0-35,15.7-35,35\r\n				v131.2c0,19.3,15.7,35,35,35h129.7c19.3,0,35-15.7,35-35v-64C207.8,105,204.2,101.4,199.7,101.4z"/>\r\n			<path d="M207.6,15.6c0-0.1-0.1-0.2-0.1-0.3c-0.1-0.5-0.3-1.1-0.5-1.5c0-0.1-0.1-0.1-0.1-0.2\r\n				c-0.6-1.1-1.2-2.2-2.1-3.1c-0.2-0.2-0.4-0.3-0.5-0.4c-0.3-0.3-0.6-0.6-1.1-0.9c-0.2-0.2-0.5-0.3-0.9-0.4c-0.3-0.2-0.6-0.4-1.1-0.5\r\n				c-0.2-0.1-0.5-0.1-0.7-0.2c-0.4-0.1-0.9-0.3-1.1-0.3c-0.2,0-0.5,0-0.7-0.1c-0.4,0-0.9-0.1-1.2-0.1h-47.9c-5.6,0-10.1,4.6-10.1,10.1\r\n				s4.6,10.1,10.1,10.1h23.5L88.3,113c-4,4-4,10.4,0,14.3c1.9,1.9,4.5,3,7.1,3c2.8,0,5.3-1.1,7.1-3l84.9-84.9v21.5\r\n				c0,5.6,4.6,10.1,10.1,10.1c5.6,0,10.1-4.6,10.1-10.1V17.6C207.8,17,207.8,16.2,207.6,15.6z"/>\r\n		</g>\r\n		<g id="pc-svgicon-arrow-down">\r\n			<path d="M9.4,65c4.4-5.4,12.4-6.1,17.6-1.9l80.9,65.9l80.9-65.9c5.4-4.4,13.3-3.6,17.6,1.9c1.9,2.3,2.7,5,2.7,7.9\r\n				c0,3.8-1.6,7.3-4.6,9.8L115.7,155c-2.3,1.9-5.1,2.7-7.9,2.7c-2.7,0-5.7-0.9-7.9-2.7L11.2,82.7C5.9,78.3,5,70.3,9.4,65z"/>\r\n		</g>\r\n		<g id="pc-svgicon-arrow-up">\r\n			<path d="M9.5,150.9c4.4,5.4,12.3,6.1,17.6,1.9L108,86.8l80.8,65.9c5.4,4.4,13.3,3.6,17.6-1.9c1.9-2.3,2.7-5,2.7-7.9\r\n				c0-3.8-1.6-7.3-4.6-9.8l-88.6-72.3c-2.3-1.9-5.1-2.7-7.9-2.7c-2.7,0-5.7,0.9-7.9,2.7l-88.7,72.3C6,137.5,5.1,145.4,9.5,150.9z"/>\r\n		</g>\r\n		<g id="pc-svgicon-no-sound">\r\n			<path d="M207.2,51L17.5,179.4c-1.2,0.9-2.7,1.3-4.3,1.3c-4.3,0-7.7-3.4-7.7-7.7\r\n				c0-2.7,1.3-4.9,3.4-6.3L198.5,38.2c1.2-0.9,2.7-1.3,4.3-1.3c4.3,0,7.7,3.4,7.7,7.7C210.6,47.2,209.3,49.6,207.2,51z M29,85\r\n				c0-8.5,6.9-15.3,15.3-15.3l0,0h50.9l52-42.5v0.1c2.7-2.2,6-3.5,9.6-3.5c8,0,14.6,6.1,15.2,13.9L29,134.3V85L29,85z M172.2,120.8\r\n				v15.3v15.3V177c0,8.5-6.9,15.3-15.3,15.3c-3.4,0-6.5-1.1-9-3l0,0l-52.2-38h-10l86.5-58.5L172.2,120.8L172.2,120.8z"/>\r\n		</g>\r\n		<g id="pc-svgicon-sound">\r\n			<path d="M124,63.1L124,63.1c-1.1-1-2.6-1.6-4.3-1.6c-3.6,0-6.6,2.9-6.6,6.6c0,1.9,0.8,3.5,2,4.7\r\n				c7.6,9.7,12.2,22,12.2,35.3c0,13-4.5,25.1-11.7,34.7c-0.9,0.7-1.4,1.5-1.9,2.6c-1.3,3.3,0.3,7.1,3.7,8.5c2.2,0.9,4.6,0.4,6.2-0.9\r\n				l0.1,0.1c0.2-0.2,0.3-0.5,0.5-0.8c0.4-0.4,0.8-0.9,1-1.3c9.2-11.9,14.7-26.7,14.7-43C140,90.9,134.1,75.4,124,63.1z"/>\r\n			<path d="M173.8,13.2L173.8,13.2L173.8,13.2c-1.1-1-2.7-1.6-4.3-1.6c-3.6,0-6.6,2.9-6.6,6.6\r\n				c0,2.3,1.1,4.2,2.8,5.4c19.8,22.6,31.9,52.1,31.9,84.5c0,32.8-12.5,62.9-32.7,85.6l-0.1,0.1c-0.1,0.1-0.1,0.2-0.2,0.3l0,0\r\n				c-0.4,0.5-0.8,1-1,1.6c-1.3,3.3,0.3,7.1,3.7,8.5c3.2,1.2,6.8-0.2,8.2-3.2c21.8-24.7,34.9-57.3,34.9-92.8\r\n				C210.5,71.4,196.6,38.2,173.8,13.2z"/>\r\n			<path d="M149.2,38.5L149.2,38.5c-1.1-1-2.6-1.6-4.3-1.6c-3.6,0-6.6,2.9-6.6,6.6c0,1.9,0.9,3.6,2.2,4.8\r\n				c13.7,16.2,22,37,22,59.9c0,23.3-8.7,44.7-22.9,60.9l0,0c-0.3,0.4-0.7,0.9-0.9,1.3c-1.3,3.3,0.3,7.1,3.7,8.5\r\n				c3.2,1.2,6.7-0.2,8.2-3.1c15.3-18.4,24.5-41.9,24.5-67.7C175.2,81.4,165.4,57,149.2,38.5z"/>\r\n			<path d="M85.7,53.5c-2.3,0-4.4,0.9-6,2.2l0,0L47,82.3H15l0,0c-5.2,0-9.6,4.4-9.6,9.6v32\r\n				c0,5.3,4.4,9.6,9.6,9.6h32.1l32.8,23.9l0,0c1.5,1.1,3.5,1.9,5.6,1.9c5.3,0,9.6-4.4,9.6-9.6V63.2C95.2,57.9,90.9,53.5,85.7,53.5z"/>\r\n		</g>\r\n		<g id="pc-svgicon-sad-face">\r\n				<path d="M61.7,144c-2.1,2.1-2.4,5.4-0.9,7.2c1.6,1.7,4.3,1.5,6.1-0.2c23.5-23.2,58.6-23.2,82.2,0\r\n					c1.9,1.9,4.6,2,6.1,0.2c1.6-1.7,1.3-5.1-0.9-7.2C127.8,117.7,88.2,117.7,61.7,144z"/>\r\n				<circle cx="146.9" cy="91.1" r="11.4"/>\r\n				<circle cx="69.1" cy="91.1" r="11.4"/>\r\n				<path d="M108,9.9C53.9,9.9,9.9,54,9.9,108s44,98.1,98.1,98.1s98.1-44,98.1-98.1S162.1,9.9,108,9.9z\r\n					 M108,193.6c-47.2,0-85.5-38.4-85.5-85.5S60.8,22.5,108,22.5s85.5,38.4,85.5,85.5S155.2,193.6,108,193.6z"/>\r\n		</g>\r\n		<g id="pc-svgicon-happy-face">\r\n			<path d="M149.1,125.8c-23.5,23.2-58.6,23.2-82.2,0c-1.9-1.9-4.6-2-6.1-0.2c-1.6,1.7-1.3,5.1,0.9,7.2\r\n				c26.6,26.3,66.2,26.3,92.7,0c2.1-2.1,2.4-5.4,0.9-7.2C153.7,123.8,150.9,123.9,149.1,125.8z"/>\r\n			<circle cx="146.9" cy="91.1" r="11.4"/>\r\n			<circle cx="69.1" cy="91.1" r="11.4"/>\r\n			<path d="M108,9.9C53.9,9.9,9.9,54,9.9,108s44,98.1,98.1,98.1s98.1-44,98.1-98.1S162.1,9.9,108,9.9z\r\n				 M108,193.6c-47.2,0-85.5-38.4-85.5-85.5S60.8,22.5,108,22.5s85.5,38.4,85.5,85.5S155.2,193.6,108,193.6z"/>\r\n		</g>\r\n		<g id="pc-svgicon-re-queue">\r\n			<path d="M148.2,71c0,5.1,4.1,9.3,9.3,9.3h40.2c5.1,0,9.3-4.1,9.3-9.3V33.9c0-5.1-4.1-9.3-9.3-9.3\r\n				c-5.1,0-9.3,4.1-9.3,9.3v16.7c-17.9-25.1-47.2-41.4-80.3-41.4C53.5,9.2,9.3,53.4,9.3,108s44.2,98.8,98.8,98.8S207,162.6,207,108\r\n				c0-5.1-4.1-9.3-9.3-9.3c-5.1,0-9.3,4.1-9.3,9.3c0,44.4-36,80.3-80.3,80.3s-80.3-36-80.3-80.3s36-80.3,80.3-80.3\r\n				c27.1,0,51,13.4,65.6,34h-16.1C152.4,61.7,148.2,65.8,148.2,71z"/>\r\n		</g>\r\n		<g id="pc-svgicon-close">\r\n			<path d="M187.5,204.7c-4.5,0-8.7-1.6-12.2-5.1L108,132.6l-67.1,67.1c-6.8,6.8-17.8,6.8-24.6,0\r\n				c-6.8-6.8-6.8-17.8,0-24.6L83.4,108L16.3,40.9c-6.8-6.8-6.8-17.8,0-24.6s17.8-6.8,24.6,0L108,83.4l67.1-67.1\r\n				c6.8-6.8,17.8-6.8,24.6,0c6.8,6.8,6.8,17.8,0,24.6L132.6,108l67.1,67.1c6.8,6.8,6.8,17.8,0,24.6\r\n				C196.4,203.2,191.9,204.7,187.5,204.7z"/>\r\n		</g>\r\n		<g id="pc-svgicon-close-filled">\r\n			<path d="m184.37 31.632c42.177 42.177 42.177 110.56 0 152.74-42.177 42.177-110.56 42.177-152.74 0-42.177-42.177-42.177-110.56 0-152.74 42.177-42.177 110.56-42.177 152.74 0zm-49.643 117.86c4.0581 4.0582 10.662 4.059 14.721 8e-4 4.059-4.059 4.059-10.662 8e-4 -14.721l-26.62-26.62 26.129-26.129c4.0582-4.0582 4.0574-10.662-8e-4 -14.721-4.0582-4.0582-10.662-4.0582-14.72 0l-26.128 26.128-26.618-26.618c-4.0582-4.0582-10.662-4.0574-14.721 8e-4 -4.0589 4.0589-4.0589 10.662-7.36e-4 14.721l26.618 26.618-27.109 27.109c-4.0582 4.0582-4.0582 10.662 0 14.72 4.0589 4.059 10.662 4.059 14.721 7.9e-4l27.109-27.109z"/>\r\n		</g>\r\n		<g id="pc-svgicon-play">\r\n			<path d="M28.2,48.5v121c0,17.3,11.2,24.5,26.9,17.2l128.6-60c15.1-7.1,15.4-16.1,0.6-24L53.9,33.1\r\n				C38.7,25,28.2,31.3,28.2,48.5z M14.8,48.5c0-27.4,21.3-40.2,45.5-27.3l130.4,69.6c24.5,13.1,23.9,36.3-1.3,48l-128.6,60\r\n				c-24.6,11.5-46.1-2.2-46.1-29.4V48.5z"/>\r\n		</g>\r\n		<g id="pc-svgicon-paperclip">\r\n			<path d="M171.383,97.691l-67.553,67.464c-13.107,13.051-34.429,13.051-47.529,0c-13.1-13.051-13.107-34.298,0-47.356l71.438-70.88\r\n				c7.864-7.834,20.656-7.834,28.52,0c7.857,7.835,7.864,20.572,0,28.406l-57.182,56.677c-2.621,2.612-6.883,2.612-9.505,0\r\n				c-2.621-2.612-2.621-6.857,0-9.469l47.677-47.208c0,0,4.724-4.765,0-9.469c-4.724-4.703-9.511,0-9.511,0l-47.677,47.202\r\n				c-7.877,7.848-7.871,20.578,0,28.419c7.871,7.841,20.642,7.841,28.513,0L165.756,84.8c6.567-6.542,9.841-15.107,9.841-23.679\r\n				c0-18.542-15.096-33.475-33.609-33.475c-8.604,0-17.201,3.268-23.768,9.81L46.79,108.323c-9.182,9.161-13.78,21.154-13.78,33.153\r\n				c0,25.868,21.04,46.874,47.052,46.874c12.045,0,24.084-4.58,33.272-13.728l67.553-67.464c0,0,4.79-4.646-0.054-9.469\r\n				c-4.84-4.822-9.453,0-9.453,0L171.383,97.691z"/>\r\n		</g>\r\n		<g id="pc-svgicon-notification">\r\n			<path d="m108.72 0.062542c-59.55 0-108 48.45-108 108 0 59.55 48.45 108 108 108 59.55 0 108-48.45 108-108 0-59.55-48.45-108-108-108zm0 201.26c-51.425 0-93.259-41.834-93.259-93.259 0-51.425 41.834-93.259 93.259-93.259 51.425 0 93.259 41.834 93.259 93.259 0 51.425-41.834 93.259-93.259 93.259z"/>\r\n			<path d="m98.6 154.95c0-5.951 4.132-10.247 9.753-10.247 5.951 0 9.753 4.297 9.753 10.247 0 5.786-3.802 10.251-9.753 10.251-5.786 0-9.753-4.465-9.753-10.251zm4.132-23.638-2.313-79.352h15.868l-2.313 79.352z"/>\r\n		</g>\r\n\r\n		<!-- message tail shadow -->\r\n		<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="pc-filter-tails">\r\n			<feOffset dx="1" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>\r\n			<feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>\r\n			<feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>\r\n			<feMerge>\r\n				<feMergeNode />\r\n				<feMergeNode in="SourceGraphic" />\r\n			</feMerge>\r\n		</filter>\r\n		<g id="pc-svgicon-tail-left">\r\n			<path fill="#fff" style="filter:url(#pc-filter-tails)" d="M3,3 L3,9 C3,11.0738525 4.44388994,11.5561101 6,10 L13,3 L3,3 Z"></path>\r\n			<path d="M3,3 L3,9 C3,11.0738525 4.44388994,11.5561101 6,10 L13,3 L3,3 Z"></path>\r\n			<rect x="0" y="0" width="17" height="4"></rect>\r\n		</g>\r\n\r\n		<g id="pc-svgicon-tail-right">\r\n			<path style="filter:url(#pc-filter-tails)" d="M13,3 L13,9 C13,11.0738525 11.5561101,11.5561101 10,10 L3,3 L13,3 Z"></path>\r\n			<path d="M13,3 L13,9 C13,11.0738525 11.5561101,11.5561101 10,10 L3,3 L13,3 Z"></path>\r\n			<rect x="0" y="0" width="17" height="4"></rect>\r\n		</g>\r\n\r\n	</defs>\r\n</svg>\r\n';
}
return __p;
};
/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-enterinfo-container">\r\n	<div data-resourcekey="noOperators_email_message">\r\n		';
 if (obj.fromMissed) { 
__p+='\r\n		<p>'+
((__t=( obj.Utils.linkify(_.escape(obj.getResource('emailForm_missed_response'))) ))==null?'':__t)+
'</p>\r\n		';
 } else { 
__p+='\r\n		'+
((__t=( obj.getResource('emailForm_message') ))==null?'':__t)+
'\r\n		';
 } 
__p+='\r\n	</div>\r\n</div>\r\n<form class="purechat-form purechat-email-form" action="">\r\n	';
 if (obj.get('EmailFormAskForFirstName')) { 
__p+='\r\n	<p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterfirstname purechat-display-none">'+
((__t=( obj.getResource('error_enterFirstName') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-firstname-input"\r\n        autocomplete="off"\r\n        name="purechat-firstname-input"\r\n        id="purechat-emailform-firstname-input"\r\n        maxlength="40"\r\n        value="'+
((__t=( obj.InitialVisitorFirstName ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_firstName') + (obj.RequireFirstName ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireFirstName) { 
__p+='required';
 } 
__p+=' />\r\n	';
 } 
__p+='\r\n	';
 if (obj.get('EmailFormAskForLastName')) { 
__p+='\r\n	<p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterlastname purechat-display-none">'+
((__t=( obj.getResource('error_enterLastName') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-lastname-input"\r\n        autocomplete="off"\r\n        name="purechat-lastname-input"\r\n        id="purechat-emailform-lastname-input"\r\n        maxlength="40"\r\n        value="'+
((__t=( obj.InitialVisitorLastName ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_lastName') + (obj.RequireLastName ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireLastName) { 
__p+='required';
 } 
__p+=' />\r\n	';
 } 
__p+='\r\n	<p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enteremail purechat-display-none">'+
((__t=( obj.getResource('error_enterEmail') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="email"\r\n        class="purechat-email-input"\r\n        name="purechat-email-input"\r\n        id="purechat-emailform-email-input"\r\n        maxlength="100"\r\n        value="'+
((__t=( obj.InitialVisitorEmail ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_email') + '*' ))==null?'':_.escape(__t))+
'"\r\n        required />\r\n	';
 if (obj.get('EmailFormAskForPhoneNumber')) { 
__p+='\r\n	<p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterphonenumber purechat-display-none">'+
((__t=( obj.getResource('error_enterPhoneNumber') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-phonenumber-input"\r\n        name="purechat-phonenumber-input"\r\n        id="purechat-emailform-phonenumber-input"\r\n        maxlength="30"\r\n        value="'+
((__t=( obj.InitialVisitorPhoneNumber ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_phonenumber') + (obj.RequirePhoneNumber ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequirePhoneNumber) { 
__p+='required';
 } 
__p+=' />\r\n	';
 } 
__p+='\r\n	';
 if(obj.get('EmailFormAskForCompany')) { 
__p+='\r\n	<p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-entercompany purechat-display-none">'+
((__t=( obj.getResource('error_enterCompany') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-company-input"\r\n        name="purechat-company-input"\r\n        id="purechat-emailform-company-input"\r\n        maxlength="30"\r\n        value="'+
((__t=( obj.InitialVisitorCompany ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_company') + (obj.RequireCompany ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireCompany) { 
__p+='required';
 } 
__p+=' />\r\n	';
 } 
__p+='\r\n	<p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterquestion purechat-display-none">'+
((__t=( obj.getResource('error_enterQuestion') ))==null?'':_.escape(__t))+
'</p>\r\n	<textarea class="purechat-question-input" name="purechat-question-input" id="purechat-emailform-question-input" rows="1" placeholder="'+
((__t=( obj.getResource('placeholder_question') + '*' ))==null?'':_.escape(__t))+
'" required>'+
((__t=( obj.getMessage() ))==null?'':_.escape(__t))+
'</textarea>\r\n	<input type="submit" class="purechat-btn" id="purechat-emailform-name-submit" value="'+
((__t=( obj.getResource('button_sendEmail') ))==null?'':_.escape(__t))+
'" />\r\n	<p class="purechat-email-error purechat-alert purechat-alert-error purechat-init-error purechat-display-none">Unable to send, please try again.</p>\r\n	<p class="purechat-alert purechat-alert-error purechat-init-error general-error purechat-display-none"></p>\r\n</form>\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-enterinfo-container purechat-email-success purechat-card">\r\n	<h2>'+
((__t=( obj.getResource('emailForm_success_message') ))==null?'':__t)+
'</h2>\r\n	';
 if (obj.AskForFirstName) { 
__p+='\r\n	<div class="purechat-label">'+
((__t=( obj.getResource('placeholder_firstName') ))==null?'':_.escape(__t))+
'</div>\r\n	<p>'+
((__t=( obj.FirstName ))==null?'':_.escape(__t))+
'</p>\r\n	';
 } 
__p+='\r\n	';
 if (!obj.AskForFirstName && obj.AskForLastName) { 
__p+='\r\n	<div class="purechat-label">'+
((__t=( obj.getResource('placeholder_lastName') ))==null?'':_.escape(__t))+
'</div>\r\n	<p>'+
((__t=( obj.LastName ))==null?'':_.escape(__t))+
'</p>\r\n	';
 } 
__p+='\r\n	<div class="purechat-label">'+
((__t=( obj.getResource('placeholder_email') ))==null?'':_.escape(__t))+
'</div>\r\n	<p>'+
((__t=( obj.Email ))==null?'':_.escape(__t))+
'</p>\r\n	';
 if (obj.EmailFormAskForCompany) { 
__p+='\r\n	<div class="purechat-label">'+
((__t=( obj.getResource('placeholder_company') ))==null?'':_.escape(__t))+
'</div>\r\n	<p>'+
((__t=( obj.Company ))==null?'':_.escape(__t))+
'</p>\r\n	';
 } 
__p+='\r\n	';
 if (obj.EmailFormAskForPhoneNumber) { 
__p+='\r\n	<div class="purechat-label">'+
((__t=( obj.getResource('placeholder_phonenumber') ))==null?'':_.escape(__t))+
'</div>\r\n	<p>'+
((__t=( obj.PhoneNumber ))==null?'':_.escape(__t))+
'</p>\r\n	';
 } 
__p+='\r\n	<div class="purechat-label">'+
((__t=( obj.getResource('placeholder_question') ))==null?'':_.escape(__t))+
'</div>\r\n	<div>'+
((__t=( obj.Question ))==null?'':_.escape(__t))+
'</div>\r\n</div>\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-card-header">\r\n	<span>tab or ⇅ to navigate</span>\r\n	<span>↵ to choose</span>\r\n	<span>␛ to dismiss</span>\r\n</div>\r\n<div class="purechat-card-body">\r\n	<div class="purechat-filtered-emojis"></div>\r\n</div>\r\n<div class="purechat-card-footer"></div>\r\n';
}
return __p;
};
module.exports = JSON.parse("[{\"regex\":\"(:\\\\)|:-\\\\)|\\\\(happy\\\\))\",\"emoji\":\"🙂\"},{\"regex\":\"(:\\\\(|:-\\\\(|\\\\(sad\\\\))\",\"emoji\":\"😞\"},{\"regex\":\"(:D|:-D|\\\\(grin\\\\))\",\"emoji\":\"😃\"},{\"regex\":\"(:x|:-x|\\\\(sealed\\\\))\",\"emoji\":\"😶\"},{\"regex\":\"(;\\\\)|;-\\\\)|\\\\(wink\\\\))\",\"emoji\":\"😉\"},{\"regex\":\"(\\\\(yawn\\\\))\",\"emoji\":\"😩\"},{\"regex\":\"(\\\\(smirk\\\\))\",\"emoji\":\"😏\"},{\"regex\":\"(\\\\(starstruck\\\\))\",\"emoji\":\"😲\"},{\"regex\":\"(:C|:-C|\\\\(depressed\\\\))\",\"emoji\":\"☹️\"},{\"regex\":\"(8\\\\(|8-\\\\(|\\\\(sadnerd\\\\))\",\"emoji\":\"😞\"},{\"regex\":\"(D:|\\\\(zomg\\\\))\",\"emoji\":\"😦\"},{\"regex\":\"(:\\\\||:-\\\\||\\\\(speechless\\\\))\",\"emoji\":\"😐\"},{\"regex\":\"(:'\\\\(|:'-\\\\(|\\\\(crying\\\\))\",\"emoji\":\"😢\"},{\"regex\":\"(\\\\(relieved\\\\))\",\"emoji\":\"😌\"},{\"regex\":\"(\\\\(satisfied\\\\))\",\"emoji\":\"😊\"},{\"regex\":\"(\\\\(determined\\\\))\",\"emoji\":\"\",\"deprecated\":true},{\"regex\":\"(:p|:-p|\\\\(tongue\\\\))\",\"emoji\":\"😛\"},{\"regex\":\"(:-\\\\/|\\\\(unsure\\\\))\",\"emoji\":\"😕\"},{\"regex\":\"(-_-|\\\\(sleep\\\\))\",\"emoji\":\"😴\"},{\"regex\":\"(8{|8-{|\\\\(disguise\\\\))\",\"emoji\":\"\",\"deprecated\":true},{\"regex\":\"(B\\\\)|B-\\\\)|\\\\(cool\\\\))\",\"emoji\":\"😎\"},{\"regex\":\"(8\\\\)|8-\\\\)|\\\\(nerd\\\\))\",\"emoji\":\"\",\"deprecated\":true},{\"regex\":\"(\\\\(lovestruck\\\\))\",\"emoji\":\"😍\"},{\"regex\":\"\\\\(angry\\\\)\",\"emoji\":\"😠\"},{\"regex\":\"(\\\\(evil\\\\))\",\"emoji\":\"😈\"},{\"regex\":\"(:s|:-s|\\\\(sick\\\\))\",\"emoji\":\"😷\"},{\"regex\":\"(\\\\/_\\\\\\\\|\\\\(embarassed\\\\))\",\"emoji\":\"😰\"},{\"regex\":\"(:{|\\\\(mustache\\\\))\",\"emoji\":\"\",\"deprecated\":true},{\"regex\":\"(:o|:-o|\\\\(surprised\\\\))\",\"emoji\":\"😮\"},{\"regex\":\"(;p|;-p|\\\\(tease\\\\))\",\"emoji\":\"😜\"},{\"regex\":\"\\\\(ninja\\\\)\",\"emoji\":\"\",\"deprecated\":true},{\"regex\":\"\\\\(zombie\\\\)\",\"emoji\":\"\",\"deprecated\":true}]");/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-messages"></div>\r\n<div class="purechat-send-form-container ';
 if (obj.isOperator()) { 
__p+='text-normal';
 } 
__p+='">\r\n	<div class="purechat-user-status"><span>';
 if (!obj.isOperator()) { 
__p+=''+
((__t=( obj.getResource('chat_idleText') ))==null?'':_.escape(__t))+
'';
 } 
__p+='</span></div>\r\n	<div class="purechat-autocomplete purechat-display-none"></div>\r\n	<form class="purechat-send-form" action="">\r\n		';
 if (!obj.isInvisible()) { 
__p+='\r\n			<textarea class="purechat-send-form-message ';
 if (obj.isOperator()) { 
__p+='text-normal';
 } 
__p+='" name="purechat-send-form-message" placeholder="'+
((__t=( obj.getResource('chat_pressEnter') ))==null?'':_.escape(__t))+
'" rows="1"></textarea>\r\n			';
 if (!obj.isOperator()) { 
__p+='\r\n				';
 if (obj.isFileTransferEnabled()) { 
__p+='\r\n					<button type="button" class="purechat-btn-file-transfer">\r\n						<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-md">\r\n							<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-paperclip"></use>\r\n						</svg>\r\n					</button>\r\n					<input type="file" name="purechat-files" class="purechat-file-picker purechat-display-none" />\r\n				';
 } 
__p+='\r\n				';
 if(obj.isMobile()) { 
__p+='\r\n					<button type="submit" class="purechat-btn-send-message">\r\n                        <svg height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg">\r\n                            <path d="m19.354 10.146-6-6c-.195-.195-.512-.195-.707 0s-.195.512 0 .707l5.146 5.146h-16.293c-.276 0-.5.224-.5.5s.224.5.5.5h16.293l-5.146 5.146c-.195.195-.195.512 0 .707.098.098.226.146.354.146s.256-.049.354-.146l6-6c.195-.195.195-.512 0-.707z" />\r\n                        </svg>\r\n					</button>\r\n				';
 } else { 
__p+='\r\n					<button type="button" class="purechat-btn-emoji">\r\n						<svg viewBox="0 0 216 216" class="pc-svgicon pc-svgicon-md">\r\n							<use '+
((__t=( obj.svgHrefAttr() ))==null?'':__t)+
'="'+
((__t=( obj.iconRootUrl() ))==null?'':__t)+
'#pc-svgicon-happy-face"></use>\r\n						</svg>\r\n					</button>\r\n				';
 } 
__p+='\r\n			';
 } 
__p+='\r\n		';
 } 
__p+='\r\n	</form>\r\n</div>\r\n<div class="purechat-confirm-close-modal purechat-display-none">\r\n	<span class="message">Are you sure you want to close the chat?</span>\r\n	<div class="modal-button-bar">\r\n		<button type="button" class="purechat-btn kill-chat">Yes</button>\r\n		<button type="button" class="purechat-btn cancel">No</button>\r\n	</div>\r\n</div>\r\n<div class="purchat-confirm-close-modal-overlay purechat-display-none"></div>\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))module.exports = __webpack_require__.p + "1avatar-operator-skinny.d0b62c7c078feb3f1042.png";/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='';
 if (!obj.EmailForm) { 
__p+='\r\n';
 if (obj.AskForPhoneNumber || obj.AskForFirstName || obj.AskForLastName || obj.AskForCompany || obj.AskForEmail || obj.AskForQuestion) { 
__p+='\r\n<div class="purechat-enterinfo-container">\r\n    <div data-resourcekey="label_initial">'+
((__t=( obj.Utils.linkify(obj.getResource('label_initial')) ))==null?'':__t)+
'</div>\r\n</div>\r\n';
 } 
__p+='\r\n';
 } else { 
__p+='\r\n<div class="purechat-enterinfo-container">\r\n    <div data-resourcekey="emailForm_message">'+
((__t=( obj.getResource('emailForm_message') ))==null?'':__t)+
'</div>\r\n</div>\r\n';
 } 
__p+='\r\n\r\n<form class="purechat-form '+
((__t=( (!obj.EmailForm ? 'purechat-init-form' : 'purechat-email-form')))==null?'':__t)+
'" action="">\r\n\r\n    ';
 if ((obj.EmailForm && obj.EmailFormAskForFirstName) || (!obj.EmailForm && obj.AskForFirstName)) { 
__p+='\r\n    <p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterfirstname purechat-display-none">'+
((__t=( obj.getResource('error_enterFirstName') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-firstname-input" \r\n        autocomplete="off"\r\n        name="purechat-firstname-input"\r\n        id="purechat-firstname-input"\r\n        maxlength="40"\r\n        value="'+
((__t=( obj.InitialVisitorFirstName ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_firstName') + (obj.RequireFirstName ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireFirstName) { 
__p+='required';
 } 
__p+=' />\r\n    ';
 } 
__p+='\r\n    ';
 if ((obj.EmailForm && obj.EmailFormAskForLastName) || (!obj.EmailForm && obj.AskForLastName)) { 
__p+='\r\n    <p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterlastname purechat-display-none">'+
((__t=( obj.getResource('error_enterLastName') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-lastname-input"\r\n        autocomplete="off"\r\n        name="purechat-lastname-input"\r\n        id="purechat-lastname-input"\r\n        maxlength="40"\r\n        value="'+
((__t=( obj.InitialVisitorLastName ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_lastName') + (obj.RequireLastName ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireLastName) { 
__p+='required';
 } 
__p+=' />\r\n    ';
 } 
__p+='\r\n    ';
 if (obj.EmailForm || obj.AskForEmail) { 
__p+='\r\n    <p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enteremail purechat-display-none">'+
((__t=( obj.getResource('error_enterEmail') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="email"\r\n        class="purechat-email-input"\r\n        name="purechat-email-input"\r\n        id="purechat-email-input"\r\n        maxlength="100"\r\n        value="'+
((__t=( obj.InitialVisitorEmail))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_email') + (obj.RequireEmail ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireEmail) { 
__p+='required';
 } 
__p+=' />\r\n    ';
 } 
__p+='\r\n    ';
 if((obj.EmailForm && obj.EmailFormAskForPhoneNumber) || (!obj.EmailForm && obj.AskForPhoneNumber)) { 
__p+='\r\n    <p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterphonenumber purechat-display-none">'+
((__t=( obj.getResource('error_enterPhoneNumber') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-phonenumber-input"\r\n        name="purechat-phonenumber-input"\r\n        id="purechat-phonenumber-input"\r\n        maxlength="30"\r\n        value="'+
((__t=( obj.InitialVisitorPhoneNumber ))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_phonenumber') + (obj.RequirePhoneNumber ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequirePhoneNumber) { 
__p+='required';
 } 
__p+=' />\r\n    ';
 } 
__p+='\r\n    ';
 if ((obj.EmailForm && obj.EmailFormAskForCompany) || (!obj.EmailForm && obj.AskForCompany)) { 
__p+='\r\n    <p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-entercompany purechat-display-none">'+
((__t=( obj.getResource('error_enterCompany') ))==null?'':_.escape(__t))+
'</p>\r\n    <input\r\n        type="text"\r\n        class="purechat-company-input"\r\n        name="purechat-company-input"\r\n        id="purechat-company-input"\r\n        maxlength="100"\r\n        value="'+
((__t=( obj.InitialVisitorCompany))==null?'':_.escape(__t))+
'"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_company') + (obj.RequireCompany ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireCompany) { 
__p+='required';
 } 
__p+=' />\r\n    ';
 } 
__p+='\r\n    ';
 if (obj.EmailForm || obj.AskForQuestion) { 
__p+='\r\n    <p class="purechat-alert purechat-alert-error purechat-init-error purechat-init-error-inline please-enterquestion purechat-display-none">'+
((__t=( obj.getResource('error_enterQuestion') ))==null?'':_.escape(__t))+
'</p>\r\n    <textarea\r\n        class="purechat-question-input"\r\n        name="purechat-question-input"\r\n        id="purechat-question-input"\r\n        rows="1"\r\n        placeholder="'+
((__t=( obj.getResource('placeholder_question') + (obj.RequireQuestion ? '*' : '') ))==null?'':_.escape(__t))+
'"\r\n        ';
 if (obj.RequireQuestion) { 
__p+='required';
 } 
__p+='>'+
((__t=( obj.InitialVisitorQuestion))==null?'':_.escape(__t))+
'</textarea>\r\n    ';
 } 
__p+='\r\n\r\n    ';
 if (!obj.EmailForm) { 
__p+='\r\n    <input type="submit" class="purechat-btn" id="purechat-name-submit" value="'+
((__t=( obj.getResource('button_startChat') ))==null?'':_.escape(__t))+
'">\r\n    ';
 } else { 
__p+='\r\n    <input type="submit" class="purechat-btn" id="purechat-name-submit" value="'+
((__t=( obj.getResource('button_sendEmail') ))==null?'':_.escape(__t))+
'">\r\n    <p class="purechat-email-error purechat-alert purechat-alert-error purechat-init-error purechat-display-none">Unable to send, please try again.</p>\r\n    ';
 } 
__p+='\r\n    <p class="purechat-alert purechat-alert-error purechat-init-error general-error purechat-display-none"></p>\r\n</form>';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))/* WEBPACK VAR INJECTION */(function(_) {module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="purechat-widget-content '+
((__t=( obj.isMobile() ? 'purechat-mobile fake-chat' : '' ))==null?'':__t)+
'" style="">\r\n	<div class="purechat-message-list-view">\r\n		<div class="purechat-message-display-container">\r\n			<div class="purechat-message-display purechat-clearfix">\r\n				<div class="purechat-message-wrapper purechat-clearfix">\r\n					<div data-resourcekey="" class="purechat-message-container purechat-message-left">\r\n						';
 if (obj.isMobile()) { 
__p+='\r\n						<img class="gravitar purechat-operator-gravatar left" height="50" width="50" src="'+
((__t=( obj.personalAvatarUrl() ))==null?'':__t)+
'" alt=""/>\r\n						';
 } 
__p+='\r\n\r\n						<div class="purechat-timestamp">\r\n							<span class="purechat-time">&nbsp;</span>\r\n						</div>\r\n						<div class="purechat-message" style="margin-right: 0;">\r\n							<span class="purechat-message-actual">\r\n								<span class="purechat-new-thought">'+
((__t=( obj.getResource('chat_startedMessage') ))==null?'':_.escape(__t))+
'</span>\r\n							</span>\r\n						</div>\r\n					</div>\r\n				</div>\r\n			</div>\r\n		</div>\r\n		<div class="purechat-send-form-container">\r\n			<div class="purechat-user-status"><span>'+
((__t=( obj.getResource('chat_idleText') ))==null?'':_.escape(__t))+
'</span></div>\r\n			<form class="purechat-send-form purechat-form" action="">\r\n				<textarea class="purechat-send-form-message purechat-question-input" name="purechat-question-input" id="purechat-question-input" placeholder="'+
((__t=( obj.getResource('chat_pressEnter') ))==null?'':_.escape(__t))+
'" rows="1">'+
((__t=(obj.InitialVisitorQuestion))==null?'':__t)+
'</textarea>\r\n				';
 if(obj.isMobile()) { 
__p+='\r\n				<button type="submit" class="button green send-message">\r\n					Send\r\n				</button>\r\n				';
 } 
__p+='\r\n				<p class="purechat-alert purechat-alert-error purechat-init-error general-error purechat-display-none"></p>\r\n			</form>\r\n		</div>\r\n		<div class="purechat-confirm-close-modal purechat-display-none">\r\n			<span class="message">Are you sure you want to close the chat?</span><div class="modal-button-bar">\r\n				<button type="button" class="purechat-btn kill-chat">Yes</button><button type="button" class="purechat-btn cancel">No</button>\r\n			</div>\r\n		</div>\r\n	</div>\r\n</div>\r\n';
}
return __p;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))module.exports = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<p class="purechat-message-note purechat-unitalic">\r\n	Sorry, but it appears that you are using a browser that is incompatible with Pure Chat\'s technology. 😢\r\n</p>\r\n<p class="purechat-message-note purechat-unitalic">\r\n	In order to use Pure Chat\'s live chat capabilities, please upgrade your browser to a newer version, or use one of these recommended alternative browsers:\r\n	<ul>\r\n		<li>\r\n			<a href="https://www.google.com/chrome" target="_blank">\r\n				Google Chrome\r\n			</a>\r\n		</li>\r\n		<li>\r\n			<a href="https://www.mozilla.org/firefox/new" target="_blank">\r\n				Mozilla Firefox\r\n			</a>\r\n		</li>\r\n	</ul>\r\n</p>';
}
return __p;
};

var content = __webpack_require__(779);

if(typeof content === 'string') content = [[module.i, content, '']];

var transform;
var insertInto;



var options = {"attrs":{"id":"pcwidget-styles"},"hmr":true}

options.transform = transform
options.insertInto = undefined;

var update = __webpack_require__(781)(content, options);

if(content.locals) module.exports = content.locals;

if(false) {}exports = module.exports = __webpack_require__(780)(false);
// imports


// module
exports.push([module.i, "#PureChatWidget.purechat .purechat-truncate {\n  display: block !important;\n  white-space: nowrap !important;\n  overflow: hidden !important;\n  text-overflow: ellipsis !important;\n}\n.purechat a,\n.purechat abbr,\n.purechat address,\n.purechat area,\n.purechat article,\n.purechat aside,\n.purechat audio,\n.purechat b,\n.purechat base,\n.purechat bdi,\n.purechat bdo,\n.purechat blockquote,\n.purechat body,\n.purechat br,\n.purechat button,\n.purechat canvas,\n.purechat caption,\n.purechat cite,\n.purechat code,\n.purechat col,\n.purechat colgroup,\n.purechat command,\n.purechat datalist,\n.purechat dd,\n.purechat del,\n.purechat details,\n.purechat dfn,\n.purechat div,\n.purechat dl,\n.purechat dt,\n.purechat em,\n.purechat embed,\n.purechat fieldset,\n.purechat figcaption,\n.purechat figure,\n.purechat footer,\n.purechat form,\n.purechat h1,\n.purechat h2,\n.purechat h3,\n.purechat h4,\n.purechat h5,\n.purechat h6,\n.purechat head,\n.purechat header,\n.purechat hgroup,\n.purechat hr,\n.purechat i,\n.purechat iframe,\n.purechat img,\n.purechat input,\n.purechat ins,\n.purechat kbd,\n.purechat keygen,\n.purechat label,\n.purechat legend,\n.purechat li,\n.purechat link,\n.purechat map,\n.purechat mark,\n.purechat menu,\n.purechat meta,\n.purechat meter,\n.purechat nav,\n.purechat noscript,\n.purechat object,\n.purechat ol,\n.purechat optgroup,\n.purechat option,\n.purechat output,\n.purechat p,\n.purechat param,\n.purechat pre,\n.purechat progress,\n.purechat q,\n.purechat rp,\n.purechat rt,\n.purechat ruby,\n.purechat s,\n.purechat samp,\n.purechat section,\n.purechat select,\n.purechat small,\n.purechat source,\n.purechat span,\n.purechat strong,\n.purechat style,\n.purechat sub,\n.purechat summary,\n.purechat sup,\n.purechat table,\n.purechat tbody,\n.purechat td,\n.purechat textarea,\n.purechat tfoot,\n.purechat th,\n.purechat thead,\n.purechat time,\n.purechat title,\n.purechat tr,\n.purechat track,\n.purechat u,\n.purechat ul,\n.purechat var,\n.purechat video,\n.purechat wbr,\n.purechat a:before,\n.purechat abbr:before,\n.purechat address:before,\n.purechat area:before,\n.purechat article:before,\n.purechat aside:before,\n.purechat audio:before,\n.purechat b:before,\n.purechat base:before,\n.purechat bdi:before,\n.purechat bdo:before,\n.purechat blockquote:before,\n.purechat body:before,\n.purechat br:before,\n.purechat button:before,\n.purechat canvas:before,\n.purechat caption:before,\n.purechat cite:before,\n.purechat code:before,\n.purechat col:before,\n.purechat colgroup:before,\n.purechat command:before,\n.purechat datalist:before,\n.purechat dd:before,\n.purechat del:before,\n.purechat details:before,\n.purechat dfn:before,\n.purechat div:before,\n.purechat dl:before,\n.purechat dt:before,\n.purechat em:before,\n.purechat embed:before,\n.purechat fieldset:before,\n.purechat figcaption:before,\n.purechat figure:before,\n.purechat footer:before,\n.purechat form:before,\n.purechat h1:before,\n.purechat h2:before,\n.purechat h3:before,\n.purechat h4:before,\n.purechat h5:before,\n.purechat h6:before,\n.purechat head:before,\n.purechat header:before,\n.purechat hgroup:before,\n.purechat hr:before,\n.purechat i:before,\n.purechat iframe:before,\n.purechat img:before,\n.purechat input:before,\n.purechat ins:before,\n.purechat kbd:before,\n.purechat keygen:before,\n.purechat label:before,\n.purechat legend:before,\n.purechat li:before,\n.purechat link:before,\n.purechat map:before,\n.purechat mark:before,\n.purechat menu:before,\n.purechat meta:before,\n.purechat meter:before,\n.purechat nav:before,\n.purechat noscript:before,\n.purechat object:before,\n.purechat ol:before,\n.purechat optgroup:before,\n.purechat option:before,\n.purechat output:before,\n.purechat p:before,\n.purechat param:before,\n.purechat pre:before,\n.purechat progress:before,\n.purechat q:before,\n.purechat rp:before,\n.purechat rt:before,\n.purechat ruby:before,\n.purechat s:before,\n.purechat samp:before,\n.purechat section:before,\n.purechat select:before,\n.purechat small:before,\n.purechat source:before,\n.purechat span:before,\n.purechat strong:before,\n.purechat style:before,\n.purechat sub:before,\n.purechat summary:before,\n.purechat sup:before,\n.purechat table:before,\n.purechat tbody:before,\n.purechat td:before,\n.purechat textarea:before,\n.purechat tfoot:before,\n.purechat th:before,\n.purechat thead:before,\n.purechat time:before,\n.purechat title:before,\n.purechat tr:before,\n.purechat track:before,\n.purechat u:before,\n.purechat ul:before,\n.purechat var:before,\n.purechat video:before,\n.purechat wbr:before,\n.purechat a:after,\n.purechat abbr:after,\n.purechat address:after,\n.purechat area:after,\n.purechat article:after,\n.purechat aside:after,\n.purechat audio:after,\n.purechat b:after,\n.purechat base:after,\n.purechat bdi:after,\n.purechat bdo:after,\n.purechat blockquote:after,\n.purechat body:after,\n.purechat br:after,\n.purechat button:after,\n.purechat canvas:after,\n.purechat caption:after,\n.purechat cite:after,\n.purechat code:after,\n.purechat col:after,\n.purechat colgroup:after,\n.purechat command:after,\n.purechat datalist:after,\n.purechat dd:after,\n.purechat del:after,\n.purechat details:after,\n.purechat dfn:after,\n.purechat div:after,\n.purechat dl:after,\n.purechat dt:after,\n.purechat em:after,\n.purechat embed:after,\n.purechat fieldset:after,\n.purechat figcaption:after,\n.purechat figure:after,\n.purechat footer:after,\n.purechat form:after,\n.purechat h1:after,\n.purechat h2:after,\n.purechat h3:after,\n.purechat h4:after,\n.purechat h5:after,\n.purechat h6:after,\n.purechat head:after,\n.purechat header:after,\n.purechat hgroup:after,\n.purechat hr:after,\n.purechat i:after,\n.purechat iframe:after,\n.purechat img:after,\n.purechat input:after,\n.purechat ins:after,\n.purechat kbd:after,\n.purechat keygen:after,\n.purechat label:after,\n.purechat legend:after,\n.purechat li:after,\n.purechat link:after,\n.purechat map:after,\n.purechat mark:after,\n.purechat menu:after,\n.purechat meta:after,\n.purechat meter:after,\n.purechat nav:after,\n.purechat noscript:after,\n.purechat object:after,\n.purechat ol:after,\n.purechat optgroup:after,\n.purechat option:after,\n.purechat output:after,\n.purechat p:after,\n.purechat param:after,\n.purechat pre:after,\n.purechat progress:after,\n.purechat q:after,\n.purechat rp:after,\n.purechat rt:after,\n.purechat ruby:after,\n.purechat s:after,\n.purechat samp:after,\n.purechat section:after,\n.purechat select:after,\n.purechat small:after,\n.purechat source:after,\n.purechat span:after,\n.purechat strong:after,\n.purechat style:after,\n.purechat sub:after,\n.purechat summary:after,\n.purechat sup:after,\n.purechat table:after,\n.purechat tbody:after,\n.purechat td:after,\n.purechat textarea:after,\n.purechat tfoot:after,\n.purechat th:after,\n.purechat thead:after,\n.purechat time:after,\n.purechat title:after,\n.purechat tr:after,\n.purechat track:after,\n.purechat u:after,\n.purechat ul:after,\n.purechat var:after,\n.purechat video:after,\n.purechat wbr:after {\n  alignment-baseline: auto !important;\n  animation-delay: 0s !important;\n  animation-direction: normal !important;\n  animation-duration: 0s !important;\n  animation-fill-mode: none !important;\n  animation-iteration-count: 1 !important;\n  animation-name: none !important;\n  animation-play-state: running !important;\n  animation-timing-function: ease !important;\n  background-attachment: scroll !important;\n  background-blend-mode: normal !important;\n  background-clip: border-box !important;\n  background-color: rgba(0,0,0,0) !important;\n  background-image: none !important;\n  background-origin: padding-box !important;\n  background-position-x: 0% !important;\n  background-position-y: 0% !important;\n  background-repeat-x: no-repeat !important;\n  background-repeat-y: no-repeat !important;\n  border-bottom-color: rgba(0,0,0,0) !important;\n  border-bottom-left-radius: 0px !important;\n  border-bottom-right-radius: 0px !important;\n  border-bottom-style: none !important;\n  border-bottom-width: 0px !important;\n  border-collapse: separate !important;\n  border-left-color: rgba(0,0,0,0) !important;\n  border-left-style: none !important;\n  border-left-width: 0px !important;\n  border-right-color: rgba(0,0,0,0) !important;\n  border-right-style: none !important;\n  border-right-width: 0px !important;\n  border-top-color: rgba(0,0,0,0) !important;\n  border-top-left-radius: 0px !important;\n  border-top-right-radius: 0px !important;\n  border-top-style: none !important;\n  border-top-width: 0px !important;\n  bottom: auto !important;\n  box-shadow: none !important;\n  box-sizing: border-box !important;\n  clear: none !important;\n  color: #3b404c !important;\n  cursor: default !important;\n  display: block !important;\n  fill: #000 !important;\n  fill-opacity: 1 !important;\n  fill-rule: nonzero !important;\n  filter: none !important;\n  flex-basis: auto !important;\n  flex-direction: row !important;\n  flex-grow: 0 !important;\n  flex-shrink: 1 !important;\n  flex-wrap: nowrap !important;\n  float: none !important;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\", \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", sans-serif !important;\n  font-size: 14px !important;\n  font-stretch: normal !important;\n  font-style: normal !important;\n  font-variant-caps: normal !important;\n  font-weight: normal !important;\n  height: auto !important;\n  left: auto !important;\n  letter-spacing: normal !important;\n  line-height: 1.2 !important;\n  margin-bottom: 0px !important;\n  margin-left: 0px !important;\n  margin-right: 0px !important;\n  margin-top: 0px !important;\n  max-height: none !important;\n  max-width: none !important;\n  min-height: 0px !important;\n  min-width: 0px !important;\n  opacity: 1 !important;\n  outline-color: rgba(0,0,0,0) !important;\n  outline-offset: 0px !important;\n  outline-style: none !important;\n  outline-width: 0px !important;\n  overflow-anchor: auto !important;\n  overflow-wrap: normal !important;\n  overflow-x: visible !important;\n  overflow-y: visible !important;\n  padding-bottom: 0px !important;\n  padding-left: 0px !important;\n  padding-right: 0px !important;\n  padding-top: 0px !important;\n  position: static !important;\n  right: auto !important;\n  table-layout: auto !important;\n  text-align: start !important;\n  text-decoration-color: rgba(0,0,0,0) !important;\n  text-decoration-line: none !important;\n  text-decoration-skip: objects !important;\n  text-decoration-style: solid !important;\n  text-indent: 0px !important;\n  text-shadow: none !important;\n  text-transform: none !important;\n  top: auto !important;\n  transform: none !important;\n  -webkit-transition: none !important;\n  transition-delay: 0s !important;\n  transition-duration: 0s !important;\n  transition-property: all !important;\n  transition-timing-function: ease !important;\n  vertical-align: baseline !important;\n  visibility: visible !important;\n  white-space: normal !important;\n  width: auto !important;\n  word-break: normal !important;\n  word-spacing: 0px !important;\n  word-wrap: normal !important;\n  z-index: auto !important;\n  zoom: 1 !important;\n}\n.purechat a:before,\n.purechat abbr:before,\n.purechat address:before,\n.purechat area:before,\n.purechat article:before,\n.purechat aside:before,\n.purechat audio:before,\n.purechat b:before,\n.purechat base:before,\n.purechat bdi:before,\n.purechat bdo:before,\n.purechat blockquote:before,\n.purechat body:before,\n.purechat br:before,\n.purechat button:before,\n.purechat canvas:before,\n.purechat caption:before,\n.purechat cite:before,\n.purechat code:before,\n.purechat col:before,\n.purechat colgroup:before,\n.purechat command:before,\n.purechat datalist:before,\n.purechat dd:before,\n.purechat del:before,\n.purechat details:before,\n.purechat dfn:before,\n.purechat div:before,\n.purechat dl:before,\n.purechat dt:before,\n.purechat em:before,\n.purechat embed:before,\n.purechat fieldset:before,\n.purechat figcaption:before,\n.purechat figure:before,\n.purechat footer:before,\n.purechat form:before,\n.purechat h1:before,\n.purechat h2:before,\n.purechat h3:before,\n.purechat h4:before,\n.purechat h5:before,\n.purechat h6:before,\n.purechat head:before,\n.purechat header:before,\n.purechat hgroup:before,\n.purechat hr:before,\n.purechat i:before,\n.purechat iframe:before,\n.purechat img:before,\n.purechat input:before,\n.purechat ins:before,\n.purechat kbd:before,\n.purechat keygen:before,\n.purechat label:before,\n.purechat legend:before,\n.purechat li:before,\n.purechat link:before,\n.purechat map:before,\n.purechat mark:before,\n.purechat menu:before,\n.purechat meta:before,\n.purechat meter:before,\n.purechat nav:before,\n.purechat noscript:before,\n.purechat object:before,\n.purechat ol:before,\n.purechat optgroup:before,\n.purechat option:before,\n.purechat output:before,\n.purechat p:before,\n.purechat param:before,\n.purechat pre:before,\n.purechat progress:before,\n.purechat q:before,\n.purechat rp:before,\n.purechat rt:before,\n.purechat ruby:before,\n.purechat s:before,\n.purechat samp:before,\n.purechat section:before,\n.purechat select:before,\n.purechat small:before,\n.purechat source:before,\n.purechat span:before,\n.purechat strong:before,\n.purechat style:before,\n.purechat sub:before,\n.purechat summary:before,\n.purechat sup:before,\n.purechat table:before,\n.purechat tbody:before,\n.purechat td:before,\n.purechat textarea:before,\n.purechat tfoot:before,\n.purechat th:before,\n.purechat thead:before,\n.purechat time:before,\n.purechat title:before,\n.purechat tr:before,\n.purechat track:before,\n.purechat u:before,\n.purechat ul:before,\n.purechat var:before,\n.purechat video:before,\n.purechat wbr:before,\n.purechat a:after,\n.purechat abbr:after,\n.purechat address:after,\n.purechat area:after,\n.purechat article:after,\n.purechat aside:after,\n.purechat audio:after,\n.purechat b:after,\n.purechat base:after,\n.purechat bdi:after,\n.purechat bdo:after,\n.purechat blockquote:after,\n.purechat body:after,\n.purechat br:after,\n.purechat button:after,\n.purechat canvas:after,\n.purechat caption:after,\n.purechat cite:after,\n.purechat code:after,\n.purechat col:after,\n.purechat colgroup:after,\n.purechat command:after,\n.purechat datalist:after,\n.purechat dd:after,\n.purechat del:after,\n.purechat details:after,\n.purechat dfn:after,\n.purechat div:after,\n.purechat dl:after,\n.purechat dt:after,\n.purechat em:after,\n.purechat embed:after,\n.purechat fieldset:after,\n.purechat figcaption:after,\n.purechat figure:after,\n.purechat footer:after,\n.purechat form:after,\n.purechat h1:after,\n.purechat h2:after,\n.purechat h3:after,\n.purechat h4:after,\n.purechat h5:after,\n.purechat h6:after,\n.purechat head:after,\n.purechat header:after,\n.purechat hgroup:after,\n.purechat hr:after,\n.purechat i:after,\n.purechat iframe:after,\n.purechat img:after,\n.purechat input:after,\n.purechat ins:after,\n.purechat kbd:after,\n.purechat keygen:after,\n.purechat label:after,\n.purechat legend:after,\n.purechat li:after,\n.purechat link:after,\n.purechat map:after,\n.purechat mark:after,\n.purechat menu:after,\n.purechat meta:after,\n.purechat meter:after,\n.purechat nav:after,\n.purechat noscript:after,\n.purechat object:after,\n.purechat ol:after,\n.purechat optgroup:after,\n.purechat option:after,\n.purechat output:after,\n.purechat p:after,\n.purechat param:after,\n.purechat pre:after,\n.purechat progress:after,\n.purechat q:after,\n.purechat rp:after,\n.purechat rt:after,\n.purechat ruby:after,\n.purechat s:after,\n.purechat samp:after,\n.purechat section:after,\n.purechat select:after,\n.purechat small:after,\n.purechat source:after,\n.purechat span:after,\n.purechat strong:after,\n.purechat style:after,\n.purechat sub:after,\n.purechat summary:after,\n.purechat sup:after,\n.purechat table:after,\n.purechat tbody:after,\n.purechat td:after,\n.purechat textarea:after,\n.purechat tfoot:after,\n.purechat th:after,\n.purechat thead:after,\n.purechat time:after,\n.purechat title:after,\n.purechat tr:after,\n.purechat track:after,\n.purechat u:after,\n.purechat ul:after,\n.purechat var:after,\n.purechat video:after,\n.purechat wbr:after {\n  box-sizing: border-box !important;\n}\n.purechat ::-webkit-input-placeholder {\n  color: #afaba3 !important;\n}\n.purechat ::-moz-placeholder {\n  color: #afaba3 !important;\n  opacity: 1 !important;\n}\n.purechat :-ms-input-placeholder {\n  color: #afaba3 !important;\n}\n.purechat ::-ms-input-placeholder {\n  color: #afaba3 !important;\n}\n.purechat a {\n  cursor: pointer !important;\n}\n.purechat a,\n.purechat em,\n.purechat span,\n.purechat strong {\n  display: inline !important;\n}\n.purechat button,\n.purechat img {\n  display: inline-block !important;\n}\n#PureChatWidget.purechat.purechat-animate,\n#PureChatWidget.purechat .purechat-animate {\n  animation-fill-mode: both !important;\n  animation-duration: 1s !important;\n}\n#PureChatWidget.purechat.purechat-animate-somewhat-fast,\n#PureChatWidget.purechat .purechat-animate-somewhat-fast {\n  animation-duration: 0.2s !important;\n  animation-fill-mode: both !important;\n  animation-timing-function: ease-in !important;\n}\n#PureChatWidget.purechat.purechat-animate.purechat-animate-fast,\n#PureChatWidget.purechat .purechat-animate.purechat-animate-fast {\n  animation-duration: 0.1s !important;\n  animation-fill-mode: both !important;\n  animation-timing-function: ease-in !important;\n}\n#PureChatWidget.purechat.purechat-animate.purechat-animation-hinge {\n  animation-duration: 1s !important;\n}\n#PureChatWidget.purechat.purechat-animate.purechat-animation-flip {\n  backface-visibility: visible !important;\n  animation-name: purechat-flip !important;\n}\n#PureChatWidget.purechat.purechat-animation-flipInX {\n  backface-visibility: visible !important;\n  animation-name: purechat-flipInX !important;\n}\n#PureChatWidget.purechat.purechat-animation-flipInY {\n  backface-visibility: visible !important;\n  animation-name: purechat-flipInY !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeIn,\n#PureChatWidget.purechat .purechat-animation-fadeIn {\n  animation-name: purechat-fadeIn !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInUp {\n  animation-name: purechat-fadeInUp !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInDown {\n  animation-name: purechat-fadeInDown !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInLeft {\n  animation-name: purechat-fadeInLeft !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInRight {\n  animation-name: purechat-fadeInRight !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInUpBig {\n  animation-name: purechat-fadeInUpBig !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInDownBig {\n  animation-name: purechat-fadeInDownBig !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInLeftBig {\n  animation-name: purechat-fadeInLeftBig !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInRightBig {\n  animation-name: purechat-fadeInRightBig !important;\n}\n#PureChatWidget.purechat.purechat-animation-slideInDown {\n  animation-name: purechat-slideInDown !important;\n}\n#PureChatWidget.purechat.purechat-animation-slideInUp {\n  animation-name: purechat-slideInUp !important;\n}\n#PureChatWidget.purechat.purechat-animation-slideInLeft {\n  animation-name: purechat-slideInLeft !important;\n}\n#PureChatWidget.purechat.purechat-animation-slideInRight {\n  animation-name: purechat-slideInRight !important;\n}\n#PureChatWidget.purechat.purechat-animation-bounceIn {\n  animation-name: purechat-bounceIn !important;\n}\n#PureChatWidget.purechat.purechat-animation-bounceInUp {\n  animation-name: purechat-bounceInUp !important;\n}\n#PureChatWidget.purechat.purechat-animation-bounceInDown {\n  animation-name: purechat-bounceInDown !important;\n}\n#PureChatWidget.purechat.purechat-animation-bounceInLeft {\n  animation-name: purechat-bounceInLeft !important;\n}\n#PureChatWidget.purechat.purechat-animation-bounceInRight {\n  animation-name: purechat-bounceInRight !important;\n}\n#PureChatWidget.purechat.purechat-animation-slideInRight {\n  animation-name: purechat-slideInRight !important;\n}\n#PureChatWidget.purechat.purechat-animation-rotateIn {\n  animation-name: purechat-rotateIn !important;\n}\n#PureChatWidget.purechat.purechat-animation-rotateInUpLeft {\n  animation-name: purechat-rotateInUpLeft !important;\n}\n#PureChatWidget.purechat.purechat-animation-rotateInDownLeft {\n  animation-name: purechat-rotateInDownLeft !important;\n}\n#PureChatWidget.purechat.purechat-animation-rotateInUpRight {\n  animation-name: purechat-rotateInUpRight !important;\n}\n#PureChatWidget.purechat.purechat-animation-rotateInDownRight {\n  animation-name: purechat-rotateInDownRight !important;\n}\n#PureChatWidget.purechat.purechat-animation-lightSpeedIn {\n  animation-name: lightSpeedIn !important;\n  animation-timing-function: ease-out !important;\n}\n#PureChatWidget.purechat.purechat-animation-rollIn {\n  animation-name: purechat-rollIn !important;\n}\n#PureChatWidget.purechat.purechat-animation-toast-x {\n  opacity: 0 !important;\n  animation-duration: 4s !important;\n  animation-iteration-count: 1 !important;\n  animation-name: purechat-toastRight !important;\n}\n#PureChatWidget.purechat .purechat-animation-toastUpDown {\n  opacity: 0 !important;\n  animation-duration: 4s !important;\n  animation-iteration-count: 1 !important;\n  animation-name: purechat-toastUpDown !important;\n}\n#PureChatWidget.purechat .purechat-animation-toastDownUp {\n  opacity: 0 !important;\n  animation-duration: 4s !important;\n  animation-iteration-count: 1 !important;\n  animation-name: purechat-toastDownUp !important;\n}\n#PureChatWidget.purechat.purechat-animation.purechat-animation-none {\n  animation-fill-mode: both !important;\n  animation-duration: 0.1s !important;\n}\n#PureChatWidget.purechat.purechat-animation-none {\n  animation-name: purechat-none !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeOutDownSmall,\n#PureChatWidget.purechat .purechat-animation-fadeOutDownSmall {\n  animation-name: purechat-fadeOutDownSmall !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeOutUpSmall,\n#PureChatWidget.purechat .purechat-animation-fadeOutUpSmall {\n  animation-name: purechat-fadeOutUpSmall !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInDownSmall,\n#PureChatWidget.purechat .purechat-animation-fadeInDownSmall {\n  animation-name: purechat-fadeInDownSmall !important;\n}\n#PureChatWidget.purechat.purechat-animation-fadeInUpSmall,\n#PureChatWidget.purechat .purechat-animation-fadeInUpSmall {\n  animation-name: purechat-fadeInUpSmall !important;\n}\n#PureChatWidget.purechat.purechat-animation-bounceUpSmall,\n#PureChatWidget.purechat .purechat-animation-bounceUpSmall {\n  animation-name: purechat-bounceUpSmall !important;\n}\n#PureChatWidget.purechat.purechat-animation-bounceDownSmall,\n#PureChatWidget.purechat .purechat-animation-bounceDownSmall {\n  animation-name: purechat-bounceDownSmall !important;\n}\n#PureChatWidget.purechat .purechat-animate-spin,\n#PureChatWidget.purechat.purechat-animate-spin {\n  animation-name: purechat-spin !important;\n  animation-iteration-count: infinite !important;\n  animation-duration: 3s !important;\n}\n@-moz-keyframes purechat-spin {\n  from {\n    transform: rotate(0deg) !important;\n  }\n  to {\n    transform: rotate(360deg) !important;\n  }\n}\n@-webkit-keyframes purechat-spin {\n  from {\n    transform: rotate(0deg) !important;\n  }\n  to {\n    transform: rotate(360deg) !important;\n  }\n}\n@-o-keyframes purechat-spin {\n  from {\n    transform: rotate(0deg) !important;\n  }\n  to {\n    transform: rotate(360deg) !important;\n  }\n}\n@keyframes purechat-spin {\n  from {\n    transform: rotate(0deg) !important;\n  }\n  to {\n    transform: rotate(360deg) !important;\n  }\n}\n@-moz-keyframes purechat-flip {\n  0% {\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    animation-timing-function: ease-out;\n  }\n  40% {\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    animation-timing-function: ease-out;\n  }\n  50% {\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n  80% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(0.95);\n    animation-timing-function: ease-in;\n  }\n  100% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n}\n@-webkit-keyframes purechat-flip {\n  0% {\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    animation-timing-function: ease-out;\n  }\n  40% {\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    animation-timing-function: ease-out;\n  }\n  50% {\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n  80% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(0.95);\n    animation-timing-function: ease-in;\n  }\n  100% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n}\n@-o-keyframes purechat-flip {\n  0% {\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    animation-timing-function: ease-out;\n  }\n  40% {\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    animation-timing-function: ease-out;\n  }\n  50% {\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n  80% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(0.95);\n    animation-timing-function: ease-in;\n  }\n  100% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n}\n@keyframes purechat-flip {\n  0% {\n    transform: perspective(400px) translateZ(0) rotateY(0) scale(1);\n    animation-timing-function: ease-out;\n  }\n  40% {\n    transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);\n    animation-timing-function: ease-out;\n  }\n  50% {\n    transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n  80% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(0.95);\n    animation-timing-function: ease-in;\n  }\n  100% {\n    transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);\n    animation-timing-function: ease-in;\n  }\n}\n@-moz-keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-rotateInDownLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-rotateInDownLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-rotateInDownLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@keyframes purechat-rotateInDownLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-rotateInUpRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-rotateInUpRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-rotateInUpRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@keyframes purechat-rotateInUpRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(-90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-rotateInDownRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-rotateInDownRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-rotateInDownRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@keyframes purechat-rotateInDownRight {\n  0% {\n    transform-origin: right bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: right bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-lightSpeedIn {\n  0% {\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n  60% {\n    transform: translateX(-20%) skewX(30deg);\n    opacity: 1;\n  }\n  80% {\n    transform: translateX(0%) skewX(-15deg);\n    opacity: 1;\n  }\n  100% {\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-lightSpeedIn {\n  0% {\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n  60% {\n    transform: translateX(-20%) skewX(30deg);\n    opacity: 1;\n  }\n  80% {\n    transform: translateX(0%) skewX(-15deg);\n    opacity: 1;\n  }\n  100% {\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-lightSpeedIn {\n  0% {\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n  60% {\n    transform: translateX(-20%) skewX(30deg);\n    opacity: 1;\n  }\n  80% {\n    transform: translateX(0%) skewX(-15deg);\n    opacity: 1;\n  }\n  100% {\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n}\n@keyframes purechat-lightSpeedIn {\n  0% {\n    transform: translateX(100%) skewX(-30deg);\n    opacity: 0;\n  }\n  60% {\n    transform: translateX(-20%) skewX(30deg);\n    opacity: 1;\n  }\n  80% {\n    transform: translateX(0%) skewX(-15deg);\n    opacity: 1;\n  }\n  100% {\n    transform: translateX(0%) skewX(0deg);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-rollIn {\n  0% {\n    opacity: 0;\n    transform: translateX(-100%) rotate(-120deg);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0px) rotate(0deg);\n  }\n}\n@-webkit-keyframes purechat-rollIn {\n  0% {\n    opacity: 0;\n    transform: translateX(-100%) rotate(-120deg);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0px) rotate(0deg);\n  }\n}\n@-o-keyframes purechat-rollIn {\n  0% {\n    opacity: 0;\n    transform: translateX(-100%) rotate(-120deg);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0px) rotate(0deg);\n  }\n}\n@keyframes purechat-rollIn {\n  0% {\n    opacity: 0;\n    transform: translateX(-100%) rotate(-120deg);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0px) rotate(0deg);\n  }\n}\n@-moz-keyframes purechat-toastRight {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  6% {\n    transform: translateX(7px);\n  }\n  7% {\n    transform: translateX(0px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n}\n@-webkit-keyframes purechat-toastRight {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  6% {\n    transform: translateX(7px);\n  }\n  7% {\n    transform: translateX(0px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n}\n@-o-keyframes purechat-toastRight {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  6% {\n    transform: translateX(7px);\n  }\n  7% {\n    transform: translateX(0px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n}\n@keyframes purechat-toastRight {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  6% {\n    transform: translateX(7px);\n  }\n  7% {\n    transform: translateX(0px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n}\n@-moz-keyframes purechat-toastUpDown {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n@-webkit-keyframes purechat-toastUpDown {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n@-o-keyframes purechat-toastUpDown {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n@keyframes purechat-toastUpDown {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n@-moz-keyframes purechat-toastDownUp {\n  0% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-toastDownUp {\n  0% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-toastDownUp {\n  0% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-toastDownUp {\n  0% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n  5% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  95% {\n    opacity: 1;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-none {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-none {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-none {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@keyframes purechat-none {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-flipInX {\n  0% {\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateX(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateX(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-flipInX {\n  0% {\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateX(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateX(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-flipInX {\n  0% {\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateX(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateX(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n}\n@keyframes purechat-flipInX {\n  0% {\n    transform: perspective(400px) rotateX(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateX(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateX(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateX(0deg);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-flipInY {\n  0% {\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateY(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateY(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-flipInY {\n  0% {\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateY(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateY(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-flipInY {\n  0% {\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateY(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateY(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n}\n@keyframes purechat-flipInY {\n  0% {\n    transform: perspective(400px) rotateY(90deg);\n    opacity: 0;\n  }\n  40% {\n    transform: perspective(400px) rotateY(-10deg);\n  }\n  70% {\n    transform: perspective(400px) rotateY(10deg);\n  }\n  100% {\n    transform: perspective(400px) rotateY(0deg);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-fadeIn {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-fadeIn {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-fadeIn {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@keyframes purechat-fadeIn {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-fadeInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-fadeInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-fadeInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-fadeInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-fadeInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-fadeInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-fadeInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-fadeInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-fadeInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-fadeInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-fadeInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-fadeInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-20px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-fadeInUpBig {\n  0% {\n    opacity: 0;\n    transform: translateY(100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInUpBig {\n  0% {\n    opacity: 0;\n    transform: translateY(100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-fadeInUpBig {\n  0% {\n    opacity: 0;\n    transform: translateY(100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-fadeInUpBig {\n  0% {\n    opacity: 0;\n    transform: translateY(100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-fadeInDownBig {\n  0% {\n    opacity: 0;\n    transform: translateY(-100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInDownBig {\n  0% {\n    opacity: 0;\n    transform: translateY(-100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-fadeInDownBig {\n  0% {\n    opacity: 0;\n    transform: translateY(-100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-fadeInDownBig {\n  0% {\n    opacity: 0;\n    transform: translateY(-100vh);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-fadeInLeftBig {\n  0% {\n    opacity: 0;\n    transform: translateX(100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInLeftBig {\n  0% {\n    opacity: 0;\n    transform: translateX(100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-fadeInLeftBig {\n  0% {\n    opacity: 0;\n    transform: translateX(100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-fadeInLeftBig {\n  0% {\n    opacity: 0;\n    transform: translateX(100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-fadeInRightBig {\n  0% {\n    opacity: 0;\n    transform: translateX(-100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInRightBig {\n  0% {\n    opacity: 0;\n    transform: translateX(-100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-fadeInRightBig {\n  0% {\n    opacity: 0;\n    transform: translateX(-100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-fadeInRightBig {\n  0% {\n    opacity: 0;\n    transform: translateX(-100vw);\n  }\n  100% {\n    opacity: 1;\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-slideInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-slideInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-slideInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-slideInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-slideInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-slideInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-slideInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-slideInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-slideInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-slideInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-slideInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-slideInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-slideInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-slideInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-slideInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-slideInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-bounceIn {\n  0% {\n    opacity: 0;\n    transform: scale(0.3);\n  }\n  50% {\n    opacity: 1;\n    transform: scale(1.05);\n  }\n  70% {\n    transform: scale(0.9);\n  }\n  100% {\n    transform: scale(1);\n  }\n}\n@-webkit-keyframes purechat-bounceIn {\n  0% {\n    opacity: 0;\n    transform: scale(0.3);\n  }\n  50% {\n    opacity: 1;\n    transform: scale(1.05);\n  }\n  70% {\n    transform: scale(0.9);\n  }\n  100% {\n    transform: scale(1);\n  }\n}\n@-o-keyframes purechat-bounceIn {\n  0% {\n    opacity: 0;\n    transform: scale(0.3);\n  }\n  50% {\n    opacity: 1;\n    transform: scale(1.05);\n  }\n  70% {\n    transform: scale(0.9);\n  }\n  100% {\n    transform: scale(1);\n  }\n}\n@keyframes purechat-bounceIn {\n  0% {\n    opacity: 0;\n    transform: scale(0.3);\n  }\n  50% {\n    opacity: 1;\n    transform: scale(1.05);\n  }\n  70% {\n    transform: scale(0.9);\n  }\n  100% {\n    transform: scale(1);\n  }\n}\n@-moz-keyframes purechat-bounceInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(-30px);\n  }\n  80% {\n    transform: translateY(10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-bounceInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(-30px);\n  }\n  80% {\n    transform: translateY(10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-bounceInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(-30px);\n  }\n  80% {\n    transform: translateY(10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-bounceInUp {\n  0% {\n    opacity: 0;\n    transform: translateY(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(-30px);\n  }\n  80% {\n    transform: translateY(10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-bounceInDown {\n  0% {\n    opacity: 0;\n    transform: translateY(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateY(30px);\n  }\n  80% {\n    transform: translateY(-10px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-bounceInLeft {\n  0% {\n    opacity: 0;\n    transform: translateX(2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(-30px);\n  }\n  80% {\n    transform: translateX(10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-webkit-keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-o-keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@keyframes purechat-bounceInRight {\n  0% {\n    opacity: 0;\n    transform: translateX(-2000px);\n  }\n  60% {\n    opacity: 1;\n    transform: translateX(30px);\n  }\n  80% {\n    transform: translateX(-10px);\n  }\n  100% {\n    transform: translateX(0);\n  }\n}\n@-moz-keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@keyframes purechat-rotateIn {\n  0% {\n    transform-origin: center center;\n    transform: rotate(-200deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: center center;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-webkit-keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-o-keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@keyframes purechat-rotateInUpLeft {\n  0% {\n    transform-origin: left bottom;\n    transform: rotate(90deg);\n    opacity: 0;\n  }\n  100% {\n    transform-origin: left bottom;\n    transform: rotate(0);\n    opacity: 1;\n  }\n}\n@-moz-keyframes purechat-bounceUpSmall {\n  50% {\n    opacity: 1;\n    transform: translateY(-5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-bounceUpSmall {\n  50% {\n    opacity: 1;\n    transform: translateY(-5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-bounceUpSmall {\n  50% {\n    opacity: 1;\n    transform: translateY(-5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-bounceUpSmall {\n  50% {\n    opacity: 1;\n    transform: translateY(-5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-bounceDownSmall {\n  50% {\n    transform: translateY(5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-bounceDownSmall {\n  50% {\n    transform: translateY(5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-bounceDownSmall {\n  50% {\n    transform: translateY(5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-bounceDownSmall {\n  50% {\n    transform: translateY(5px);\n  }\n  100% {\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-fadeInDownSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInDownSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-fadeInDownSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-fadeInDownSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-fadeInUpSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-webkit-keyframes purechat-fadeInUpSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-o-keyframes purechat-fadeInUpSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@keyframes purechat-fadeInUpSmall {\n  0% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n@-moz-keyframes purechat-fadeOutUpSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n}\n@-webkit-keyframes purechat-fadeOutUpSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n}\n@-o-keyframes purechat-fadeOutUpSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n}\n@keyframes purechat-fadeOutUpSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n}\n@-moz-keyframes purechat-fadeOutDownSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n@-webkit-keyframes purechat-fadeOutDownSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n@-o-keyframes purechat-fadeOutDownSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n@keyframes purechat-fadeOutDownSmall {\n  0% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    transform: translateY(10px);\n  }\n}\n#PureChatWidget.purechat .purechat-widget-header {\n  align-items: center !important;\n  background-color: var(--purechat-p-bg) !important;\n  border-top-left-radius: 8px !important;\n  border-top-right-radius: 8px !important;\n  display: flex !important;\n  min-height: 55px !important;\n  padding: 10px 16px !important;\n  z-index: 1 !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-widget-room-avatar {\n  display: none !important;\n  order: 1 !important;\n  flex-shrink: 0 !important;\n  flex-grow: 0 !important;\n  width: 72px !important;\n  height: 72px !important;\n  border: 3px solid #fff !important;\n  margin: -33px -5px -5px 0 !important;\n  border-radius: 36px !important;\n  box-shadow: 1px 1px 2px rgba(0,0,0,0.35) !important;\n  background-size: cover !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-widget-room-avatar.purechat-has-room-avatar {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-menu.purechat-btn-toolbar {\n  display: block !important;\n  order: 3 !important;\n  flex-shrink: 0 !important;\n  flex-grow: 0 !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-widget-title {\n  display: flex !important;\n  flex-grow: 1 !important;\n  margin-left: -8px !important;\n  margin-top: 0 !important;\n  order: 2 !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn {\n  background-color: transparent !important;\n  border: 1px solid var(--purechat-btn-b) !important;\n  border-radius: 3px !important;\n  box-shadow: 1px 1px 2px rgba(0,0,0,0.5) !important;\n  display: inline-block !important;\n  margin-left: 9px !important;\n  margin-bottom: 0 !important;\n  padding: 5px 5px 4px !important;\n  position: relative !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-btn-active,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn:hover {\n  border: 1px solid var(--purechat-btn-b-h) !important;\n  box-shadow: 1px 1px 2px #000 !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn i {\n  font-size: 18px !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-display-none,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-display-none {\n  display: none !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-display-block,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-display-block {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-display-flex,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-display-flex {\n  display: flex !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-display-inline-block,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-display-inline-block {\n  display: inline-block !important;\n}\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-invisible,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-invisible *,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-invisible,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-invisible *,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-invisible *:after,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-invisible *:after,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn .purechat-invisible *:before,\n#PureChatWidget.purechat .purechat-widget-header .purechat-btn.purechat-invisible *:before {\n  visibility: hidden !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed.purechat-attached.purechat-top-left .purechat-widget-header,\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-attached.purechat-top-left .purechat-widget-header {\n  border-top-left-radius: 0 !important;\n  border-top-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed.purechat-attached.purechat-top-right .purechat-widget-header,\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-attached.purechat-top-right .purechat-widget-header {\n  border-top-left-radius: 0 !important;\n  border-top-right-radius: 0 !important;\n}\n#PureChatWidget.purechat .purechat-collapsed .purechat-widget-header {\n  border-radius: 5px !important;\n  height: 35px !important;\n  min-height: auto !important;\n  padding-left: 7px !important;\n  padding-right: 7px !important;\n}\n#PureChatWidget.purechat .purechat-collapsed .purechat-widget-header .purechat-btn {\n  margin-left: 5px !important;\n  padding: 2px !important;\n}\n#PureChatWidget.purechat .purechat-collapsed .purechat-widget-header .purechat-btn:first-child {\n  margin-left: 0 !important;\n}\n#PureChatWidget.purechat .purechat-collapsed .purechat-widget-header .purechat-btn:after,\n#PureChatWidget.purechat .purechat-collapsed .purechat-widget-header .purechat-btn svg:after {\n  content: none !important;\n  display: none !important;\n}\n#PureChatWidget.purechat .purechat-collapsed .purechat-widget-header .purechat-widget-title-link {\n  cursor: pointer !important;\n  font-size: 16px !important;\n  padding-bottom: 7px !important;\n  padding-left: 17px !important;\n  padding-top: 9px !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-widget-title-link {\n  color: var(--purechat-p-fg) !important;\n  cursor: default !important;\n  display: block !important;\n  font-size: 18px !important;\n  overflow: hidden !important;\n  padding-left: 17px !important;\n  text-overflow: ellipsis !important;\n  white-space: nowrap !important;\n}\n#PureChatWidget.purechat.purechat-unavailable-behavior-hide .purechat-widget-title-link {\n  cursor: default !important;\n}\n#PureChatWidget.purechat .purechat-footer {\n  align-items: center !important;\n  border-bottom-left-radius: 13px !important;\n  border-bottom-right-radius: 13px !important;\n  display: flex !important;\n  flex-shrink: 0 !important;\n  flex-grow: 0 !important;\n  padding: 10px !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-bottom-left .purechat-footer {\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-bottom-right .purechat-footer {\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat .purechat-footer button {\n  margin-right: 10px !important;\n}\n#PureChatWidget.purechat .purechat-poweredby-container,\n#PureChatWidget.purechat .doop__purechat-poweredby-container___18Yqr {\n  flex-grow: 1 !important;\n  flex-shrink: 1 !important;\n  order: 2 !important;\n}\n#PureChatWidget.purechat .purechat-poweredby,\n#PureChatWidget.purechat .doop__purechat-poweredby___3MzyS {\n  text-align: right !important;\n}\n#PureChatWidget.purechat .purechat-poweredby-text,\n#PureChatWidget.purechat .purechat-poweredby-link,\n#PureChatWidget.purechat .doop__purechat-poweredby-text___wnkQ_,\n#PureChatWidget.purechat .doop__purechat-poweredby-link___1e9as {\n  display: inline !important;\n  font-size: 12px !important;\n  opacity: 1 !important;\n  visibility: visible !important;\n}\n#PureChatWidget.purechat .purechat-poweredby-text,\n#PureChatWidget.purechat .doop__purechat-poweredby-text___wnkQ_ {\n  color: var(--purechat-s-fg) !important;\n}\n#PureChatWidget.purechat .purechat-poweredby-link,\n#PureChatWidget.purechat .doop__purechat-poweredby-link___1e9as {\n  color: var(--purechat-s-fg) !important;\n}\n#PureChatWidget.purechat .purechat-poweredby-link:hover,\n#PureChatWidget.purechat .doop__purechat-poweredby-link___1e9as:hover {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-toggle-audio-notifications,\n#PureChatWidget.purechat .purechat-btn-pop-out {\n  cursor: pointer !important;\n  color: var(--purechat-s-fg) !important;\n}\n#PureChatWidget.purechat .purechat-closed-poweredby a {\n  color: var(--purechat-s-fg) !important;\n}\n#PureChatWidget.purechat .purechat-closed-poweredby a:hover {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-firstname-input,\n#PureChatWidget.purechat .purechat-lastname-input,\n#PureChatWidget.purechat .purechat-phonenumber-input,\n#PureChatWidget.purechat .purechat-email-input,\n#PureChatWidget.purechat .purechat-company-input,\n#PureChatWidget.purechat .purechat-question-input,\n#PureChatWidget.purechat .purechat-send-form-message,\n#PureChatWidget.purechat .purechat-send-form,\n#PureChatWidget.purechat .purechat-emoji-search {\n  background-color: #fff !important;\n  border: 1px solid rgba(0,0,0,0.3) !important;\n  border-radius: 5px !important;\n  cursor: text !important;\n  font-size: 16px !important;\n  line-height: 22px !important;\n  margin-bottom: 10px !important;\n  padding: 8px 10px 9px 10px !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-firstname-input:focus,\n#PureChatWidget.purechat .purechat-lastname-input:focus,\n#PureChatWidget.purechat .purechat-phonenumber-input:focus,\n#PureChatWidget.purechat .purechat-email-input:focus,\n#PureChatWidget.purechat .purechat-company-input:focus,\n#PureChatWidget.purechat .purechat-question-input:focus,\n#PureChatWidget.purechat .purechat-send-form-message:focus,\n#PureChatWidget.purechat .purechat-send-form:focus,\n#PureChatWidget.purechat .purechat-emoji-search:focus {\n  font-size: 16px !important;\n}\n#PureChatWidget.purechat .purechat-question-input {\n  resize: none !important;\n  word-wrap: break-word !important;\n}\n#PureChatWidget.purechat .purechat-init-form .purechat-question-input,\n#PureChatWidget.purechat .purechat-email-form .purechat-question-input {\n  min-height: 85px !important;\n}\n#PureChatWidget.purechat .purechat-send-form {\n  -ms-flex-align: center !important;\n  align-items: center !important;\n  display: flex !important;\n  margin: 0 !important;\n  padding: 9px 11px !important;\n}\n#PureChatWidget.purechat .purechat-send-form-message {\n  border: none !important;\n  box-sizing: content-box !important;\n  flex-grow: 1 !important;\n  flex-shrink: 1 !important;\n  font-size: 16px !important;\n  height: auto !important;\n  line-height: 1.4 !important;\n  margin: 0 10px 0 0 !important;\n  overflow-x: hidden !important;\n  padding: 0 !important;\n  resize: none !important;\n  white-space: pre-wrap !important;\n  width: auto !important;\n  -ms-overflow-style: none !important;\n}\n#PureChatWidget.purechat .purechat-send-form-message:focus {\n  font-size: 16px !important;\n}\n#PureChatWidget.purechat .purechat-btn {\n  margin: 0 auto 5px !important;\n  padding: 10px 20px !important;\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-btn-emoji,\n#PureChatWidget.purechat .purechat-btn-file-transfer,\n#PureChatWidget.purechat .purechat-btn-send-message {\n  color: #afaba3 !important;\n  fill: #afaba3 !important;\n  transition: color 0.4s, fill 0.4s !important;\n}\n#PureChatWidget.purechat .purechat-btn-emoji:hover,\n#PureChatWidget.purechat .purechat-btn-file-transfer:hover,\n#PureChatWidget.purechat .purechat-btn-send-message:hover {\n  color: #3b404c !important;\n  fill: #3b404c !important;\n}\n#PureChatWidget.purechat .purechat-btn-file-transfer {\n  margin-right: 9px !important;\n}\n#PureChatWidget.purechat .purechat-label {\n  margin-top: 10px !important;\n}\n#PureChatWidget.purechat ::-webkit-input-placeholder {\n  color: #afaba3 !important;\n  opacity: 1 !important;\n}\n#PureChatWidget.purechat ::-moz-placeholder {\n  color: #afaba3 !important;\n  opacity: 1 !important;\n}\n#PureChatWidget.purechat :-ms-input-placeholder {\n  color: #afaba3 !important;\n  opacity: 1 !important;\n}\n#PureChatWidget.purechat ::-ms-input-placeholder {\n  color: #afaba3 !important;\n  opacity: 1 !important;\n}\n#PureChatWidget.purechat .purechat-message-wrapper {\n  position: relative !important;\n}\n#PureChatWidget.purechat .purechat-message-right {\n  margin-left: 20px !important;\n  position: relative !important;\n  text-align: right !important;\n}\n#PureChatWidget.purechat .purechat-message-left {\n  margin-right: 20px !important;\n  position: relative !important;\n  text-align: left !important;\n}\n#PureChatWidget.purechat .purechat-message-container {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-message,\n#PureChatWidget.purechat .purechat-message-note {\n  background-color: var(--purechat-s-bg-l) !important;\n  border-radius: 5px !important;\n  box-shadow: 1px 1px 5px rgba(0,0,0,0.4) !important;\n  color: var(--purechat-s-fg-d) !important;\n  display: inline-block !important;\n  font-size: 14px !important;\n  margin-bottom: 16px !important;\n  max-width: 100% !important;\n  padding: 8px 18px 9px !important;\n  position: relative !important;\n  word-wrap: break-word !important;\n}\n#PureChatWidget.purechat .purechat-message .purechat-message-tail,\n#PureChatWidget.purechat .purechat-message-note .purechat-message-tail {\n  bottom: -11px !important;\n  color: var(--purechat-s-bg-l) !important;\n  display: block !important;\n  fill: #fff !important;\n  height: 16px !important;\n  left: 5px !important;\n  position: absolute !important;\n  width: 18px !important;\n}\n#PureChatWidget.purechat .purechat-new-thought {\n  color: var(--purechat-s-fg-d) !important;\n  display: inline !important;\n  font-size: 14px !important;\n  word-wrap: break-word !important;\n}\n#PureChatWidget.purechat .purechat-new-thought a,\n#PureChatWidget.purechat .purechat-new-thought a:hover {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-message-right .purechat-message {\n  background-color: var(--purechat-s-bg-d) !important;\n}\n#PureChatWidget.purechat .purechat-message-right .purechat-message .purechat-message-tail {\n  color: var(--purechat-s-bg-d) !important;\n  left: auto !important;\n  right: 5px !important;\n}\n#PureChatWidget.purechat .purechat-message-right .purechat-new-thought {\n  color: var(--purechat-s-fg-l) !important;\n}\n#PureChatWidget.purechat .purechat-message-right .purechat-new-thought a,\n#PureChatWidget.purechat .purechat-message-right .purechat-new-thought a:hover {\n  color: var(--purechat-s-fg-l) !important;\n}\n#PureChatWidget.purechat .purechat-message-note-closed {\n  margin-bottom: 0 !important;\n  text-align: center !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-message-note-closed p {\n  color: var(--purechat-s-fg) !important;\n  text-align: center !important;\n  margin-bottom: 5px !important;\n}\n#PureChatWidget.purechat .purechat-message-wrapper.purechat-separator {\n  overflow: hidden !important;\n  margin: 0 0 15px 0 !important;\n  position: relative !important;\n  text-align: center !important;\n}\n#PureChatWidget.purechat .purechat-message-wrapper.purechat-separator span {\n  color: var(--purechat-s-fg) !important;\n  display: inline-block !important;\n  font-size: 12px !important;\n  padding: 0 10px !important;\n  position: relative !important;\n  vertical-align: baseline !important;\n  zoom: 1 !important;\n}\n#PureChatWidget.purechat .purechat-message-wrapper.purechat-separator span:before,\n#PureChatWidget.purechat .purechat-message-wrapper.purechat-separator span:after {\n  content: '' !important;\n  display: block !important;\n  width: 1000px !important;\n  position: absolute !important;\n  top: 0.73em !important;\n  border-top: 1px solid rgba(0,0,0,0.1) !important;\n}\n#PureChatWidget.purechat .purechat-message-wrapper.purechat-separator span:before {\n  right: 100% !important;\n}\n#PureChatWidget.purechat .purechat-message-wrapper.purechat-separator span:after {\n  left: 100% !important;\n}\n#PureChatWidget.purechat .purechat-message-right .purechat-time {\n  text-align: right !important;\n}\n#PureChatWidget.purechat .purechat-operator-gravatar,\n#PureChatWidget.purechat .purechat-timestamp,\n#PureChatWidget.purechat .purechat-displayname {\n  display: none !important;\n}\n#PureChatWidget.purechat .purechat-displayname.purechat-display-block {\n  color: var(--purechat-s-fg) !important;\n  font-size: 12px !important;\n  left: 9px !important;\n  position: absolute !important;\n  top: -16px !important;\n  width: 300px !important;\n}\n#PureChatWidget.purechat .purechat-message-multiple-operators {\n  margin-top: 15px !important;\n}\n#PureChatWidget.purechat .purechat-timestamp {\n  margin-top: -6px !important;\n  margin-bottom: 6px !important;\n}\n#PureChatWidget.purechat .purechat-time {\n  color: var(--purechat-s-fg) !important;\n  font-size: 12px !important;\n}\n#PureChatWidget.purechat .purechat-message-wrapper:last-child .purechat-timestamp {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-message-link {\n  overflow-wrap: break-word !important;\n  word-wrap: break-word !important;\n  -ms-word-break: break-all !important;\n  word-break: break-all !important;\n  word-break: break-word !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-link .purechat-message,\n#PureChatWidget.purechat .purechat-unfurl-image .purechat-message,\n#PureChatWidget.purechat .purechat-unfurl-twitter .purechat-message,\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-message,\n#PureChatWidget.purechat .purechat-unfurl-giphy .purechat-message {\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-twitter iframe.twitter-timeline {\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-media,\n#PureChatWidget.purechat .purechat-unfurl-iframe {\n  display: block !important;\n  margin-left: auto !important;\n  margin-right: auto !important;\n  max-height: 160px !important;\n  max-width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-iframe {\n  border: none 0 !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-title {\n  display: flex !important;\n  margin: 0 0 6px 0 !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-title a {\n  display: block !important;\n  overflow: hidden !important;\n  text-overflow: ellipsis !important;\n  white-space: nowrap !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-favicon {\n  margin-right: 6px !important;\n  max-width: 100% !important;\n  min-width: auto !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-image .purechat-new-thought a,\n#PureChatWidget.purechat .purechat-unfurl-image .purechat-new-thought img {\n  cursor: pointer !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-image .purechat-new-thought a {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-link .purechat-new-thought {\n  display: flex !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-link .purechat-unfurl-media {\n  flex-shrink: 0 !important;\n  margin-right: 10px !important;\n  max-height: 52px !important;\n  max-width: 25% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-link .purechat-unfurl-link-container {\n  color: var(--purechat-s-fg-l) !important;\n  overflow: hidden !important;\n  position: relative !important;\n  max-height: 3.875em !important;\n  text-align: left !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-message {\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-unfurl-youtube-wrapper {\n  position: relative !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-unfurl-youtube-wrapper:before {\n  content: \"\" !important;\n  display: block !important;\n  padding-top: 56.25% !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-unfurl-youtube-wrapper .purechat-unfurl-media,\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-unfurl-youtube-wrapper .purechat-unfurl-iframe {\n  bottom: 0 !important;\n  display: block !important;\n  height: 100% !important;\n  max-height: none !important;\n  max-width: none !important;\n  position: absolute !important;\n  left: 0 !important;\n  right: 0 !important;\n  top: 0 !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-unfurl-youtube-wrapper .purechat-unfurl-iframe {\n  max-height: 100% !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-unfurl-play {\n  background: rgba(0,0,0,0.5) !important;\n  border-radius: 25px !important;\n  cursor: pointer !important;\n  height: 50px !important;\n  left: 50% !important;\n  line-height: 50px !important;\n  position: absolute !important;\n  top: 50% !important;\n  transform: translate(-50%, -50%) !important;\n  width: 50px !important;\n}\n#PureChatWidget.purechat .purechat-unfurl-youtube .purechat-unfurl-play .pc-svgicon {\n  color: #fff !important;\n  cursor: pointer !important;\n  left: 15px !important;\n  position: absolute !important;\n  top: 13px !important;\n}\n#PureChatWidget.purechat .purechat-file {\n  margin-top: 12px !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-left .purechat-file-description,\n#PureChatWidget.purechat .purechat-file .purechat-message-left .purechat-file-description {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-left .purechat-file-description small,\n#PureChatWidget.purechat .purechat-file .purechat-message-left .purechat-file-description small {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-left .purechat-file-actions button,\n#PureChatWidget.purechat .purechat-file .purechat-message-left .purechat-file-actions button {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-left .purechat-file-actions button:hover,\n#PureChatWidget.purechat .purechat-file .purechat-message-left .purechat-file-actions button:hover {\n  color: var(--purechat-s-fg-l) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-left .purechat-file-error,\n#PureChatWidget.purechat .purechat-file .purechat-message-left .purechat-file-error {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-right .purechat-file-description,\n#PureChatWidget.purechat .purechat-file .purechat-message-right .purechat-file-description {\n  color: var(--purechat-s-fg-l) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-right .purechat-file-description small,\n#PureChatWidget.purechat .purechat-file .purechat-message-right .purechat-file-description small {\n  color: var(--purechat-s-fg-l) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-right .purechat-file-actions button,\n#PureChatWidget.purechat .purechat-file .purechat-message-right .purechat-file-actions button {\n  color: var(--purechat-s-fg-l) !important;\n}\n#PureChatWidget.purechat .purechat-file.purechat-message-right .purechat-file-error,\n#PureChatWidget.purechat .purechat-file .purechat-message-right .purechat-file-error {\n  color: var(--purechat-s-fg-l) !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-message {\n  padding: 0 !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-new-thought {\n  flex-direction: row !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-icon {\n  flex-shrink: 0 !important;\n  position: relative !important;\n  padding: 8px 18px 9px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-icon img {\n  margin-top: -15px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-description {\n  align-self: center !important;\n  flex-grow: 1 !important;\n  flex-shrink: 1 !important;\n  font-size: 20px !important;\n  overflow: hidden !important;\n  padding: 8px 0 9px !important;\n  text-overflow: ellipsis !important;\n  white-space: nowrap !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-description small {\n  font-size: 14px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-actions {\n  align-items: center !important;\n  display: flex !important;\n  flex-shrink: 0 !important;\n  position: relative !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-actions .purechat-loading {\n  position: relative !important;\n  right: 8px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-actions button,\n#PureChatWidget.purechat .purechat-file .purechat-file-actions a {\n  border-radius: 0 5px 5px 0 !important;\n  color: var(--purechat-s-fg-l) !important;\n  height: 100% !important;\n  opacity: 0.8 !important;\n  padding: 0 8px !important;\n  position: relative !important;\n  transition: background 0.3s, opacity 0.3s !important;\n  z-index: 100 !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-actions button:hover,\n#PureChatWidget.purechat .purechat-file .purechat-file-actions a:hover {\n  opacity: 1 !important;\n  color: #fff !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-actions a {\n  align-items: center !important;\n  display: flex !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image {\n  min-height: 80px !important;\n  position: relative !important;\n  text-align: center !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image img {\n  max-height: 160px !important;\n  max-width: 100% !important;\n  padding: 8px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image .purechat-file-actions {\n  display: none !important;\n  position: absolute !important;\n  top: 4px !important;\n  right: 4px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image .purechat-file-actions button,\n#PureChatWidget.purechat .purechat-file .purechat-file-image .purechat-file-actions a {\n  background: rgba(0,0,0,0.5) !important;\n  box-shadow: none !important;\n  color: #fff !important;\n  display: inline-block !important;\n  margin: 0 !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image .purechat-file-actions a + button {\n  margin-left: 8px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image .purechat-file-delete,\n#PureChatWidget.purechat .purechat-file .purechat-file-image .purechat-file-download {\n  border-radius: 5px !important;\n  padding: 8px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image .purechat-file-image-name {\n  background: rgba(0,0,0,0.5) !important;\n  border-radius: 5px !important;\n  bottom: 2px !important;\n  color: #fff !important;\n  display: none !important;\n  left: 50% !important;\n  margin-right: 50% !important;\n  max-width: 98% !important;\n  overflow: hidden !important;\n  padding: 4px 6px !important;\n  position: absolute !important;\n  text-align: center !important;\n  text-overflow: ellipsis !important;\n  transform: translate(-50%, 0) !important;\n  white-space: nowrap !important;\n  z-index: 9999 !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image:hover .purechat-file-image-name,\n#PureChatWidget.purechat .purechat-file .purechat-file-image.purechat-file-image-active .purechat-file-image-name {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-image:hover .purechat-file-actions,\n#PureChatWidget.purechat .purechat-file .purechat-file-image.purechat-file-image-active .purechat-file-actions {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-error {\n  color: var(--purechat-s-fg-l) !important;\n  padding: 8px 18px 9px !important;\n}\n#PureChatWidget.purechat .purechat-file .purechat-file-error svg {\n  color: var(--purechat-a-d) !important;\n  fill: var(--purechat-a-d) !important;\n  margin-right: 8px !important;\n}\n#PureChatWidget.purechat.purechat-style-minimal .purechat-file-actions .purechat-file-delete:hover {\n  background-color: var(--purechat-a-d-bg) !important;\n  color: var(--purechat-a-d-fg) !important;\n}\n#PureChatWidget.purechat.purechat-style-minimal .purechat-file-actions .purechat-file-download:hover {\n  background-color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-card {\n  background-color: var(--purechat-s-bg-l) !important;\n  border-radius: 5px !important;\n  box-shadow: 2px 2px 5px rgba(0,0,0,0.2) !important;\n  display: block !important;\n  font-size: 14px !important;\n  margin: 10px 10px 0 !important;\n  padding: 12px 18px !important;\n}\n#PureChatWidget.purechat .purechat-card-flex {\n  display: flex !important;\n  flex-direction: column !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-card-flex .purechat-card-header {\n  display: flex !important;\n  flex-grow: 0 !important;\n  flex-shrink: 0 !important;\n  font-size: 13px !important;\n  justify-content: space-between !important;\n}\n#PureChatWidget.purechat .purechat-card-flex .purechat-card-header span {\n  font-size: 13px !important;\n}\n#PureChatWidget.purechat .purechat-card-flex .purechat-card-body {\n  flex-grow: 1 !important;\n  flex-shrink: 1 !important;\n  overflow-y: auto !important;\n}\n#PureChatWidget.purechat .purechat-card-flex .purechat-card-footer {\n  font-size: 13px !important;\n}\n#PureChatWidget.purechat .purechat-card-bordered .purechat-card-header {\n  border-bottom: solid 1px rgba(0,0,0,0.1) !important;\n  padding-bottom: 12px !important;\n}\n#PureChatWidget.purechat .purechat-card-bordered .purechat-card-body {\n  padding-bottom: 12px !important;\n  padding-top: 12px !important;\n}\n#PureChatWidget.purechat .purechat-card-bordered .purechat-card-footer {\n  border-top: solid 1px rgba(0,0,0,0.1) !important;\n  padding-top: 12px !important;\n}\n#PureChatWidget.purechat .purechat-alert {\n  font-size: 14px !important;\n  padding: 5px !important;\n  text-align: center !important;\n}\n#PureChatWidget.purechat .purechat-alert-error {\n  color: var(--purechat-a-d) !important;\n}\n#PureChatWidget.purechat .purechat-alert-error.purechat-init-error-inline {\n  font-size: 24px !important;\n  line-height: 44px !important;\n  padding: 1px 5px !important;\n  position: absolute !important;\n  right: 30px !important;\n}\n#PureChatWidget.purechat .pc-svgicon {\n  background: none !important;\n  color: currentColor !important;\n  display: inline-block !important;\n  fill: currentColor !important;\n  height: 18px !important;\n  margin: initial !important;\n  overflow: hidden !important;\n  pointer-events: none !important;\n  position: relative !important;\n  transform: none !important;\n  vertical-align: -0.15em !important;\n  width: 18px !important;\n}\n#PureChatWidget.purechat .pc-svgicon-sm {\n  height: 15px !important;\n  width: 15px !important;\n}\n#PureChatWidget.purechat .pc-svgicon-md {\n  height: 20px !important;\n  width: 20px !important;\n}\n#PureChatWidget.purechat .pc-svgicon-lg {\n  height: 24px !important;\n  width: 24px !important;\n}\n#PureChatWidget.purechat .pc-svgicon-xl {\n  height: 40px !important;\n  width: 40px !important;\n}\n#PureChatWidget.purechat .purechat-emojis {\n  position: absolute !important;\n  top: 0 !important;\n  bottom: 10px !important;\n  left: 0 !important;\n  right: 0 !important;\n  z-index: 99999 !important;\n}\n#PureChatWidget.purechat.purechat-state-closed .purechat-emojis {\n  display: none !important;\n  z-index: -1 !important;\n}\n#PureChatWidget.purechat .purechat-emoji-container {\n  display: flex !important;\n  flex-wrap: wrap !important;\n}\n#PureChatWidget.purechat .purechat-curated-emojis {\n  margin-bottom: 15px !important;\n}\n#PureChatWidget.purechat .purechat-emoji-button {\n  border-radius: 3px !important;\n  flex-basis: 10% !important;\n  font-size: 18px !important;\n  padding: 3px 0 !important;\n  text-align: center !important;\n  transition: background-color 0.4s ease !important;\n}\n#PureChatWidget.purechat .purechat-emoji-button:hover,\n#PureChatWidget.purechat .purechat-emoji-button.purechat-emoji-button-active {\n  background-color: rgba(0,0,0,0.1) !important;\n}\n#PureChatWidget.purechat .purechat-emoji-autocomplete {\n  position: absolute !important;\n  bottom: 10px !important;\n  left: 0 !important;\n  right: 0 !important;\n  z-index: 99999 !important;\n}\n#PureChatWidget.purechat .purechat-flyout-arrow,\n#PureChatWidget.purechat .purechat-flyout-arrow:after {\n  position: absolute !important;\n  display: block !important;\n  width: 0 !important;\n  height: 0 !important;\n  border-color: transparent !important;\n  border-style: solid !important;\n  border-width: 20px 10px !important;\n}\n#PureChatWidget.purechat .purechat-flyout-arrow {\n  border-width: 22px 11px !important;\n}\n#PureChatWidget.purechat .purechat-flyout-arrow:after {\n  content: \"\" !important;\n}\n#PureChatWidget.purechat .purechat-flyout-arrow.purechat-flyout-arrow-bottom {\n  bottom: -22px !important;\n  left: 50% !important;\n  margin-left: -11px !important;\n  border-top-color: var(--purechat-p-bg-d) !important;\n  border-bottom-width: 0 !important;\n}\n#PureChatWidget.purechat .purechat-flyout-arrow.purechat-flyout-arrow-bottom:after {\n  content: \" \" !important;\n  top: -23px !important;\n  margin-left: -10px !important;\n  border-top-color: #fff !important;\n  border-bottom-width: 0 !important;\n}\n#PureChatWidget.purechat .purechat-flyout-arrow.purechat-flyout-arrow-top {\n  top: -22px !important;\n  left: 50% !important;\n  margin-left: -11px !important;\n  border-bottom-color: var(--purechat-p-bg-d) !important;\n  border-top-width: 0 !important;\n}\n#PureChatWidget.purechat .purechat-flyout-arrow.purechat-flyout-arrow-top:after {\n  content: \" \" !important;\n  bottom: -23px !important;\n  margin-left: -10px !important;\n  border-bottom-color: #fff !important;\n  border-top-width: 0 !important;\n}\n#PureChatWidget.purechat .purechat-flyout {\n  background: #fff !important;\n  border: solid 1px var(--purechat-p-bg) !important;\n  border-radius: 5px !important;\n  box-shadow: 1px 1px 4px rgba(0,0,0,0.4) !important;\n  opacity: 1 !important;\n  padding: 10px !important;\n  position: absolute !important;\n  min-width: 35px !important;\n  max-width: 373px !important;\n  z-index: 9999 !important;\n}\n#PureChatWidget.purechat .purechat-flyout.purechat-flyout-wide {\n  left: 0 !important;\n  max-width: none !important;\n  right: 0 !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-email-form {\n  min-width: 313px !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-twitter {\n  display: flex !important;\n  flex-direction: column !important;\n  min-width: 353px !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-twitter .purechat-flyout-twitter-feed {\n  flex-grow: 1 !important;\n  height: 312px !important;\n  margin-bottom: 10px !important;\n  overflow-y: hidden !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-twitter .purechat-flyout-twitter-feed >iframe {\n  border: none !important;\n  display: inline-block !important;\n  height: 312px !important;\n  margin-top: 0px !important;\n  margin-bottom: 0px !important;\n  max-height: 312px !important;\n  min-height: 312px !important;\n  max-width: 100% !important;\n  min-width: 180px !important;\n  padding: 0px !important;\n  position: static !important;\n  visibility: visible !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-twitter .purechat-flyout-twitter-buttons {\n  display: flex !important;\n  flex-direction: row !important;\n  height: 20px !important;\n  justify-content: center !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-twitter .purechat-flyout-twitter-buttons > div > iframe {\n  height: 20px !important;\n  position: static !important;\n  visibility: visible !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-twitter .purechat-flyout-twitter-buttons :first-child {\n  margin-right: 5px !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-twitter .purechat-flyout-twitter-buttons :last-child {\n  margin-left: 5px !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-address {\n  min-width: 353px !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-flyout-address iframe {\n  border: solid 1px #ddd !important;\n  height: 300px !important;\n  margin-bottom: 10px !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-flyout.purechat-flyout-bounce-up {\n  animation-name: purechat-bounceUpSmall !important;\n}\n#PureChatWidget.purechat .purechat-flyout.purechat-flyout-bounce-down {\n  animation-name: purechat-bounceDownSmall !important;\n}\n#PureChatWidget.purechat .purechat-flyout .purechat-card {\n  background: transparent !important;\n  box-shadow: none !important;\n  padding: 0 !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-flyout .purechat-email-form,\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-flyout .purechat-flyout-twitter,\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-flyout .purechat-flyout-address {\n  min-width: 0 !important;\n}\n#PureChatWidget.purechat.purechat-bottom-left .purechat-flyout.purechat-flyout-hide,\n#PureChatWidget.purechat.purechat-bottom-right .purechat-flyout.purechat-flyout-hide {\n  animation-name: purechat-fadeOutDownSmall !important;\n}\n#PureChatWidget.purechat.purechat-top-left .purechat-flyout.purechat-flyout-hide,\n#PureChatWidget.purechat.purechat-top-right .purechat-flyout.purechat-flyout-hide {\n  animation-name: purechat-fadeOutUpSmall !important;\n}\n#PureChatWidget.purechat.purechat-bottom-left .purechat-flyout.purechat-flyout-show,\n#PureChatWidget.purechat.purechat-bottom-right .purechat-flyout.purechat-flyout-show {\n  animation-name: purechat-fadeInDownSmall !important;\n}\n#PureChatWidget.purechat.purechat-top-left .purechat-flyout.purechat-flyout-show,\n#PureChatWidget.purechat.purechat-top-right .purechat-flyout.purechat-flyout-show {\n  animation-name: purechat-fadeInUpSmall !important;\n}\n#PureChatWidget.purechat.purechat-style-classic .purechat-flyout p {\n  color: #3b404c !important;\n}\n#PureChatWidget.purechat .purechat-message-preview-text {\n  white-space: nowrap !important;\n  overflow: hidden !important;\n  text-overflow: ellipsis !important;\n}\n#PureChatWidget.purechat .purechat-badge {\n  background-color: #c11e1f !important;\n  border-radius: 16px !important;\n  box-shadow: 1px 1px 3px rgba(0,0,0,0.4) !important;\n  color: #fff !important;\n  display: block !important;\n  font-size: 12px !important;\n  height: 16px !important;\n  padding: 0 !important;\n  position: absolute !important;\n  left: -5px !important;\n  text-align: center !important;\n  top: -5px !important;\n  width: 16px !important;\n  z-index: 10000000 !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed .purechat-badge,\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-badge {\n  font-size: 16px !important;\n  height: 25px !important;\n  left: -10px !important;\n  padding: 2px !important;\n  top: -12px !important;\n  width: 25px !important;\n}\n#PureChatWidget.purechat .purechat-loading {\n  margin: 0 !important;\n  height: 20px !important;\n  width: 20px !important;\n  animation: purechat-animation-loading 0.8s infinite linear !important;\n  border: 3px solid var(--purechat-btn-fg) !important;\n  border-right-color: transparent !important;\n  border-radius: 50% !important;\n}\n#PureChatWidget.purechat .purechat-loading-large {\n  height: 32px !important;\n  width: 32px !important;\n}\n#PureChatWidget.purechat .purechat-loading-center {\n  margin: 0 auto !important;\n  position: relative !important;\n  top: 8px !important;\n}\n#PureChatWidget.purechat .purechat-loading-light {\n  border: 3px solid var(--purechat-s-fg-d) !important;\n  border-right-color: transparent !important;\n}\n#PureChatWidget.purechat .purechat-loading-dark {\n  border: 3px solid var(--purechat-s-fg-d) !important;\n  border-right-color: transparent !important;\n}\n@-moz-keyframes purechat-animation-loading {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n@-webkit-keyframes purechat-animation-loading {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n@-o-keyframes purechat-animation-loading {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n@keyframes purechat-animation-loading {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n#PureChatWidget.purechat .purechat-file-overlay {\n  background: rgba(0,0,0,0.4) !important;\n  bottom: 0 !important;\n  left: 0 !important;\n  position: absolute !important;\n  right: 0 !important;\n  top: 0 !important;\n  z-index: 9999 !important;\n}\n#PureChatWidget.purechat:not(.purechat-attached) .purechat-file-overlay {\n  border-bottom-right-radius: 13px !important;\n  border-bottom-left-radius: 13px !important;\n}\n#PureChatWidget.purechat .purechat-file-overlay-instructions {\n  background: #fff !important;\n  border-radius: 110px !important;\n  font-size: 20px !important;\n  height: 220px !important;\n  left: 50% !important;\n  line-height: 260px !important;\n  position: absolute !important;\n  text-align: center !important;\n  top: 50% !important;\n  transform: translate(-50%, -50%) !important;\n  width: 220px !important;\n}\n#PureChatWidget.purechat .purechat-file-overlay-instructions img {\n  position: absolute !important;\n  top: -10px !important;\n  left: 50% !important;\n  transform: translateX(-50%) !important;\n}\n#PureChatWidgetImagePreview {\n  background: rgba(0,0,0,0.8) !important;\n  bottom: 0 !important;\n  left: 0 !important;\n  position: fixed !important;\n  right: 0 !important;\n  top: 0 !important;\n  z-index: 9999999 !important;\n}\n#PureChatWidgetImagePreview > img {\n  left: 50% !important;\n  position: absolute !important;\n  max-height: 100% !important;\n  max-width: 100% !important;\n  top: 50% !important;\n  transform: translate(-50%, -50%) !important;\n}\n#PureChatWidgetImagePreview > button {\n  background: transparent !important;\n  border: none 0 !important;\n  color: #fff !important;\n  font-size: 35px !important;\n  position: absolute !important;\n  right: 10px !important;\n  top: 10px !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner {\n  background: var(--purechat-p-bg) 50% 50% no-repeat !important;\n  mask: url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiIGNsYXNzPSJ1aWwtc3BpbiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0iaGVpZ2h0OjY0cHg7d2lkdGg6NjRweDtwZXJzcGVjdGl2ZS1vcmlnaW46MzJweCAzMnB4O3RyYW5zZm9ybS1vcmlnaW46MzJweCAzMnB4OyI+ICAgIDxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJub25lIiBjbGFzcz0iYmsiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6bm9uZTsiLz4gICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTAgNTApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoMCkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuOTkxMjAzIDAuOTkxMjAzKSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC42MzM2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSIwcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjBzIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDQ1KSB0cmFuc2xhdGUoMzQgMCkiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4OyI+ICAgICAgICAgICAgPGNpcmNsZSBjeD0iMCIgY3k9IjAiIHI9IjgiIGZpbGw9IiM4YzVlOWMiIHRyYW5zZm9ybT0ic2NhbGUoMS4xNDEyIDEuMTQxMikiIHN0eWxlPSJoZWlnaHQ6YXV0bztvcGFjaXR5OjAuNzQxNjY2O292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTtyOjhweDsiPiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiBmcm9tPSIxIiB0bz0iMC4xIiBiZWdpbj0iOTBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjkwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgIDwvY2lyY2xlPiAgICAgICAgPC9nPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoOTApIHRyYW5zbGF0ZSgzNCAwKSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7Ij4gICAgICAgICAgICA8Y2lyY2xlIGN4PSIwIiBjeT0iMCIgcj0iOCIgZmlsbD0iIzhjNWU5YyIgdHJhbnNmb3JtPSJzY2FsZSgxLjI5MTIgMS4yOTEyKSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC44NDk2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSIxODBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjE4MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDEzNSkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDEuNDU3ODcgMS40NTc4NykiIHN0eWxlPSJoZWlnaHQ6YXV0bztvcGFjaXR5OjAuOTY5NjY2O292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTtyOjhweDsiPiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiBmcm9tPSIxIiB0bz0iMC4xIiBiZWdpbj0iMjgwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InNjYWxlIiBmcm9tPSIxLjUiIHRvPSIuMjUiIGJlZ2luPSIyODBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgPC9jaXJjbGU+ICAgICAgICA8L2c+ICAgICAgICA8ZyB0cmFuc2Zvcm09InJvdGF0ZSgxODApIHRyYW5zbGF0ZSgzNCAwKSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7Ij4gICAgICAgICAgICA8Y2lyY2xlIGN4PSIwIiBjeT0iMCIgcj0iOCIgZmlsbD0iIzhjNWU5YyIgdHJhbnNmb3JtPSJzY2FsZSgwLjM1Nzg3IDAuMzU3ODcpIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3BhY2l0eTowLjE3NzY2NjtvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7cjo4cHg7Ij4gICAgICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgZnJvbT0iMSIgdG89IjAuMSIgYmVnaW49IjM3MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICAgICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJzY2FsZSIgZnJvbT0iMS41IiB0bz0iLjI1IiBiZWdpbj0iMzcwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgIDwvY2lyY2xlPiAgICAgICAgPC9nPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoMjI1KSB0cmFuc2xhdGUoMzQgMCkiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4OyI+ICAgICAgICAgICAgPGNpcmNsZSBjeD0iMCIgY3k9IjAiIHI9IjgiIGZpbGw9IiM4YzVlOWMiIHRyYW5zZm9ybT0ic2NhbGUoMC41MDc4NyAwLjUwNzg3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC4yODU2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI0NjBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjQ2MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDI3MCkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuNjc0NTM3IDAuNjc0NTM3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC40MDU2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI1NjBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjU2MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDMxNSkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuODI0NTM3IDAuODI0NTM3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC41MTM2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI2NTBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjY1MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgPC9nPiAgPC9zdmc+\") 50% 50% no-repeat !important;\n  -webkit-mask: url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiIGNsYXNzPSJ1aWwtc3BpbiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0iaGVpZ2h0OjY0cHg7d2lkdGg6NjRweDtwZXJzcGVjdGl2ZS1vcmlnaW46MzJweCAzMnB4O3RyYW5zZm9ybS1vcmlnaW46MzJweCAzMnB4OyI+ICAgIDxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJub25lIiBjbGFzcz0iYmsiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6bm9uZTsiLz4gICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTAgNTApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoMCkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuOTkxMjAzIDAuOTkxMjAzKSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC42MzM2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSIwcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjBzIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDQ1KSB0cmFuc2xhdGUoMzQgMCkiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4OyI+ICAgICAgICAgICAgPGNpcmNsZSBjeD0iMCIgY3k9IjAiIHI9IjgiIGZpbGw9IiM4YzVlOWMiIHRyYW5zZm9ybT0ic2NhbGUoMS4xNDEyIDEuMTQxMikiIHN0eWxlPSJoZWlnaHQ6YXV0bztvcGFjaXR5OjAuNzQxNjY2O292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTtyOjhweDsiPiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiBmcm9tPSIxIiB0bz0iMC4xIiBiZWdpbj0iOTBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjkwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgIDwvY2lyY2xlPiAgICAgICAgPC9nPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoOTApIHRyYW5zbGF0ZSgzNCAwKSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7Ij4gICAgICAgICAgICA8Y2lyY2xlIGN4PSIwIiBjeT0iMCIgcj0iOCIgZmlsbD0iIzhjNWU5YyIgdHJhbnNmb3JtPSJzY2FsZSgxLjI5MTIgMS4yOTEyKSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC44NDk2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSIxODBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjE4MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDEzNSkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDEuNDU3ODcgMS40NTc4NykiIHN0eWxlPSJoZWlnaHQ6YXV0bztvcGFjaXR5OjAuOTY5NjY2O292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTtyOjhweDsiPiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiBmcm9tPSIxIiB0bz0iMC4xIiBiZWdpbj0iMjgwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InNjYWxlIiBmcm9tPSIxLjUiIHRvPSIuMjUiIGJlZ2luPSIyODBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgPC9jaXJjbGU+ICAgICAgICA8L2c+ICAgICAgICA8ZyB0cmFuc2Zvcm09InJvdGF0ZSgxODApIHRyYW5zbGF0ZSgzNCAwKSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7Ij4gICAgICAgICAgICA8Y2lyY2xlIGN4PSIwIiBjeT0iMCIgcj0iOCIgZmlsbD0iIzhjNWU5YyIgdHJhbnNmb3JtPSJzY2FsZSgwLjM1Nzg3IDAuMzU3ODcpIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3BhY2l0eTowLjE3NzY2NjtvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7cjo4cHg7Ij4gICAgICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgZnJvbT0iMSIgdG89IjAuMSIgYmVnaW49IjM3MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICAgICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJzY2FsZSIgZnJvbT0iMS41IiB0bz0iLjI1IiBiZWdpbj0iMzcwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgIDwvY2lyY2xlPiAgICAgICAgPC9nPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoMjI1KSB0cmFuc2xhdGUoMzQgMCkiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4OyI+ICAgICAgICAgICAgPGNpcmNsZSBjeD0iMCIgY3k9IjAiIHI9IjgiIGZpbGw9IiM4YzVlOWMiIHRyYW5zZm9ybT0ic2NhbGUoMC41MDc4NyAwLjUwNzg3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC4yODU2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI0NjBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjQ2MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDI3MCkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuNjc0NTM3IDAuNjc0NTM3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC40MDU2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI1NjBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjU2MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDMxNSkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuODI0NTM3IDAuODI0NTM3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC41MTM2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI2NTBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjY1MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgPC9nPiAgPC9zdmc+\") 50% 50% no-repeat !important;\n  height: 64px !important;\n  left: 50% !important;\n  margin-left: -32px !important;\n  margin-top: -32px !important;\n  position: absolute !important;\n  top: 50% !important;\n  width: 64px !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner * {\n  display: none !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner.purechat-progress-spinner-compat {\n  background: transparent url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiIGNsYXNzPSJ1aWwtc3BpbiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0iaGVpZ2h0OjY0cHg7d2lkdGg6NjRweDtwZXJzcGVjdGl2ZS1vcmlnaW46MzJweCAzMnB4O3RyYW5zZm9ybS1vcmlnaW46MzJweCAzMnB4OyI+ICAgIDxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJub25lIiBjbGFzcz0iYmsiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6bm9uZTsiLz4gICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTAgNTApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoMCkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuOTkxMjAzIDAuOTkxMjAzKSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC42MzM2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSIwcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjBzIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDQ1KSB0cmFuc2xhdGUoMzQgMCkiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4OyI+ICAgICAgICAgICAgPGNpcmNsZSBjeD0iMCIgY3k9IjAiIHI9IjgiIGZpbGw9IiM4YzVlOWMiIHRyYW5zZm9ybT0ic2NhbGUoMS4xNDEyIDEuMTQxMikiIHN0eWxlPSJoZWlnaHQ6YXV0bztvcGFjaXR5OjAuNzQxNjY2O292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTtyOjhweDsiPiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiBmcm9tPSIxIiB0bz0iMC4xIiBiZWdpbj0iOTBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjkwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgIDwvY2lyY2xlPiAgICAgICAgPC9nPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoOTApIHRyYW5zbGF0ZSgzNCAwKSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7Ij4gICAgICAgICAgICA8Y2lyY2xlIGN4PSIwIiBjeT0iMCIgcj0iOCIgZmlsbD0iIzhjNWU5YyIgdHJhbnNmb3JtPSJzY2FsZSgxLjI5MTIgMS4yOTEyKSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC44NDk2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSIxODBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjE4MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDEzNSkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDEuNDU3ODcgMS40NTc4NykiIHN0eWxlPSJoZWlnaHQ6YXV0bztvcGFjaXR5OjAuOTY5NjY2O292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTtyOjhweDsiPiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiBmcm9tPSIxIiB0bz0iMC4xIiBiZWdpbj0iMjgwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InNjYWxlIiBmcm9tPSIxLjUiIHRvPSIuMjUiIGJlZ2luPSIyODBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgPC9jaXJjbGU+ICAgICAgICA8L2c+ICAgICAgICA8ZyB0cmFuc2Zvcm09InJvdGF0ZSgxODApIHRyYW5zbGF0ZSgzNCAwKSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46MHB4IDBweDt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7Ij4gICAgICAgICAgICA8Y2lyY2xlIGN4PSIwIiBjeT0iMCIgcj0iOCIgZmlsbD0iIzhjNWU5YyIgdHJhbnNmb3JtPSJzY2FsZSgwLjM1Nzg3IDAuMzU3ODcpIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3BhY2l0eTowLjE3NzY2NjtvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7cjo4cHg7Ij4gICAgICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgZnJvbT0iMSIgdG89IjAuMSIgYmVnaW49IjM3MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICAgICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJzY2FsZSIgZnJvbT0iMS41IiB0bz0iLjI1IiBiZWdpbj0iMzcwbXMiIGR1cj0iNzUwbXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjo1MCUgNTAlO3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpOyIvPiAgICAgICAgICAgIDwvY2lyY2xlPiAgICAgICAgPC9nPiAgICAgICAgPGcgdHJhbnNmb3JtPSJyb3RhdGUoMjI1KSB0cmFuc2xhdGUoMzQgMCkiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjBweCAwcHg7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4OyI+ICAgICAgICAgICAgPGNpcmNsZSBjeD0iMCIgY3k9IjAiIHI9IjgiIGZpbGw9IiM4YzVlOWMiIHRyYW5zZm9ybT0ic2NhbGUoMC41MDc4NyAwLjUwNzg3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC4yODU2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI0NjBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjQ2MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDI3MCkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuNjc0NTM3IDAuNjc0NTM3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC40MDU2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI1NjBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjU2MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgICAgIDxnIHRyYW5zZm9ybT0icm90YXRlKDMxNSkgdHJhbnNsYXRlKDM0IDApIiBzdHlsZT0iaGVpZ2h0OmF1dG87b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDsiPiAgICAgICAgICAgIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSI4IiBmaWxsPSIjOGM1ZTljIiB0cmFuc2Zvcm09InNjYWxlKDAuODI0NTM3IDAuODI0NTM3KSIgc3R5bGU9ImhlaWdodDphdXRvO29wYWNpdHk6MC41MTM2NjY7b3ZlcmZsb3cteDp2aXNpYmxlO292ZXJmbG93LXk6dmlzaWJsZTt3aWR0aDphdXRvO3BlcnNwZWN0aXZlLW9yaWdpbjowcHggMHB4O3RyYW5zZm9ybS1vcmlnaW46MHB4IDBweDtmaWxsOnJnYigxNDAsIDk0LCAxNTYpO3I6OHB4OyI+ICAgICAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIGZyb209IjEiIHRvPSIwLjEiIGJlZ2luPSI2NTBtcyIgZHVyPSI3NTBtcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIHN0eWxlPSJoZWlnaHQ6YXV0bztvdmVyZmxvdy14OnZpc2libGU7b3ZlcmZsb3cteTp2aXNpYmxlO3dpZHRoOmF1dG87cGVyc3BlY3RpdmUtb3JpZ2luOjUwJSA1MCU7dHJhbnNmb3JtLW9yaWdpbjowcHggMHB4O2ZpbGw6cmdiKDE0MCwgOTQsIDE1Nik7Ii8+ICAgICAgICAgICAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0ic2NhbGUiIGZyb209IjEuNSIgdG89Ii4yNSIgYmVnaW49IjY1MG1zIiBkdXI9Ijc1MG1zIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgc3R5bGU9ImhlaWdodDphdXRvO292ZXJmbG93LXg6dmlzaWJsZTtvdmVyZmxvdy15OnZpc2libGU7d2lkdGg6YXV0bztwZXJzcGVjdGl2ZS1vcmlnaW46NTAlIDUwJTt0cmFuc2Zvcm0tb3JpZ2luOjBweCAwcHg7ZmlsbDpyZ2IoMTQwLCA5NCwgMTU2KTsiLz4gICAgICAgICAgICA8L2NpcmNsZT4gICAgICAgIDwvZz4gICAgPC9nPiAgPC9zdmc+\") 50% 50% no-repeat !important;\n  mask: none !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner-container {\n  position: relative !important;\n  overflow: hidden !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner-container > * {\n  opacity: 0.5 !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner-container .purechat-progress-spinner {\n  opacity: 1 !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner-overlay {\n  height: 100% !important;\n  margin: 0 !important;\n  left: 0 !important;\n  top: 0 !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-progress-spinner-overlay:before {\n  left: 50% !important;\n  position: absolute !important;\n  top: 50% !important;\n}\n#PureChatWidget.purechat .purechat-collapsed-image {\n  background-size: contain !important;\n  background-repeat: no-repeat !important;\n  background-position: center center !important;\n  display: block !important;\n  height: 75px !important;\n  position: absolute !important;\n  width: 75px !important;\n}\n.purechat-assist,\n.purechat-assist body {\n  height: 100% !important;\n  width: 100% !important;\n  position: relative !important;\n  padding: 0 !important;\n  margin: 0 !important;\n}\n#PureChatWidget.purechat {\n  background-color: var(--purechat-p-bg-d) !important;\n  border: 0 !important;\n  border-radius: 13px !important;\n  box-shadow: 1px 1px 4px rgba(0,0,0,0.4) !important;\n  cursor: default !important;\n  position: fixed !important;\n  width: 373px !important;\n  z-index: 2147483646 !important;\n/* Default\n\t   ========================================================================== */\n/* Thumbs\n\t   ========================================================================== */\n/* Forms\n\t   ========================================================================== */\n/* Message Preview\n\t   ========================================================================== */\n/* Collapsed\n\t   ========================================================================== */\n/* Super collapsed\n\t   ========================================================================== */\n/* Expanded\n\t   ========================================================================== */\n/* Direct Access (Hosted)\n\t   ========================================================================== */\n}\n#PureChatWidget.purechat.purechat-style-classic {\n  border: 10px solid var(--purechat-p-bg-d) !important;\n}\n#PureChatWidget.purechat a,\n#PureChatWidget.purechat a:hover {\n  text-decoration: underline !important;\n}\n#PureChatWidget.purechat p {\n  color: var(--purechat-s-fg-d) !important;\n  margin-bottom: 10px !important;\n}\n#PureChatWidget.purechat textarea {\n  overflow: auto !important;\n}\n#PureChatWidget.purechat path {\n  color: currentColor !important;\n  fill: currentColor !important;\n}\n#PureChatWidget.purechat .purechat-display-none,\n#PureChatWidget.purechat.purechat-display-none {\n  display: none !important;\n}\n#PureChatWidget.purechat .purechat-display-block,\n#PureChatWidget.purechat.purechat-display-block {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-display-flex,\n#PureChatWidget.purechat.purechat-display-flex {\n  display: flex !important;\n}\n#PureChatWidget.purechat .purechat-display-inline-block,\n#PureChatWidget.purechat.purechat-display-inline-block {\n  display: inline-block !important;\n}\n#PureChatWidget.purechat .purechat-invisible,\n#PureChatWidget.purechat .purechat-invisible *,\n#PureChatWidget.purechat.purechat-invisible,\n#PureChatWidget.purechat.purechat-invisible *,\n#PureChatWidget.purechat .purechat-invisible *:after,\n#PureChatWidget.purechat.purechat-invisible *:after,\n#PureChatWidget.purechat .purechat-invisible *:before,\n#PureChatWidget.purechat.purechat-invisible *:before {\n  visibility: hidden !important;\n}\n#PureChatWidget.purechat.purechat-bottom-left {\n  left: 40px !important;\n  bottom: 10px !important;\n}\n#PureChatWidget.purechat.purechat-bottom-right {\n  right: 60px !important;\n  bottom: 10px !important;\n}\n#PureChatWidget.purechat.purechat-top-left {\n  left: 40px !important;\n  top: 10px !important;\n}\n#PureChatWidget.purechat.purechat-top-right {\n  right: 60px !important;\n  top: 10px !important;\n}\n#PureChatWidget.purechat .purechat-expanded,\n#PureChatWidget.purechat .purechat-collapsed-outer,\n#PureChatWidget.purechat .purechat-widget-inner,\n#PureChatWidget.purechat .purechat-widget-content-wrapper,\n#PureChatWidget.purechat .purechat-content-wrapper,\n#PureChatWidget.purechat .purechat-content,\n#PureChatWidget.purechat .purechat-message-list-view,\n#PureChatWidget.purechat .purechat-messages,\n#PureChatWidget.purechat .purechat-message-display-container,\n#PureChatWidget.purechat .purechat-send-form-container {\n  display: flex !important;\n  flex-direction: column !important;\n}\n#PureChatWidget.purechat .purechat-collapsed-outer {\n  position: relative !important;\n  z-index: 10 !important;\n}\n#PureChatWidget.purechat .purechat-expanded .purechat-display-none,\n#PureChatWidget.purechat .purechat-collapsed .purechat-display-none,\n#PureChatWidget.purechat .purechat-expanded.purechat-display-none,\n#PureChatWidget.purechat .purechat-collapsed.purechat-display-none {\n  display: none !important;\n}\n#PureChatWidget.purechat .purechat-expanded .purechat-display-block,\n#PureChatWidget.purechat .purechat-collapsed .purechat-display-block,\n#PureChatWidget.purechat .purechat-expanded.purechat-display-block,\n#PureChatWidget.purechat .purechat-collapsed.purechat-display-block {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-expanded .purechat-display-flex,\n#PureChatWidget.purechat .purechat-collapsed .purechat-display-flex,\n#PureChatWidget.purechat .purechat-expanded.purechat-display-flex,\n#PureChatWidget.purechat .purechat-collapsed.purechat-display-flex {\n  display: flex !important;\n}\n#PureChatWidget.purechat .purechat-expanded .purechat-display-inline-block,\n#PureChatWidget.purechat .purechat-collapsed .purechat-display-inline-block,\n#PureChatWidget.purechat .purechat-expanded.purechat-display-inline-block,\n#PureChatWidget.purechat .purechat-collapsed.purechat-display-inline-block {\n  display: inline-block !important;\n}\n#PureChatWidget.purechat .purechat-expanded .purechat-invisible,\n#PureChatWidget.purechat .purechat-collapsed .purechat-invisible,\n#PureChatWidget.purechat .purechat-expanded .purechat-invisible *,\n#PureChatWidget.purechat .purechat-collapsed .purechat-invisible *,\n#PureChatWidget.purechat .purechat-expanded.purechat-invisible,\n#PureChatWidget.purechat .purechat-collapsed.purechat-invisible,\n#PureChatWidget.purechat .purechat-expanded.purechat-invisible *,\n#PureChatWidget.purechat .purechat-collapsed.purechat-invisible *,\n#PureChatWidget.purechat .purechat-expanded .purechat-invisible *:after,\n#PureChatWidget.purechat .purechat-collapsed .purechat-invisible *:after,\n#PureChatWidget.purechat .purechat-expanded.purechat-invisible *:after,\n#PureChatWidget.purechat .purechat-collapsed.purechat-invisible *:after,\n#PureChatWidget.purechat .purechat-expanded .purechat-invisible *:before,\n#PureChatWidget.purechat .purechat-collapsed .purechat-invisible *:before,\n#PureChatWidget.purechat .purechat-expanded.purechat-invisible *:before,\n#PureChatWidget.purechat .purechat-collapsed.purechat-invisible *:before {\n  visibility: hidden !important;\n}\n#PureChatWidget.purechat .purechat-message-list-view {\n  flex-grow: 1 !important;\n}\n#PureChatWidget.purechat .purechat-send-form-container {\n  flex-shrink: 0 !important;\n}\n#PureChatWidget.purechat .purechat-content-wrapper {\n  background-color: var(--purechat-s-bg) !important;\n  border-bottom-left-radius: 13px !important;\n  border-bottom-right-radius: 13px !important;\n  position: relative !important;\n}\n#PureChatWidget.purechat .purechat-content-wrapper .purechat-user-status,\n#PureChatWidget.purechat .purechat-content-wrapper .purechat-send-form-container {\n  padding-left: 10px !important;\n  padding-right: 10px !important;\n}\n#PureChatWidget.purechat .purechat-content-wrapper strong,\n#PureChatWidget.purechat .purechat-content-wrapper strong > a {\n  font-weight: bold !important;\n}\n#PureChatWidget.purechat .purechat-content-wrapper em,\n#PureChatWidget.purechat .purechat-content-wrapper em > a {\n  font-style: italic !important;\n}\n#PureChatWidget.purechat .purechat-content-wrapper del,\n#PureChatWidget.purechat .purechat-content-wrapper del > a {\n  text-decoration: line-through !important;\n}\n#PureChatWidget.purechat .purechat-content-wrapper [data-resourcekey] p img {\n  max-width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-content-wrapper:before {\n  box-shadow: 0px 0px 10px rgba(0,0,0,0.2) !important;\n  content: '' !important;\n  height: 10px !important;\n  left: 0 !important;\n  position: absolute !important;\n  top: -10px !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-content {\n  flex-grow: 1 !important;\n  flex-shrink: 1 !important;\n  flex-basis: auto !important;\n}\n#PureChatWidget.purechat .purechat-message-display-container {\n  height: 370px !important;\n  min-height: 370px !important;\n  position: relative !important;\n}\n#PureChatWidget.purechat .purechat-message-display {\n  padding: 10px !important;\n  margin-bottom: 15px !important;\n  overflow-y: auto !important;\n  overflow-x: hidden !important;\n}\n#PureChatWidget.purechat.purechat-state-inactive.purechat-widget-expanded .purechat-message-display {\n  overflow: hidden !important;\n}\n#PureChatWidget.purechat.purechat-state-closed .purechat-message-display {\n  margin-bottom: 0 !important;\n}\n#PureChatWidget.purechat .purechat-messages {\n  flex-grow: 1 !important;\n  flex-shrink: 1 !important;\n}\n#PureChatWidget.purechat .purechat-user-status {\n  margin-top: -25px !important;\n  position: absolute !important;\n  text-align: center !important;\n  width: 100% !important;\n}\n#PureChatWidget.purechat .purechat-user-status span {\n  background-color: var(--purechat-s-bg) !important;\n  border-top-left-radius: 3px !important;\n  border-top-right-radius: 3px !important;\n  color: var(--purechat-s-fg) !important;\n  display: inline-block !important;\n  font-size: 12px !important;\n  padding: 5px 7px !important;\n  text-align: center !important;\n}\n#PureChatWidget.purechat.purechat-state-unavailable .purechat-closedmessage-container.purechat-no-operators {\n  color: var(--purechat-s-fg) !important;\n  padding: 1rem !important;\n  text-align: center !important;\n}\n#PureChatWidget.purechat .purechat-collapsed-image {\n  cursor: pointer !important;\n}\n#PureChatWidget.purechat .purechat-thumbs-container {\n  text-align: center !important;\n}\n#PureChatWidget.purechat .purechat-thumbs {\n  border: 1px solid rgba(0,0,0,0.2) !important;\n  border-radius: 3px !important;\n  color: var(--purechat-s-fg) !important;\n  box-shadow: 0px 0px 5px rgba(0,0,0,0.2) !important;\n  display: inline-block !important;\n  font-size: 38px !important;\n  margin-bottom: 10px !important;\n  margin-top: 10px !important;\n  padding: 10px !important;\n}\n#PureChatWidget.purechat .purechat-thumbs:hover,\n#PureChatWidget.purechat .purechat-thumbs.purechat-thumbs-selected {\n  border: 1px solid rgba(0,0,0,0.4) !important;\n  box-shadow: 0px 0px 5px rgba(0,0,0,0.5) !important;\n}\n#PureChatWidget.purechat .purechat-thumbs.purechat-thumbs-down {\n  color: #ce8d3a !important;\n  fill: #ce8d3a !important;\n}\n#PureChatWidget.purechat .purechat-thumbs.purechat-thumbs-up {\n  color: #1e7377 !important;\n  fill: #1e7377 !important;\n}\n#PureChatWidget.purechat .purechat-thumbs + .purechat-thumbs {\n  margin-left: 10px !important;\n}\n#PureChatWidget.purechat .purechat-message-note .purechat-poweredby-text,\n#PureChatWidget.purechat .purechat-message-note .purechat-poweredby-link {\n  font-size: 10px !important;\n}\n#PureChatWidget.purechat .purechat-ended-form a:not(.purechat-btn),\n#PureChatWidget.purechat .purechat-download-container a:not(.purechat-btn) {\n  color: var(--purechat-s-fg) !important;\n}\n#PureChatWidget.purechat .purechat-ended-form a:hover,\n#PureChatWidget.purechat .purechat-download-container a:hover {\n  color: var(--purechat-s-fg-d) !important;\n}\n#PureChatWidget.purechat .purechat-email-success {\n  background: var(--purechat-s-bg-l) !important;\n  margin: 10px 10px 0 !important;\n  padding: 10px !important;\n  border-radius: 5px !important;\n  box-shadow: 1px 2px 3px 1px #d9d8d7 !important;\n}\n#PureChatWidget.purechat .purechat-btn {\n  background-color: var(--purechat-btn-bg) !important;\n  border-radius: 5px !important;\n  box-shadow: 2px 2px 3px rgba(0,0,0,0.2) !important;\n  color: var(--purechat-btn-fg) !important;\n}\n#PureChatWidget.purechat a.purechat-btn,\n#PureChatWidget.purechat a.purechat-btn:hover {\n  color: var(--purechat-btn-fg) !important;\n  text-align: center !important;\n  text-decoration: none !important;\n}\n#PureChatWidget.purechat .purechat-btn i {\n  background-color: var(--purechat-btn-bg) !important;\n  color: var(--purechat-btn-fg) !important;\n}\n#PureChatWidget.purechat .purechat-label {\n  color: var(--purechat-s-fg) !important;\n}\n#PureChatWidget.purechat .purechat-message-preview.purechat-message-note {\n  margin-bottom: 10px !important;\n  max-width: calc(100% - 100px) !important;\n  position: absolute !important;\n  padding: 11px 18px !important;\n  background-color: #fff !important;\n}\n#PureChatWidget.purechat.purechat-bottom .purechat-message-preview {\n  bottom: 40px !important;\n}\n#PureChatWidget.purechat.purechat-top .purechat-message-preview {\n  top: 38px !important;\n}\n#PureChatWidget.purechat.purechat-top.purechat-attached .purechat-message-preview {\n  top: 28px !important;\n}\n#PureChatWidget.purechat.purechat-top.purechat-attached .purechat-message-preview {\n  top: 28px !important;\n}\n#PureChatWidget.purechat.purechat-top-left .purechat-message-preview {\n  right: 0 !important;\n}\n#PureChatWidget.purechat.purechat-bottom-left .purechat-message-preview {\n  right: 0 !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed {\n  border-radius: 5px !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed .purechat-collapsed-image {\n  background-position: center center !important;\n  background-repeat: no-repeat !important;\n  background-size: contain !important;\n  left: 50% !important;\n  position: absolute !important;\n  transform: translateX(-50%) !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed.purechat-top .purechat-collapsed-image {\n  bottom: 0 !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed.purechat-top .purechat-badge {\n  bottom: -4px !important;\n  top: auto !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed .purechat-message-preview.purechat-message-note {\n  margin-left: 0 !important;\n  margin-right: 0 !important;\n}\n#PureChatWidget.purechat.purechat-widget-collapsed.purechat-custom-button.purechat-style-classic {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-bottom-right,\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-bottom-left {\n  bottom: -30px !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-top-right,\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-top-left {\n  top: -30px !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-style-classic.purechat-bottom-right,\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-style-classic.purechat-bottom-left {\n  bottom: -45px !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-style-classic.purechat-top-right,\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-style-classic.purechat-top-left {\n  top: -45px !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed .purechat-btn,\n#PureChatWidget.purechat.purechat-widget-super-collapsed .purechat-widget-title-link {\n  visibility: hidden !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed .purechat-collapsed-image {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed .purechat-btn-collapse {\n  border: none !important;\n  bottom: 25px !important;\n  box-shadow: none !important;\n  display: inline-block !important;\n  margin-left: 5px !important;\n  padding: 8px !important;\n  position: absolute !important;\n  right: 14px !important;\n  visibility: visible !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-top-left .purechat-btn-collapse,\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-bottom-left .purechat-btn-collapse {\n  left: 24px !important;\n  margin-left: 0 !important;\n  right: auto !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-top .purechat-btn-collapse {\n  bottom: -42px !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed.purechat-top .purechat-badge {\n  bottom: -12px !important;\n  top: auto !important;\n}\n#PureChatWidget.purechat.purechat-widget-super-collapsed .purechat-start-chat .purechat-badge {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-widget-expanded.purechat-top-left {\n  top: 30px !important;\n}\n#PureChatWidget.purechat.purechat-widget-expanded.purechat-top-right {\n  top: 30px !important;\n}\n#PureChatWidget.purechat.purechat-widget-expanded.purechat-state-inactive .purechat-message-list-view {\n  flex-basis: 100% !important;\n}\n#PureChatWidget.purechat.purechat-hosted-widget {\n  margin: 0 auto !important;\n  position: static !important;\n}\n#PureChatWidget.purechat.purechat-hosted-widget.purechat-style-mobile {\n  width: auto !important;\n}\n@media print {\n  #PureChatWidget.purechat,\n  #PureChatWidget.purechat * {\n    display: none !important;\n  }\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-bottom-left .purechat-content-wrapper,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-bottom-left .purechat-content-wrapper {\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-bottom-right .purechat-content-wrapper,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-bottom-right .purechat-content-wrapper {\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-bottom-left,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-bottom-left,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-bottom-right,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-bottom-right {\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-top-left,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-top-left,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-top-right,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-top-right {\n  border-top-left-radius: 0 !important;\n  border-top-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-top-left.purechat-style-classic,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-top-left.purechat-style-classic,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-top-right.purechat-style-classic,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-super-collapsed.purechat-top-right.purechat-style-classic {\n  border-top: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-bottom {\n  bottom: 0 !important;\n  border-bottom: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-bottom .purechat-widget-header {\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-collapsed.purechat-top {\n  top: 0 !important;\n  border-top: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-expanded.purechat-bottom {\n  bottom: 0 !important;\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-widget-expanded.purechat-bottom .purechat-content-wrapper,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-expanded.purechat-bottom .purechat-widget-header,\n#PureChatWidget.purechat.purechat-attached.purechat-widget-expanded.purechat-bottom .purechat-footer {\n  border-bottom-left-radius: 0 !important;\n  border-bottom-right-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-bottom .purechat-message-preview {\n  bottom: 45px !important;\n  left: -10px !important;\n}\n#PureChatWidget.purechat.purechat-attached.purechat-top .purechat-message-preview {\n  top: 35px !important;\n}\n#PureChatWidget.purechat.purechat-image-only.purechat-top-left .purechat-message-preview,\n#PureChatWidget.purechat.purechat-image-only.purechat-top-right .purechat-message-preview {\n  top: 7px !important;\n}\n#PureChatWidget.purechat.purechat-image-only.purechat-widget-collapsed.purechat-bottom-right .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-image-only.purechat-widget-collapsed.purechat-top-right .purechat-collapsed-image {\n  left: auto !important;\n  right: -20px !important;\n  transform: none !important;\n}\n#PureChatWidget.purechat.purechat-image-only.purechat-widget-collapsed.purechat-bottom-left .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-image-only.purechat-widget-collapsed.purechat-top-left .purechat-collapsed-image {\n  left: 0 !important;\n  right: auto !important;\n  transform: none !important;\n}\n#PureChatWidget.purechat.purechat-image-only.purechat-widget-collapsed.purechat-style-classic {\n  border: none 0 !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget {\n  border-radius: 0 !important;\n  bottom: 0 !important;\n  display: flex !important;\n  flex-direction: column !important;\n  height: auto !important;\n  max-height: calc(100% - 24px) !important;\n  width: 100% !important;\n/* Super Collapsed and Collapsed\n\t   ========================================================================== */\n/* Collapsed\n\t   ========================================================================== */\n/* Super Collapsed\n\t   ========================================================================== */\n/* Expanded\n\t   ========================================================================== */\n}\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-message-display-container {\n  height: auto !important;\n  min-height: initial !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-message-preview.purechat-message-note {\n  padding: 20px 18px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-question-input {\n  overflow-x: hidden !important;\n  resize: none !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed {\n  border-radius: 8px !important;\n  width: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-bottom,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-bottom {\n  bottom: 10px !important;\n  left: 16px !important;\n  right: 16px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-bottom .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-bottom .purechat-collapsed-image {\n  bottom: 62px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-bottom .purechat-collapsed-image .purechat-missed-message-count,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-bottom .purechat-collapsed-image .purechat-missed-message-count {\n  top: 6px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-bottom .purechat-message-preview,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-bottom .purechat-message-preview {\n  bottom: 60px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-top,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-top {\n  top: 10px !important;\n  left: 16px !important;\n  right: 16px !important;\n  bottom: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-top .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-top .purechat-collapsed-image {\n  top: 62px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-top .purechat-collapsed-image .purechat-missed-message-count,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-top .purechat-collapsed-image .purechat-missed-message-count {\n  bottom: 6px !important;\n  top: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-top .purechat-message-preview,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-top .purechat-message-preview {\n  top: 68px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-top-left .purechat-btn-collapse,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-top-left .purechat-btn-collapse,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-bottom-left .purechat-btn-collapse,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-bottom-left .purechat-btn-collapse {\n  left: 14px !important;\n  margin-left: 0 !important;\n  right: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed .purechat-widget-header,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed .purechat-widget-header {\n  height: auto !important;\n  padding-left: 11px !important;\n  padding-right: 11px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed .purechat-widget-header .purechat-menu.purechat-btn-toolbar,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed .purechat-widget-header .purechat-menu.purechat-btn-toolbar {\n  min-height: 40px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed .purechat-widget-header .purechat-btn,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed .purechat-widget-header .purechat-btn {\n  padding: 7px 7px 6px 7px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed .purechat-widget-header .purechat-widget-title,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed .purechat-widget-header .purechat-widget-title {\n  margin-left: -8px !important;\n  margin-bottom: -8px !important;\n  margin-top: -8px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed .purechat-widget-header .purechat-widget-title-link,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed .purechat-widget-header .purechat-widget-title-link {\n  padding-bottom: 18px !important;\n  padding-left: 17px !important;\n  padding-top: 19px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-collapsed.purechat-top .purechat-badge {\n  bottom: -12px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-bottom {\n  bottom: -54px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-bottom .purechat-btn-collapse {\n  bottom: 46px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-top {\n  top: -54px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-top .purechat-btn-collapse {\n  top: 50px !important;\n  bottom: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-super-collapsed.purechat-invisible .purechat-btn-collapse {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded {\n  left: 0 !important;\n  right: 0 !important;\n  top: auto !important;\n/* Take up entire window if in the chatting state */\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-style-classic {\n  box-sizing: border-box !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded .purechat-content-wrapper,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded .purechat-footer {\n  border-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive {\n  bottom: 0 !important;\n  height: calc(100% - 24px) !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-expanded,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-expanded,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-collapsed-outer,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-collapsed-outer,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-widget-inner,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-widget-inner,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-widget-content-wrapper,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-widget-content-wrapper,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-window-content.purechat-content,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-window-content.purechat-content,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-message-list-view,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-message-list-view,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-messages,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-messages,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-message-display-container,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-message-display-container {\n  height: 100% !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-message-display-container,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-message-display-container,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-start-chat-formauto,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-start-chat-formauto,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-start-chat-formauto .purechat-widget-content.purechat-mobile,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-start-chat-formauto .purechat-widget-content.purechat-mobile {\n  display: flex !important;\n  flex-grow: 1 !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-start-chat-formauto .purechat-widget-content.purechat-mobile,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-start-chat-formauto .purechat-widget-content.purechat-mobile {\n  flex-direction: column !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-content-wrapper,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-content-wrapper {\n  height: calc(100% - 35px) !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-chatting .purechat-message-display-container,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded.purechat-state-inactive .purechat-message-display-container {\n  min-height: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-widget-expanded .purechat-window-content.purechat-content .purechat-widget-content {\n  width: 100% !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget .purechat-card {\n  overflow-y: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image .purechat-message-display-container {\n  height: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image .purechat-collapsed-image {\n  background-size: contain !important;\n  background-repeat: no-repeat !important;\n  background-position: center center !important;\n  display: block !important;\n  height: 75px !important;\n  position: absolute !important;\n  width: 75px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-super-collapsed.purechat-top-right .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed.purechat-top-right .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-super-collapsed.purechat-bottom-right .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed.purechat-bottom-right .purechat-collapsed-image {\n  right: 8px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-super-collapsed.purechat-top-left .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed.purechat-top-left .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-super-collapsed.purechat-bottom-left .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed.purechat-bottom-left .purechat-collapsed-image {\n  left: 8px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-super-collapsed.purechat-has-image .purechat-btn-collapse,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed.purechat-has-image .purechat-btn-collapse {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-super-collapsed.purechat-top .purechat-badge,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed.purechat-top .purechat-badge {\n  bottom: -12px !important;\n  top: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed.purechat-bottom {\n  bottom: 10px !important;\n  left: 10px !important;\n  right: 10px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-has-image.purechat-widget-collapsed .purechat-collapsed-image {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image .purechat-collapsed-image {\n  bottom: -2px !important;\n  height: 75px !important;\n  left: auto !important;\n  position: absolute !important;\n  transform: none !important;\n  right: 8px !important;\n  width: 75px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image .purechat-collapsed-image .purechat-missed-message-count {\n  top: 0 !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-top .purechat-collapsed-image {\n  bottom: auto !important;\n  top: -2px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-top-left .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-bottom-left .purechat-collapsed-image {\n  left: 8px !important;\n  right: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-bottom .purechat-message-preview {\n  bottom: -5px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-top .purechat-message-preview {\n  top: -5px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-super-collapsed.purechat-top .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-collapsed.purechat-top .purechat-collapsed-image {\n  top: -2px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-super-collapsed.purechat-top .purechat-badge,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-collapsed.purechat-top .purechat-badge {\n  bottom: 8px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-super-collapsed.purechat-bottom .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-collapsed.purechat-bottom .purechat-collapsed-image {\n  bottom: -2px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-super-collapsed .purechat-collapsed-image,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-collapsed .purechat-collapsed-image {\n  display: block !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-super-collapsed .purechat-start-chat .purechat-badge {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-super-collapsed .purechat-widget-header .purechat-menu.purechat-btn-toolbar {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-super-collapsed .purechat-widget-header .purechat-widget-title {\n  display: none !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-collapsed.purechat-bottom {\n  bottom: 10px !important;\n  left: 10px !important;\n  right: 10px !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-expanded {\n  left: 0 !important;\n  right: 0 !important;\n  top: auto !important;\n}\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-expanded .purechat-content-wrapper,\n#PureChatWidget.purechat.purechat-popped-out-widget.purechat-image-only.purechat-has-image.purechat-widget-expanded .purechat-footer {\n  border-radius: 0 !important;\n}\n#PureChatWidget.purechat.purechat-button-available,\n#PureChatWidget.purechat.purechat-button-unavailable {\n  padding: 0 !important;\n}\n#PureChatWidget.purechat img.emoji {\n  display: inline-block !important;\n  height: 1em !important;\n  margin: 0 0.05em 0 0.1em !important;\n  vertical-align: -0.1em !important;\n  width: 1em !important;\n}\n#PureChatWidget.purechat .purechat-emoji-button img.emoji {\n  height: 18px !important;\n  width: 18px !important;\n}\n#PureChatWidget.purechat .purechat-message .twitter-tweet {\n  display: none !important;\n}\n#PureChatWidget.purechat .purechat-message .twitter-tweet.twitter-tweet-rendered {\n  display: block !important;\n}\n#PureChatWidget.purechat .purechat-message .twitter-tweet.twitter-tweet-rendered + script + .purechat-loading {\n  display: none !important;\n}\n[dir=\"rtl\"] #PureChatWidget.purechat .purechat-widget-header .purechat-btn {\n  margin-left: 0px !important;\n  margin-right: 9px !important;\n}\n[dir=\"rtl\"] #PureChatWidget.purechat .purechat-collapsed .purechat-widget-header .purechat-btn {\n  margin-right: 5px !important;\n}\n[dir=\"rtl\"] #PureChatWidget.purechat .purechat-widget-title-link {\n  padding-left: 0px !important;\n  padding-right: 7px !important;\n}\n[dir=\"rtl\"] #PureChatWidget.purechat .purechat-poweredby,\n[dir=\"rtl\"] #PureChatWidget.purechat .doop__purechat-poweredby___3MzyS {\n  text-align: left !important;\n}\n[dir=\"rtl\"] #PureChatWidget.purechat .purechat-unfurl-favicon {\n  max-width: 100% !important;\n  margin-left: 6px !important;\n  margin-right: 0 !important;\n}\n[dir=\"rtl\"] #PureChatWidget.purechat .purechat-unfurl-link .purechat-unfurl-link-container {\n  text-align: left !important;\n}\n[dir=\"rtl\"] #PureChatWidget.purechat .purechat-unfurl-link .purechat-unfurl-media {\n  margin-left: 10px !important;\n  margin-right: 0 !important;\n}\n", ""]);

// exports
exports.locals = {
	"purechat-poweredby-container": "doop__purechat-poweredby-container___18Yqr",
	"purechat-poweredby": "doop__purechat-poweredby___3MzyS",
	"purechat-poweredby-text": "doop__purechat-poweredby-text___wnkQ_",
	"purechat-poweredby-link": "doop__purechat-poweredby-link___1e9as"
};module.exports = __webpack_require__.p + "Baby-Chicks.2e1584e1166c06b09f70.png";module.exports = __webpack_require__.p + "Baby-Otter.f50a71e0bf0cf6020795.png";module.exports = __webpack_require__.p + "Baby-Panda.9999869ff088eeb6788c.png";module.exports = __webpack_require__.p + "Bunny.baa327a9480ab3caff9f.png";module.exports = __webpack_require__.p + "Kitten.3664ab124de3af1cae0b.png";module.exports = __webpack_require__.p + "Puppy.c80bf1f5f5d5870fc0f3.png";module.exports = __webpack_require__.p + "Black-LiveChat-Bubble.01f25863746c218f9ad2.png";module.exports = __webpack_require__.p + "Blue-LiveChat-Bubble.e3258251b31dfd2aba56.png";module.exports = __webpack_require__.p + "chat-01.de1e2b5a199e84bf7c56.png";module.exports = __webpack_require__.p + "chinese.6084ba50f4a88dce7d39.png";module.exports = __webpack_require__.p + "Contact-01.26cbfe1f7fe916e186a5.png";module.exports = __webpack_require__.p + "email.3a5bee27873d147010ef.png";module.exports = __webpack_require__.p + "Female-Hello.2fe08465838e9d59a1e4.png";module.exports = __webpack_require__.p + "Female-Support2.02012942677aefd6933c.png";module.exports = __webpack_require__.p + "Female-Support.c2992c408baeb074b56f.png";module.exports = __webpack_require__.p + "Female-ThumbsUp.3d769dfd56677cd94459.png";module.exports = __webpack_require__.p + "french.8c96502a60fb9f958846.png";module.exports = __webpack_require__.p + "german.1f1a80eb30bb8445f41f.png";module.exports = __webpack_require__.p + "Global-01.2469d4726bb7a95eca6c.png";module.exports = __webpack_require__.p + "hello.ac280e23f8045df2f923.png";module.exports = __webpack_require__.p + "Info-01.6a32e4328c6e6120b1ba.png";module.exports = __webpack_require__.p + "italian.f0b97a60df8cb530cf38.png";module.exports = __webpack_require__.p + "japanese.1982203ce8e4308ed240.png";module.exports = __webpack_require__.p + "Male-Hello.6a683b8425315694bdc4.png";module.exports = __webpack_require__.p + "Male-Support2.b9d3244b0d750252be8d.png";module.exports = __webpack_require__.p + "Male-Support.f7e90892ecced395019d.png";module.exports = __webpack_require__.p + "Male-ThumbsUp.ff81642196786faad399.png";module.exports = __webpack_require__.p + "PC-Bubble.6aadc82953ab9ea31ee8.png";module.exports = __webpack_require__.p + "portugese.3b2b95d0ae5bdedfa9db.png";module.exports = __webpack_require__.p + "Red-LiveChat-Bubble.a4ad6b30018adf6410c5.png";module.exports = __webpack_require__.p + "romanian.e9bad4edf7ed0dc5bb52.png";module.exports = __webpack_require__.p + "russian.67146a38b196b537ce9f.png";module.exports = __webpack_require__.p + "snowman.51362f6d4875fdb2406e.png";module.exports = __webpack_require__.p + "spanish.c1fabaeb81f83ee3f3db.png";module.exports = __webpack_require__.p + "White-LiveChat-Bubble.913a13d4cf739e3964c1.png";module.exports = __webpack_require__.p + "black-chat-bubble.140bfd532eb4c330f5f1.png";module.exports = __webpack_require__.p + "black-circle-hi.27845211629f5dbb1bbf.png";module.exports = __webpack_require__.p + "black-decorative-pointer.d0106606e7bd4fb0e141.png";module.exports = __webpack_require__.p + "black-pointer.f8cf81062cdeed577834.png";module.exports = __webpack_require__.p + "blue-chat.c7c247e3dd6ab71587e4.png";module.exports = __webpack_require__.p + "blue-circle-hi.1432ae3e5c5185f33393.png";module.exports = __webpack_require__.p + "blue-decorative-pointer.d67b8268e2fb6f2954f5.png";module.exports = __webpack_require__.p + "blue-pin.c0ac54b050f9b975269d.png";module.exports = __webpack_require__.p + "bubbles-black.ad9e523d6088fdd1d0e3.png";module.exports = __webpack_require__.p + "bubbles-blue.b5448c542bc95c17c7a4.png";module.exports = __webpack_require__.p + "bubbles-teal.f74ba1fa8c0e9764ce03.png";module.exports = __webpack_require__.p + "bubbles-white.5f3b5beafc984f0b431c.png";module.exports = __webpack_require__.p + "bubble-white.5056fc05bea86b6e3d66.png";module.exports = __webpack_require__.p + "chat-with-us-tab.1652830788465918e7fc.png";module.exports = __webpack_require__.p + "green-pin.c8859c923282db90a299.png";module.exports = __webpack_require__.p + "green-tab.560e5226c78f59594607.png";module.exports = __webpack_require__.p + "navy-chat.f0d036ab99f585d67e89.png";module.exports = __webpack_require__.p + "red-chat-bubble.425c46d6538aff8814dc.png";module.exports = __webpack_require__.p + "red-circle-hi.ed1b785189bf84e84683.png";module.exports = __webpack_require__.p + "red-decorative-pointer.be476437f6c394c79c94.png";module.exports = __webpack_require__.p + "red-pin.84455e8d628c9dafbdf2.png";module.exports = __webpack_require__.p + "teal-chat-bubble.19bc9a709fe1a3d1029f.png";module.exports = __webpack_require__.p + "white-pointer.393e47f92f9d1ebe17b6.png";module.exports = __webpack_require__.p + "yellow-tab.a610a3fc26aa76452ef3.png";module.exports = __webpack_require__.p + "operator-person-1.68594a7540559e7ec850.png";module.exports = __webpack_require__.p + "operator-person-2.1b1478de00627e85d88e.png";module.exports = __webpack_require__.p + "operator-tab.796705872aab8c95a4db.png";module.exports = __webpack_require__.p + "support-circle-grey.4d2f2dff018180ce6e33.png";module.exports = __webpack_require__.p + "support-circle-white.b3b64c2d7e7c5ef9aa80.png";module.exports = __webpack_require__.p + "CS-F-01.b27a6ce4e9600d13be1a.png";module.exports = __webpack_require__.p + "CS-G-01.6c29c20e016e15fd3ce2.png";module.exports = __webpack_require__.p + "CS-M-01.37c6f9119b43eab4d9e3.png";__webpack_require__.r(__webpack_exports__);
/* harmony import */ var legacy_widget_main_dashboard__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(751);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
/* harmony import */ var config__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(config__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var widget_shared_url__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(310);




var query = Object(widget_shared_url__WEBPACK_IMPORTED_MODULE_3__[/* queryStringToObject */ "b"])();
var preview = query.live_preview && (query.live_preview === '1' || query.live_preview === 'true');

function NewPcWidget(connectionSettings, widgetSettings) {
  var dataServiceOptions = {
    test: false,
    widgetId: connectionSettings.widgetId || connectionSettings.c,
    connectionSettings: connectionSettings,
    isWidget: connectionSettings.isWidget || connectionSettings.f,
    isOperator: connectionSettings.d === undefined ? false : connectionSettings.d,
    pureServerUrl: connectionSettings.pureServerUrl,
    cdnServerUrl: connectionSettings.cdnServerUrl,
    apiCdnServerUrl: connectionSettings.apiCdnServerUrl,
    apiServerUrl: connectionSettings.apiServerUrl,
    renderInto: jquery__WEBPACK_IMPORTED_MODULE_1___default()('.purechat-direct-container'),
    isDirectAccess: true,
    MobileDisplayType: 2 // Force MobileDisplayType to MobileOptmized even if the user selected somethign different

  };
  window.purechatApp.Services.DataServiceSingleton.setInstance(preview && window.parent.currentWidgetSettings ? new window.purechatApp.Services.DemoDataService(dataServiceOptions) : new window.purechatApp.Services.PCDataService(dataServiceOptions));
  var viewOptions = {
    test: false,
    pureServerUrl: connectionSettings.pureServerUrl,
    cdnServerUrl: connectionSettings.cdnServerUrl,
    apiServerUrl: connectionSettings.apiServerUrl,
    apiCdnServerUrl: connectionSettings.apiCdnServerUrl,
    widgetId: connectionSettings.widgetId || connectionSettings.c,
    isWidget: connectionSettings.isWidget || connectionSettings.f,
    isOperator: connectionSettings.d === undefined ? false : connectionSettings.d,
    renderInto: jquery__WEBPACK_IMPORTED_MODULE_1___default()('.purechat-direct-container'),
    isDirectAccess: true,
    dataController: window.purechatApp.Services.DataServiceSingleton.getInstance(),
    IPIsBanned: widgetSettings.IPIsBanned,
    BrowserDetails: widgetSettings.BrowserDetails,
    ChatBoxEnabled: widgetSettings.ChatBoxEnabled,
    VisitorTrackingEnabled: widgetSettings.VisitorTrackingEnabled,
    isDemo: preview,
    expanded: true,
    MobileDisplayType: 2 // Force MobileDisplayType to MobileOptmized even if the user selected somethign different

  };
  var c1 = new window.purechatApp.Controllers.PureChatController(new window.purechatApp.Models.WidgetSettings(viewOptions));
  window.purechatApp.Notifications.controller = new window.purechatApp.Notifications.Controller({
    settings: c1.options
  });
  return c1;
}

var w = new NewPcWidget({
  pureServerUrl: config__WEBPACK_IMPORTED_MODULE_2___default.a.dashboardRootUrl,
  cdnServerUrl: config__WEBPACK_IMPORTED_MODULE_2___default.a.cdnUrl,
  apiCdnServerUrl: config__WEBPACK_IMPORTED_MODULE_2___default.a.apiCdnServerUrl,
  apiServerUrl: config__WEBPACK_IMPORTED_MODULE_2___default.a.apiUrl,
  c: query.widgetId || window.widgetSettings.WidgetSettings.Id,
  f: true
}, window.widgetSettings); // eslint-disable-next-line no-underscore-dangle

window._pcwi = w;

function fixContentPositioning() {
  if (!w.options.get('RequestFromMobileDevice') && !parseInt(w.options.get('MobileDisplayType'), 10) > 0) {
    var headerHeight = jquery__WEBPACK_IMPORTED_MODULE_1___default()('.purechat-expanded .purechat-widget-header').outerHeight();
    jquery__WEBPACK_IMPORTED_MODULE_1___default()('.purechat-expanded .purechat-content').css({
      top: headerHeight
    });
  }
}

w.on('widget:ready', function () {
  var inRoomOnLoad = w.getDataController().checkInRoom() !== null && typeof w.getDataController().checkInRoom() !== 'undefined';
  w.widgetLayout.expand(true, inRoomOnLoad);
  fixContentPositioning();
  jquery__WEBPACK_IMPORTED_MODULE_1___default()('body').css({
    visibility: 'visible'
  });
});
jquery__WEBPACK_IMPORTED_MODULE_1___default()(window).on('resize.AdjustWidgetContent', fixContentPositioning);__webpack_require__.r(__webpack_exports__);

// EXTERNAL MODULE: ../node_modules/jquery/src/jquery.js
var jquery = __webpack_require__(0);
var jquery_default = /*#__PURE__*/__webpack_require__.n(jquery);

// EXTERNAL MODULE: ../node_modules/backbone-relational/backbone-relational.js
var backbone_relational = __webpack_require__(154);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/plugins/jquery.purechat_display.js
var jquery_purechat_display = __webpack_require__(638);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/plugins/jquery.purechat_css.js
var jquery_purechat_css = __webpack_require__(639);

// EXTERNAL MODULE: ./Scripts/config/config.production.js
var config_production = __webpack_require__(11);
var config_production_default = /*#__PURE__*/__webpack_require__.n(config_production);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/utils/logger.js
var logger = __webpack_require__(61);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/services/data_singleton.js
var data_singleton = __webpack_require__(116);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/services/pc_data.js + 1 modules
var pc_data = __webpack_require__(216);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/services/base_data.js + 1 modules
var base_data = __webpack_require__(319);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/constants.js
var constants = __webpack_require__(4);

// EXTERNAL MODULE: ./Content/images/avatars/visitor.png
var visitor = __webpack_require__(311);
var visitor_default = /*#__PURE__*/__webpack_require__.n(visitor);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/services/test_data.js
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }






var test_data_TestDataController =
/*#__PURE__*/
function (_BaseDataController) {
  _inherits(TestDataController, _BaseDataController);

  function TestDataController(options) {
    var _this;

    _classCallCheck(this, TestDataController);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(TestDataController).call(this, options));
    _this.chatAvailable = typeof _this.setDemoUnavailable === 'function' ? !_this.setDemoUnavailable() : true;
    return _this;
  }

  _createClass(TestDataController, [{
    key: "startChat",
    value: function startChat() {
      this.connectionInfo.set('userId', 1);
      this.connectionInfo.set('authToken', 'adsfasfdsdf');
      this.connectionInfo.set('roomId', 1);
      return jquery_default.a.Deferred().resolve(this.connectionInfo);
    }
  }, {
    key: "closeChat",
    value: function closeChat() {
      return jquery_default.a.Deferred().resolve();
    }
  }, {
    key: "getContactInfo",
    value: function getContactInfo() {
      var d = jquery_default.a.Deferred();
      setTimeout(function () {
        return d.resolve({
          firstName: '',
          lastName: '',
          company: '',
          email: '',
          phone: ''
        });
      }, 0);
      return d;
    }
  }, {
    key: "restartChat",
    value: function restartChat() {
      return jquery_default.a.Deferred().resolve();
    }
  }, {
    key: "connectToChatServer",
    value: function connectToChatServer(handler) {
      var d = jquery_default.a.Deferred();
      this.handler = handler;
      setTimeout(function () {
        return d.resolve();
      }, 0);
      return d;
    }
  }, {
    key: "sendRoomHistory",
    value: function sendRoomHistory() {
      /* Do Nothing for now */
    }
  }, {
    key: "checkInRoom",
    value: function checkInRoom() {
      return false;
    }
  }, {
    key: "newMessage",
    value: function newMessage(message) {
      var now = new Date();
      var hours = now.getHours();
      var minutes = now.getMinutes();
      var seconds = now.getSeconds();
      var pm = hours >= 12;
      hours = hours < 10 ? hours : hours == 12 ? hours : hours % 12;
      minutes = minutes < 10 ? '0' + minutes : minutes;
      seconds = seconds < 10 ? '0' + seconds : seconds;
      this.getOption('chatModel').get('messages').add({
        userId: now.getTime(),
        type: constants["a" /* default */].MessageTypes.Message,
        message: message,
        myMessage: true,
        userName: 'Aaron',
        time: hours + ':' + minutes + ' ' + seconds + (pm ? 'PM' : 'AM'),
        date: now,
        avatarUrl: visitor_default.a
      });
    }
  }, {
    key: "checkChatAvailable",
    value: function checkChatAvailable() {
      var _this2 = this;

      var d = jquery_default.a.Deferred();
      setTimeout(function () {
        return d.resolve({
          available: _this2.chatAvailable
        });
      }, 1);
      return d;
    }
  }, {
    key: "getWidgetSettings",
    value: function getWidgetSettings() {
      var widgetSettings = {
        'Version': 27288,
        'WidgetWording': {
          'Id': 721,
          'AccountId': 0,
          'Title': 'Chat with us test.'
        },
        'AccountId': 1,
        'Color': '000000',
        'Position': 2,
        'WidgetType': 1,
        'UnavailableBehavior': 2,
        'AskForRating': true,
        'AskForFirstName': true,
        'AskForLastName': true,
        'AskForEmail': false,
        'AskForCompany': true,
        'AskForQuestion': true,
        'ForcePopout': false,
        'StringResources': {
          'chat_identifyFailed': 'Failed to connect to PureChat!',
          'greeting': 'Hello',
          'closed_message': 'Thanks for chatting. Please rate how you feel about the chat session:',
          'closed_opMessage': 'This chat has ended.<br/>What would you like to do?',
          'chat_joinMessage': '{displayName} has joined the chat!',
          'placeholder_email': 'Email',
          'chat_connecting': 'Connecting you to the chat now...',
          'chat_nowChattingWith': 'Chatting with {chatUserNames}.',
          'label_pressToBegin': 'Press the button below to begin!',
          'error_enterEmail': 'Please enter an email address.',
          'closed_downloadTrans': 'Download chat transcript',
          'title_noOperators': 'No Operators Available',
          'error_enterQuestion': 'Please enter a question',
          'noOperators_email_message': 'There are currently no operators available, but feel free to send us an email!',
          'poweredby': 'Powered by',
          'chat_noOperatorMessage': "An operator has not yet connected. Don't worry, an operator will be by shortly! When they connect, they'll see all the messages you've sent so far.",
          'chat_typing': '{displayName} is typing',
          'title_chatClosed': 'Chat Closed',
          'closed_ratingThanks': 'Thanks for your rating!',
          'placeholder_name': 'Name',
          'placeholder_firstName': 'First Name',
          'placeholder_lastName': 'Last Name',
          'placeholder_comapny': 'Company',
          'title_initial': 'Chat with us test.',
          'title_unavailable_initial': 'Contact Us',
          'placeholder_question': 'Enter your Question',
          'label_initial_label': 'Introductory Text',
          'title_initial_label': 'Widget Title',
          'error_noOperators': 'Sorry, no operators are currently available',
          'label_initial': 'Enter your info below to begin.',
          'error_noOperators_label': 'No Operators Available',
          'button_startChat': 'Send Chat Request',
          'label_initial_helptext': 'This is the introductory text that will be displayed after the user clicks on the PureChat widget.',
          'button_sendEmail': 'Send Email',
          'chat_startedMessage': 'An operator will be right with you! Feel free to hide this box and navigate around the site.',
          'chat_leftMessage': '{displayName} has left the chat!',
          'chat_connectionFailed': 'Failed to connect to PureChat!',
          'button_startNewChat': 'Start a new chat',
          'error_noOperators_helptext': 'This is the message that will be displayed when Hide Widget When Unavailable is unchecked, and there are no operators available.',
          'error_enterName': 'Please enter a name.',
          'mobile_title_initial': 'Chat',
          'mobile_title_unavailable_initial': 'Contact'
        },
        'GoogId': 'UA-XXXX-Y',
        'GaTrackingTab': false,
        'GaTrackingChat': false,
        'GaTrackingThumbs': false,
        'GATabEvent': 'Tab Opened',
        'GAChatEvent': 'Chat Started',
        'GAUpThumbEvent': 'Thumbs Up',
        'GADownThumbEvent': 'Thumbs Down',
        'GAEventCategory': 'PureChat widget',
        'UsingGa': false,
        'ChatServerUrl': 'http://chad.purechat.com:8000',
        'DisplayWidgetAnimation': 'bounceInDown',
        'CollapsedWidgetImageUrl': 'http://chad.purechat.com/Content/images/widgetSamples/operator1.png'
      };
      return jquery_default.a.Deferred().resolve(widgetSettings);
    }
  }, {
    key: "rateChat",
    value: function rateChat() {
      var d = jquery_default.a.Deferred();
      return d.resolve();
    }
  }, {
    key: "setTypingIndicator",
    value: function setTypingIndicator() {}
  }, {
    key: "bindEvents",
    value: function bindEvents(handler) {
      this.handler = handler;
    }
  }]);

  return TestDataController;
}(base_data["a" /* default */]);

/* harmony default export */ var test_data = (test_data_TestDataController);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// EXTERNAL MODULE: ./Scripts/widgets/shared/url.js
var shared_url = __webpack_require__(310);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/utils/index.js + 2 modules
var utils = __webpack_require__(15);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/utils/spinner.js
function spinner_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function spinner_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function spinner_createClass(Constructor, protoProps, staticProps) { if (protoProps) spinner_defineProperties(Constructor.prototype, protoProps); if (staticProps) spinner_defineProperties(Constructor, staticProps); return Constructor; }




function supportsMask() {
  return window.CSS && no_conflict["c" /* _ */].isFunction(window.CSS.supports) && window.CSS.supports('mask', 'none');
}

function supportsSVGAnimation() {
  // Stolen from Modernizr's check for this very thing. (https://modernizr.com/download?setclasses&q=svg)
  var toString = {}.toString;
  return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS('http://www.w3.org/2000/svg', 'animate')));
}

var WidgetSpinnerView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: no_conflict["c" /* _ */].template(''),
  className: 'purechat-progress-spinner',
  onRender: function onRender() {
    var overlay = this.getOption('overlay') || true;
    if (overlay) this.$el.addClass('purechat-progress-spinner-overlay');
  }
});

var spinner_WidgetSpinner =
/*#__PURE__*/
function () {
  function WidgetSpinner() {
    spinner_classCallCheck(this, WidgetSpinner);
  }

  spinner_createClass(WidgetSpinner, [{
    key: "show",
    value: function show(element) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      if (!element || !jquery_default()(element).length) throw new Error('No jquery element provided when creating a circle spinner!');
      var _options$preventInter = options.preventInteraction,
          preventInteraction = _options$preventInter === void 0 ? true : _options$preventInter;
      if (element.data('progress-spinner')) return;
      var view = new WidgetSpinnerView({
        overlay: preventInteraction
      });
      view.render();
      if (!supportsMask()) view.$el.addClass('purechat-progress-spinner-compat');
      if (!supportsSVGAnimation()) view.$el.addClass('purechat-animate-spin');
      view.$el.appendTo(element);
      element.addClass('purechat-progress-spinner-container').data('progress-spinner', view);

      if (preventInteraction) {
        jquery_default()(element).on('keydown.circle-spinner', function () {
          return false;
        }).on('click.circle-spinner', function () {
          return false;
        });
      }
    }
  }, {
    key: "hide",
    value: function hide(element) {
      if (!element || !jquery_default()(element).length) throw new Error('No jquery element provided when creating a circle spinner!');
      var view = element.data('progress-spinner');

      if (view) {
        view.destroy();
        element.removeData('progress-spinner').removeClass('purechat-progress-spinner-container');
        element.off('.circle-spinner');
      }
    }
  }]);

  return WidgetSpinner;
}();

var instance = new spinner_WidgetSpinner();
/* harmony default export */ var spinner = ({
  getInstance: function getInstance() {
    return instance;
  },
  show: instance.show.bind(instance),
  hide: instance.hide.bind(instance)
});
// CONCATENATED MODULE: ./Scripts/widgets/legacy/app.js

 // Perform checks to make sure the widget can load

try {
  localStorage.setItem('_purechatLocalStorageAccess', true);
} catch (ex) {
  throw new Error('Local storage access is not allowed. This is a problem with some browsers running private windows.');
}

no_conflict["a" /* Backbone */].View.prototype.getResource = function (key, data) {
  return no_conflict["b" /* Marionette */].getOption(this, 'rm').getResource(key, no_conflict["c" /* _ */].defaults(data || {}, {
    chatUserNames: ''
  }));
};

no_conflict["b" /* Marionette */].View.prototype.mixinTemplateHelpers = function (target) {
  var templateHelpers = this.templateHelpers || {};
  target = target || {};
  if (no_conflict["c" /* _ */].isFunction(templateHelpers)) templateHelpers = templateHelpers.call(this);
  target.getResource = no_conflict["c" /* _ */].bind(no_conflict["a" /* Backbone */].View.prototype.getResource, this);
  return no_conflict["c" /* _ */].extend(target, templateHelpers, {
    Utils: utils["a" /* default */]
  });
};

var purechatApp = new no_conflict["b" /* Marionette */].Application();
no_conflict["a" /* Backbone */].Relational.showWarnings = false;
purechatApp.events = no_conflict["c" /* _ */].extend({}, no_conflict["a" /* Backbone */].Events);
/* harmony default export */ var app = (purechatApp);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/Widget.html
var Widget = __webpack_require__(606);
var Widget_default = /*#__PURE__*/__webpack_require__.n(Widget);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/WidgetDirectAccess.html
var WidgetDirectAccess = __webpack_require__(607);
var WidgetDirectAccess_default = /*#__PURE__*/__webpack_require__.n(WidgetDirectAccess);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/WidgetOperator.html
var WidgetOperator = __webpack_require__(652);
var WidgetOperator_default = /*#__PURE__*/__webpack_require__.n(WidgetOperator);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/WidgetPoppedOut.html
var WidgetPoppedOut = __webpack_require__(653);
var WidgetPoppedOut_default = /*#__PURE__*/__webpack_require__.n(WidgetPoppedOut);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/icons.html
var icons = __webpack_require__(654);
var icons_default = /*#__PURE__*/__webpack_require__.n(icons);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/address.view.js



var AddressView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: no_conflict["c" /* _ */].template("\n\t\t<% if (obj.ShowGoogleMap) { %>\n\t\t<iframe src=\"<%= obj.getEmbedUrl() %>\"></iframe>\n\t\t<% } %>\n\t\t<a href=\"<%= obj.getMapsUrl() %>\" target=\"_blank\"><%= obj.sanitizeAddress() %></a>\n\t"),
  className: 'purechat-flyout-address',
  templateHelpers: function templateHelpers() {
    var _this = this;

    return {
      sanitizeAddress: function sanitizeAddress() {
        return (_this.model.get('Address') || '').replace(/(\r\n|\n)/g, '<br/>');
      },
      getMapsUrl: function getMapsUrl() {
        return "https://maps.google.com/?q=".concat(window.encodeURIComponent(_this.model.get('Address')));
      },
      getEmbedUrl: function getEmbedUrl() {
        var root = "https://www.google.com/maps/embed/v1/place?key=".concat(config_production_default.a.googleEmbedApiKey);
        return "".concat(root, "&q=").concat(window.encodeURIComponent(_this.model.get('Address')));
      }
    };
  }
});
/* harmony default export */ var address_view = (AddressView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/text.view.js

var TextView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: no_conflict["c" /* _ */].template('<%= obj.getText() %>'),
  className: 'purechat-truncate',
  templateHelpers: function templateHelpers() {
    var _this = this;

    return {
      getText: function getText() {
        var text = _this.getOption('text');

        var substitution = _this.getOption('substitution');

        if (!text) return '';

        if (substitution) {
          var regex = new RegExp('{([^}]*)}', 'g');
          return text.replace(regex, substitution);
        }

        return text;
      }
    };
  }
});
/* harmony default export */ var text_view = (TextView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/twitter.view.js



var TWITTER_WIDGET_COUNT = 3;
var TwitterView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: no_conflict["c" /* _ */].template("\n\t\t<div class=\"purechat-flyout-twitter-feed\">\n\t\t\t<a class=\"twitter-timeline\" data-height=\"312\" href=\"https://twitter.com/<%= obj.TwitterHandle %>\" data-chrome=\"nofooter\">Tweets by <%= obj.TwitterHandle %></a>\n\t\t</div>\n\t\t<div class=\"purechat-flyout-twitter-buttons\">\n\t\t\t<div><a href=\"https://twitter.com/intent/tweet?screen_name=<%= obj.TwitterHandle %>\" class=\"twitter-mention-button\" data-related=\"<%= obj.TwitterHandle %>\" data-size=\"small\">Tweet to @<%= obj.TwitterHandle %></a></div>\n\t\t\t<div><a href=\"https://twitter.com/<%= obj.TwitterHandle %>\" class=\"twitter-follow-button\" data-show-count=\"false\" data-size=\"small\">Follow @<%= obj.TwitterHandle %></a></div>\n\t\t</div>\n\t"),
  className: 'purechat-flyout-twitter',
  loadScript: function loadScript() {
    var _this = this;

    var dfr = jquery_default.a.Deferred();
    var scriptDeferred = jquery_default.a.Deferred();
    if (this.scriptReady || !this.model.get('TwitterHandle')) return dfr.resolve(); // Insert Twitter script into page. This chunk of code came from Twitter

    window.twttr = function (d, s, id) {
      var js,
          fjs = d.getElementsByTagName(s)[0],
          t = window.twttr || {};
      if (d.getElementById(id)) return t;
      js = d.createElement(s);
      js.id = id;
      js.src = 'https://platform.twitter.com/widgets.js';

      js.onload = js.onreadystatechange = function () {
        scriptDeferred.resolve();
      };

      fjs.parentNode.insertBefore(js, fjs);
      t._e = [];

      t.ready = function (f) {
        t._e.push(f);
      };

      return t;
    }(document, 'script', 'purechat-twitter-wjs');

    scriptDeferred.done(function () {
      var done = no_conflict["c" /* _ */].after(TWITTER_WIDGET_COUNT, function () {
        _this.scriptReady = true;
        dfr.resolve();
      });

      var createWidgets = function createWidgets(twttr) {
        twttr.events.bind('rendered', function (e) {
          if (_this.$el.has(e.target).length > 0) {
            setTimeout(function () {
              var styles = e.target.getAttribute('style');
              var importantStyles = styles.replace(/;/g, ' !important;');
              e.target.setAttribute('style', importantStyles);
              done();
            }, 1);
          }
        });
        twttr.widgets.load(_this.$el.get(0));
      };

      if (window.twttr && window.twttr.widgets && window.twttr.widgets.load) {
        createWidgets(window.twttr);
      } else {
        window.twttr.ready(createWidgets);
      }
    });
    return dfr.promise();
  },
  onDestroy: function onDestroy() {
    // Remove the Twitter script on destroy
    var script = document.getElementById('purechat-twitter-wjs');
    if (script) script.parentNode.removeChild(script);
  }
});
/* harmony default export */ var twitter_view = (TwitterView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/EmailForm.html
var EmailForm = __webpack_require__(655);
var EmailForm_default = /*#__PURE__*/__webpack_require__.n(EmailForm);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/email_form.view.js




var SUBMIT_DELAY = 500;
var EmailFormView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: EmailForm_default.a,
  className: 'purechat-email-form purechat-card',
  ui: {
    form: '.purechat-form',
    userDisplayName: '.purechat-name-input',
    userDisplayFirstName: '.purechat-firstname-input',
    userDisplayLastName: '.purechat-lastname-input',
    userDisplayCompany: '.purechat-company-input',
    email: '.purechat-email-input',
    question: '.purechat-question-input',
    userDisplayNameError: '.please-entername',
    emailError: '.please-enteremail',
    questionError: '.please-enterquestion',
    phoneNumber: '.purechat-phonenumber-input',
    unavailablePhoneNumber: '.purechat-unavailablephone-input',
    phoneNumberError: '.please-enterphonenumber',
    unavailablePhoneError: '.please-enterunavailablephone',
    userDisplayFirstNameError: '.please-enterfirstname',
    userDisplayLastNameError: '.please-enterlastname',
    userDisplayCompanyError: '.please-entercompany',
    error: '.purechat-email-error'
  },
  templateHelpers: function templateHelpers() {
    var _this = this;

    return no_conflict["c" /* _ */].extend({
      getMessage: function getMessage() {
        return jquery_default()('<div/>').html(_this.model.get('InitialVisitorQuestion')).text().replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
      }
    }, this.options.settings);
  },
  events: {
    'submit form': 'submitEmailForm',
    'change @ui.userDisplayFirstName': 'triggerFirstNameChange',
    'change @ui.userDisplayLastName': 'triggerLastNameChange',
    'change @ui.userCompany': 'triggerCompanyChange',
    'change @ui.email': 'triggerEmailChange',
    'change @ui.question': 'triggerQuestionChange',
    'change @ui.phoneNumber': 'triggerPhoneNumberChange'
  },
  modelEvents: {
    change: 'render'
  },
  error: function error() {
    this.ui.error.purechatDisplay();
  },
  triggerFirstNameChange: function triggerFirstNameChange() {
    var userDisplayFirstName = jquery_default.a.trim(this.ui.userDisplayFirstName.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorFirstName', userDisplayFirstName, {
      silent: true
    });
  },
  triggerLastNameChange: function triggerLastNameChange() {
    var userDisplayLastName = jquery_default.a.trim(this.ui.userDisplayLastName.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorLastName', userDisplayLastName, {
      silent: true
    });
  },
  triggerCompanyChange: function triggerCompanyChange() {
    var userDisplayCompany = jquery_default.a.trim(this.ui.userDisplayCompany.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorCompany', userDisplayCompany, {
      silent: true
    });
  },
  triggerEmailChange: function triggerEmailChange() {
    var userEmail = jquery_default.a.trim(this.ui.email.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorEmail', userEmail, {
      silent: true
    });
  },
  triggerPhoneNumberChange: function triggerPhoneNumberChange() {
    var phoneNumberVal = jquery_default.a.trim(this.ui.phoneNumber.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorPhoneNumber', phoneNumberVal, {
      silent: true
    });
  },
  triggerQuestionChange: function triggerQuestionChange() {
    var initialQuestion = this.ui.question.val();
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorQuestion', initialQuestion, {
      silent: true
    });
  },
  submitEmailForm: function submitEmailForm(e) {
    var _this2 = this;

    e.preventDefault();
    if (this.submitDelay) return false;
    this.submitDelay = true;
    setTimeout(function () {
      delete _this2.submitDelay;
    }, SUBMIT_DELAY);
    var askForFirstName = this.options.settings.get('EmailFormAskForFirstName');
    var askForLastName = this.options.settings.get('EmailFormAskForLastName');
    var askForPhoneNumber = this.options.settings.get('EmailFormAskForPhoneNumber');
    var askForCompany = this.options.settings.get('EmailFormAskForCompany');
    var userDisplayName = null;
    var userDisplayFirstName = askForFirstName ? jquery_default.a.trim(this.ui.userDisplayFirstName.val()) : null;
    var userDisplayLastName = askForLastName ? jquery_default.a.trim(this.ui.userDisplayLastName.val()) : null;
    var userDisplayCompany = askForCompany ? jquery_default.a.trim(this.ui.userDisplayCompany.val()) : null;
    var userEmail = this.ui.email.val();
    var initialQuestion = this.ui.question.val();
    this.ui.form.find('[class*="please"]').purechatDisplay('none');

    if (typeof userDisplayFirstName === 'string' && userDisplayFirstName.length === 0 && this.options.settings.get('RequireFirstName')) {
      this.ui.userDisplayFirstNameError.purechatDisplay('block');
      this.options.viewController.triggerResizedEvent();
      return false;
    }

    if (typeof userDisplayLastName === 'string' && userDisplayLastName.length === 0 && this.options.settings.get('RequireLastName')) {
      this.ui.userDisplayLastNameError.purechatDisplay('block');
      this.options.viewController.triggerResizedEvent();
      return false;
    }

    if (typeof userEmail === 'string' && userEmail.length === 0) {
      this.ui.emailError.purechatDisplay('block');
      this.options.viewController.triggerResizedEvent();
      return false;
    }

    if (typeof userDisplayCompany === 'string' && userDisplayCompany.length === 0 && this.options.settings.get('RequireCompany')) {
      this.ui.userDisplayCompanyError.purechatDisplay('block');
      this.options.viewController.triggerResizedEvent();
      return false;
    }

    var phoneNumberVal = this.ui.phoneNumber.val();

    if (askForPhoneNumber) {
      if (phoneNumberVal.length === 0 && this.options.settings.get('RequirePhoneNumber')) {
        this.ui.phoneNumberError.purechatDisplay('block');
        this.options.viewController.triggerResizedEvent();
        return false;
      }

      this.ui.phoneNumberError.purechatDisplay('none');
      this.options.viewController.triggerResizedEvent();
      this.ui.phoneNumber.val(phoneNumberVal);
    }

    if (initialQuestion === null || jquery_default.a.trim(initialQuestion) === '') {
      this.ui.questionError.purechatDisplay('block');
      this.options.viewController.triggerResizedEvent();
      return false;
    }

    userDisplayFirstName = userDisplayFirstName || this.options.viewController.getPublicApi().get('visitor_firstName') || this.model.get('InitialVisitorFirstName') || 'Visitor';
    userDisplayLastName = userDisplayLastName || this.options.viewController.getPublicApi().get('visitor_lastName') || this.model.get('InitialVisitorLastName');
    userDisplayCompany = userDisplayCompany || this.options.viewController.getPublicApi().get('visitor_company') || this.model.get('InitialVisitorCompany');
    userEmail = userEmail || this.options.viewController.getPublicApi().get('visitor_email') || this.model.get('InitialVisitorEmail');
    initialQuestion = initialQuestion || this.options.viewController.getPublicApi().get('visitor_question') || this.model.get('InitialVisitorQuestion');
    phoneNumberVal = phoneNumberVal || this.options.viewController.getPublicApi().get('visitor_phonenumber') || this.model.get('InitialVisitorPhoneNumber');

    if (userDisplayFirstName) {
      userDisplayName = userDisplayFirstName;
      if (userDisplayLastName) userDisplayName += userDisplayLastName;
    } else if (userDisplayLastName) {
      userDisplayName = userDisplayLastName;
    } else {
      userDisplayName = 'Visitor';
      userDisplayFirstName = 'Visitor';
    }

    this.model.set({
      Name: userDisplayName,
      FirstName: userDisplayFirstName,
      LastName: userDisplayLastName,
      Company: userDisplayCompany,
      Email: userEmail,
      Question: initialQuestion,
      PhoneNumber: phoneNumberVal
    });
    this.model.trigger('formSubmit', {
      visitorName: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayName || ''), true),
      visitorFirstName: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayFirstName || ''), true),
      visitorLastName: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayLastName || ''), true),
      visitorCompany: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayCompany || ''), true),
      visitorEmail: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userEmail || ''), true),
      visitorQuestion: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(initialQuestion || ''), false),
      visitorPhoneNumber: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(phoneNumberVal || ''), true)
    });
  }
});
/* harmony default export */ var email_form_view = (EmailFormView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/EmailSent.html
var EmailSent = __webpack_require__(656);
var EmailSent_default = /*#__PURE__*/__webpack_require__.n(EmailSent);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/email_sent.view.js


var EmailSentView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: EmailSent_default.a,
  templateHelpers: function templateHelpers() {
    var _this = this;

    return {
      getResource: function getResource(key) {
        return _this.getOption('rm').getResource(key);
      }
    };
  }
});
/* harmony default export */ var email_sent_view = (EmailSentView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/flyout.view.js










var HALFSIES = 0.5;
var FLYOUT_OFFSET = 20;
var BUTTON_LEFT_MARGIN = 5;
var ANIMATION_EVENTS = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
var ARROW_HALF_WIDTH = 11;
var FlyoutView = no_conflict["b" /* Marionette */].LayoutView.extend({
  currentViewId: null,
  template: no_conflict["c" /* _ */].template("\n        <div class=\"purechat-flyout-content\">\n            <div class=\"purechat-flyout-email-view\"></div>\n            <div class=\"purechat-flyout-phone-view\"></div>\n            <div class=\"purechat-flyout-twitter-view\"></div>\n            <div class=\"purechat-flyout-address-view\"></div>\n            <div class=\"purechat-flyout-arrow\"></div>\n        </div>\n    "),
  className: 'purechat-flyout purechat-animate purechat-animate-fast purechat-flyout-hide purechat-display-none',
  ui: {
    arrow: '.purechat-flyout-arrow'
  },
  regions: {
    email: '.purechat-flyout-email-view',
    phone: '.purechat-flyout-phone-view',
    twitter: '.purechat-flyout-twitter-view',
    address: '.purechat-flyout-address-view'
  },
  onRender: function onRender() {
    if (this.model.get('ShowEmailButton')) this.showChildView('email', this.getView('email'));
    if (this.model.get('ShowPhoneButton')) this.showChildView('phone', this.getView('phone'));
    if (this.model.get('ShowTwitterButton')) this.showChildView('twitter', this.getView('twitter'));
    if (this.model.get('ShowAddressButton')) this.showChildView('address', this.getView('address'));

    if (this.getOption('isTop')) {
      this.ui.arrow.addClass('purechat-flyout-arrow-top');
    } else {
      this.ui.arrow.addClass('purechat-flyout-arrow-bottom');
    }
  },
  showEmailView: function showEmailView(view, sender) {
    var _this = this;

    this.showChildView('email', view);
    this.showView('email', sender);
    view.model.on('formSubmit', function (data) {
      view.options.dataController.submitEmailForm(data).done(function (result) {
        if (result.success) {
          _this.showChildView('email', new email_sent_view({
            model: view.model,
            rm: _this.model
          }));

          _this.reposition(sender);

          view.options.viewController.trigger('email:send', data);
        } else {
          view.error();
        }
      });
    });
  },
  showView: function showView(id, sender) {
    var _this2 = this;

    if (this.currentViewId === id) {
      this.$el.on(ANIMATION_EVENTS, function () {
        _this2.$el.off(ANIMATION_EVENTS);

        _this2.$el.removeClass('purechat-animation-bounceUpSmall purechat-animation-bounceDownSmall');
      });
      var bounceClass = this.getOption('isTop') ? 'purechat-animation-bounceDownSmall' : 'purechat-animation-bounceUpSmall';
      this.$el.addClass(bounceClass);
    } else {
      this.hide().then(function () {
        _this2.regionManager.forEach(function (region) {
          return region.$el.purechatDisplay('none');
        });

        _this2.regionManager.get(id).$el.purechatDisplay();

        _this2.ui.arrow.purechatCss('left', '50%');

        _this2.currentViewId = id;

        _this2.$el.purechatDisplay();

        _this2.reposition(sender);

        if (_this2.$el.hasClass('purechat-flyout-hide')) {
          _this2.$el.on(ANIMATION_EVENTS, function () {
            _this2.$el.off(ANIMATION_EVENTS);

            _this2.$el.removeClass('purechat-flyout-show');
          });

          _this2.$el.removeClass('purechat-flyout-hide').addClass('purechat-flyout-show');
        }
      });
    }
  },
  getView: function getView(id) {
    var instanceName = "".concat(id, "View");
    if (this[instanceName]) return this[instanceName];
    this[instanceName] = this.createView(id);
    return this[instanceName];
  },
  createView: function createView(id) {
    var email = this.isEmailForm() ? new email_form_view({
      model: new no_conflict["a" /* Backbone */].Model(),
      settings: this.model
    }) : new text_view({
      text: this.model.get('EmailAddress'),
      substitution: '<a href="mailto:$1">$1</a>'
    });
    return {
      email: email,
      phone: new text_view({
        text: this.model.get('PhoneNumber'),
        substitution: '<a href="tel:$1">$1</a>'
      }),
      twitter: new twitter_view({
        model: this.model
      }),
      address: new address_view({
        model: this.model
      })
    }[id];
  },
  hide: function hide(immediate) {
    var _this3 = this;

    var def = jquery_default.a.Deferred();
    this.currentViewId = null;
    if (this.$el.hasClass('purechat-display-none')) return def.resolve();

    if (!immediate) {
      this.$el.on(ANIMATION_EVENTS, function () {
        _this3.$el.off(ANIMATION_EVENTS);

        _this3.$el.purechatCss({
          left: 'auto',
          right: 'auto'
        }); // Reset position


        _this3.$el.purechatDisplay('none');

        def.resolve();
      });
      this.$el.addClass('purechat-flyout-hide');
    } else {
      this.$el.addClass('purechat-flyout-hide').purechatDisplay('none');
      def.resolve();
    }

    return def;
  },
  setInitialPosition: function setInitialPosition() {
    var widgetElement = this.getOption('widgetElement');
    var widgetInnerHeight = widgetElement.innerHeight();
    var widgetOuterHeight = widgetElement.outerHeight();
    var borderHeight = (widgetOuterHeight - widgetInnerHeight) * HALFSIES;
    var flyoutPosition = widgetInnerHeight + borderHeight;

    if (this.getOption('isTop')) {
      this.$el.purechatCss('top', flyoutPosition + FLYOUT_OFFSET);
    } else {
      this.$el.purechatCss('bottom', flyoutPosition + FLYOUT_OFFSET);
    }
  },
  reposition: function reposition(sender) {
    this.reset();
    this.setInitialPosition();
    var isMobile = this.model.useMobile() && !this.model.isDesktopDimension();
    var widgetElement = this.getOption('widgetElement');
    var onRight = widgetElement.hasClass('purechat-bottom-right') || widgetElement.hasClass('purechat-top-right');
    var senderCenter = sender.position().left + sender.outerWidth() * HALFSIES;
    var flyoutLeft = senderCenter - this.$el.outerWidth() * HALFSIES;
    var flyoutRight = flyoutLeft + this.$el.outerWidth();
    var wideFlyouts = ['address', 'twitter', 'email'];
    var isWideFlyout = wideFlyouts.indexOf(this.currentViewId) > -1;
    var isEmailText = this.currentViewId === 'email' && !this.isEmailForm(); // Depending on what side of the screen the wigdet is, this is to make sure
    // the flyout doesn't go past the right/left of the widget. The flyout's position
    // is relative to the widget so this makes it pretty easy to figure out.
    // On mobile, expand the bigger flyouts to fill the whole width
    // of the screen.

    if (isMobile && isWideFlyout && !isEmailText) {
      this.$el.addClass('purechat-flyout-wide');
    } else if (onRight && flyoutRight > widgetElement.outerWidth()) {
      this.$el.purechatCss({
        right: 0,
        left: 'auto'
      });
    } else if (!onRight && flyoutLeft < widgetElement.position().left) {
      this.$el.purechatCss({
        right: 'auto',
        left: 0
      });
    } else {
      this.$el.purechatCss({
        left: "".concat(flyoutLeft + BUTTON_LEFT_MARGIN, "px")
      });
    }

    this.repositionArrow(sender);
  },
  repositionArrow: function repositionArrow(sender) {
    var senderOffset = sender.offset().left + sender.outerWidth() * HALFSIES;
    var arrowOffset = this.ui.arrow.offset().left;
    var delta = senderOffset - arrowOffset - ARROW_HALF_WIDTH;
    var arrowLeft = this.ui.arrow.position().left;
    this.ui.arrow.purechatCss('left', arrowLeft + delta);
  },
  reset: function reset() {
    this.$el.purechatCss('left', '');
    this.$el.purechatCss('right', '');
    this.$el.removeClass('purechat-flyout-wide');
  },
  isEmailForm: function isEmailForm() {
    return this.model.get('EmailButtonBehavior') === constants["a" /* default */].EmailButtonBehaviors.ShowEmailForm;
  }
});
/* harmony default export */ var flyout_view = (FlyoutView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/widget_layout.view.js













var IMMEDIATELY = 10;
var JUST_A_SEC = 1000;
var DEFAULT_DEBOUNCE = 50;
var widget_layout_view_ANIMATION_EVENTS = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
var AUTO_SUPER_MINIMIZE_TIMEOUT_MS = 6000;
var DEFAULT_IMAGE_SCALE = 100;
var IMAGE_SCALE_BASE = 100.0;
var IMAGE_BASE_ZINDEX = 9;
var ADDITIONAL_DETAILS_OFFSET = 200; // Maintain backward compatibility < 8.0.8 which added a 10 pixel offset

var LEGACY_IMAGE_OFFSET = 10; // The old widget was putting 60px of margin on the top of images
// if the widget was on top, this is to account for the extra space.

var LEGACY_TOPY_IMAGE_OFFSET = 24;
var widget_layout_view_notifier = new utils["a" /* default */].Notifier();
var WidgetLayout = no_conflict["b" /* Marionette */].LayoutView.extend({
  template: null,
  id: 'PureChatWidget',
  className: 'purechat purechat-display-none',
  optionsStepShown: false,
  maxWidth: 700,
  missedMessageCount: 0,
  _audioNotificationLocalStorageKey: '_purechatVisitorWidgetPlaySound',
  regions: {
    content: '.purechat-content',
    closedMessage: '.purechat-closed-content',
    flyout: '.purechat-flyout-container'
  },
  events: {
    'click [data-trigger]': 'executeCommand',
    mouseenter: 'peekWidget',
    mouseleave: 'unpeekWidget',
    'click .purechat-toggle-audio-notifications': 'updatePlayAudioLocalStorage',
    'click @ui.flyout': function clickUiFlyout(e) {
      return e.stopPropagation();
    },
    'dragover @ui.contentWrapper': 'showFileTransferOverlay',
    'dragenter @ui.contentWrapper': 'showFileTransferOverlay',
    'dragleave @ui.fileOverlay': 'hideFileTransferOverlay',
    'dragend @ui.fileOverlay': 'hideFileTransferOverlay',
    'drop @ui.fileOverlay': 'fileDropped'
  },
  childEvents: {
    roomHostChanged: function roomHostChanged(view, model) {
      this.showRoomHostAvatar(model.get('roomHostAvatarUrl'), model.get('expanded'));
    }
  },
  modelEvents: {
    'change:operatorsAvailable': 'operatorsAvailableChanged',
    'api:change': 'apiRoomDetailsChanged'
  },
  ui: {
    contentWrapper: '.purechat-content-wrapper',
    fileOverlay: '.purechat-file-overlay',
    content: '.purechat-content',
    purechatCollapsed: '.purechat-collapsed',
    collapsedTabWrapper: '.purechat-collapsed .purechat-collapsed-outer',
    title: '.purechat-expanded .purechat-widget-title-link',
    collapsedTitle: '.purechat-collapsed .purechat-widget-title-link',
    // This group of buttons are shown/hidden through PCWidgetState.UIVisiblity
    // block. Do not remove from ui.
    popoutButton: '[data-trigger="popOutChat"]',
    closeButton: '[data-trigger="closeChat"]',
    removeWidgetButton: '[data-trigger="removeWidget"]',
    restartButton: '[data-trigger="restartChat"]',
    requeueButton: '[data-trigger="requeueChat"]',
    leaveButton: '[data-trigger="leaveChat"]',
    // End PCWidget.UIVisiblity block of buttons
    widgetCollapsed: '.purechat-collapsed',
    widgetExpanded: '.purechat-expanded',
    collapseImage: '.purechat-collapsed-image',
    expandMobileButton: '.purechat-expand-mobile-button',
    roomAvatarUrl: '.purechat-widget-room-avatar',
    purechatTitleImage: '.purechat-title-image',
    superMinimizeButton: '.purechat-super-minimize-link-button',
    missedMessageCount: '.purechat-missed-message-count',
    footer: '.purechat-footer',
    flyout: '.purechat-flyout',
    messagePreview: '.purechat-collapsed .purechat-message-preview',
    messagePreviewText: '.purechat-collapsed .purechat-message-preview-text',
    emailFlyoutButton: '[data-trigger="showEmail"]',
    phoneFlyoutButton: '[data-trigger="showPhoneNumber"]',
    twitterFlyoutButton: '[data-trigger="showTwitter"]',
    addressFlyoutButton: '[data-trigger="showAddress"]'
  },
  templateHelpers: function templateHelpers() {
    var _this = this;

    var self = this;
    return jquery_default.a.extend({
      isDesktopDimension: function isDesktopDimension() {
        return self.options.viewController.isDesktopDimension();
      },
      MobileDisplayTypes: constants["a" /* default */].MobileDisplayTypes,
      localCssName: function localCssName(name) {
        var cssModules = no_conflict["b" /* Marionette */].getOption(this, 'cssModules') || {};
        return cssModules[name] || name;
      },
      icons: icons_default()(),
      // Rendered ejs-template
      showChatButton: function showChatButton() {
        return _this.getOperatorsAvailable();
      },
      isMobile: this.isMobile.bind(this),
      collapsedIconClass: function collapsedIconClass() {
        return _this.isMobile() ? 'pc-svgicon-lg' : 'pc-svgicon-md';
      },
      arrowClass: function arrowClass() {
        return _this.isTop() ? '#pc-svgicon-arrow-up' : '#pc-svgicon-arrow-down';
      },
      superMinimizeArrowClass: function superMinimizeArrowClass() {
        return _this.isTop() ? '#pc-svgicon-arrow-down' : '#pc-svgicon-arrow-up';
      },
      iconRootUrl: function iconRootUrl() {
        return utils["a" /* default */].iconRootUrl(_this.settings.get('isDemo'));
      },
      svgHrefAttr: function svgHrefAttr() {
        return utils["a" /* default */].svgHrefAttr();
      }
    }, this.settings);
  },
  setWidgetShown: function setWidgetShown() {
    window.sessionStorage.setItem('purechat_widgetShown', true);
  },
  widgetShown: function widgetShown() {
    return window.sessionStorage.getItem('purechat_widgetShown') === 'true';
  },
  apiRoomDetailsChanged: function apiRoomDetailsChanged(model, propertyName, newValue) {
    this.options.viewController.apiRoomDetailsChanged(model, propertyName, newValue);
  },
  updatePlayAudioLocalStorage: function updatePlayAudioLocalStorage(e) {
    var sender = jquery_default()(e.currentTarget);
    var icon = sender.find('.pc-svgicon use');
    var svgAttr = utils["a" /* default */].svgHrefAttr();

    if (icon.attr(svgAttr).indexOf('#pc-svgicon-sound') > -1) {
      window.localStorage[this._audioNotificationLocalStorageKey] = false;
      icon.attr(svgAttr, "".concat(window.location, "#pc-svgicon-no-sound"));
    } else {
      window.localStorage[this._audioNotificationLocalStorageKey] = true;
      icon.attr(svgAttr, "".concat(window.location, "#pc-svgicon-sound"));
    }

    return false;
  },
  clearRoomHostAvatar: function clearRoomHostAvatar() {
    this.ui.roomAvatarUrl.removeClass('purechat-has-room-avatar').removeAttr('style');
  },
  showRoomHostAvatar: function showRoomHostAvatar(url) {
    if (!url) return;
    this.ui.roomAvatarUrl.purechatCss({
      'background-image': 'url(' + url + ')'
    }).addClass('purechat-has-room-avatar');
  },
  toggleFooter: function toggleFooter() {
    if (!this.settings.get('RemoveBranding') && !this.settings.get('isOperator')) {
      this.ui.footer.purechatDisplay('flex');
    } else {
      this.ui.footer.purechatDisplay('none');
    }
  },
  hideFooter: function hideFooter() {
    if (this.settings.get('isOperator')) return;
    this.ui.footer.purechatDisplay('none');
  },
  showFooter: function showFooter() {
    if (this.settings.get('isOperator')) return;
    this.ui.footer.purechatDisplay('flex');
  },
  showSpinner: function showSpinner() {
    spinner.show(this.ui.content);
  },
  hideSpinner: function hideSpinner() {
    spinner.hide(this.ui.content);
  },
  bindAppCommands: function bindAppCommands() {
    try {
      app.events.off('footer:hide');
      app.events.off('footer:toggle');
      app.events.off('widget:spinner:show');
      app.events.off('widget:spinner:hide');
    } catch (ex) {
      /* Do Nothing */
    } finally {
      app.events.on('footer:show', this.showFooter, this);
      app.events.on('footer:hide', this.hideFooter, this);
      app.events.on('footer:toggle', this.toggleFooter, this);
      app.events.on('widget:spinner:show', this.showSpinner, this);
      app.events.on('widget:spinner:hide', this.hideSpinner, this);
    }
  },
  repositionWidget: function repositionWidget() {
    var positionClasses = {
      1: 'purechat-bottom purechat-bottom-left',
      2: 'purechat-bottom purechat-bottom-right',
      3: 'purechat-top purechat-top-left',
      4: 'purechat-top purechat-top-right',
      9999: 'purechat-widget-button'
    };

    for (var i in positionClasses) {
      this.$el.removeClass(positionClasses[i]);
    }

    if (this.isMobile()) {
      this.$el.addClass(positionClasses[this.settings.get('MobilePosition')]);
    } else if (!this.isPoppedOut() && !this.settings.get('isDirectAccess')) {
      if (this.settings.get('WidgetType') === constants["a" /* default */].WidgetType.Button) {
        this.$el.addClass(positionClasses['9999']);
      } else {
        this.$el.addClass(positionClasses[this.settings.get('Position')]);
      }
    }
  },
  chooseWidgetTemplate: function chooseWidgetTemplate() {
    var isMobile = this.settings.useMobile();

    if (this.settings.get('isDirectAccess') && isMobile) {
      this.template = WidgetDirectAccess_default.a;
      this.$el.addClass('purechat-widget purechat-popped-out-widget');
    } else if (this.settings.get('isDirectAccess')) {
      this.template = WidgetDirectAccess_default.a;
      this.$el.addClass('purechat-widget purechat-hosted-widget');
    } else if (this.settings.get('isOperator')) {
      this.template = WidgetOperator_default.a;
      this.$el.addClass('purechat-operator');
    } else if (this.settings.get('poppedOut')) {
      this.template = WidgetPoppedOut_default.a;
      this.$el.addClass('purechat-window purechat-popped-out-widget');
    } else if (isMobile && !this.settings.isDesktopDimension()) {
      // Need to add a special class that enhances everything for the widget for mobile button thing
      this.template = Widget_default.a;
      this.$el.addClass('purechat-window purechat-popped-out-widget purechat-not-clickable purechat-display-none');
    } else {
      this.template = Widget_default.a;
      this.$el.addClass('purechat-widget purechat-display-none');
    }

    if (this.settings.get('CollapsedStyle') === constants["a" /* default */].WidgetType.Button) {
      this.$el.addClass('purechat-custom-button');
    }
  },
  bindWidgetSettingsChanges: function bindWidgetSettingsChanges() {
    this.listenTo(this.settings, 'change', no_conflict["c" /* _ */].bind(this.updateImageTransform, this));
    this.listenTo(this.settings, 'change:AvailableImageXOffset', no_conflict["c" /* _ */].bind(this.updateImageTransform, this));
    this.listenTo(this.settings, 'change:AvailableImageYOffset', no_conflict["c" /* _ */].bind(this.updateImageTransform, this));
    this.listenTo(this.settings, 'change:UnavailableImageXOffset', no_conflict["c" /* _ */].bind(this.updateImageTransform, this));
    this.listenTo(this.settings, 'change:UnavailableImageYOffset', no_conflict["c" /* _ */].bind(this.updateImageTransform, this));
    this.listenTo(this.settings, 'change:Width', this.setCollapsedWidth.bind(this));
    this.listenTo(this.settings, 'change:visibleFlyoutId', this.toggleFlyoutPreview.bind(this));
  },
  getOperatorsAvailable: function getOperatorsAvailable() {
    return typeof this.model.get('operatorsAvailable') !== 'undefined' ? this.model.get('operatorsAvailable') : true;
  },
  updateCollapsedStyle: function updateCollapsedStyle() {
    var mobile = this.settings.useMobile() && !this.settings.isDesktopDimension();
    var operatorsAvailable = this.getOperatorsAvailable();
    var sameImageForBoth = this.options.widgetSettings.get(mobile ? 'MobileUseAvailableImageForBoth' : 'UseAvailableImageForBoth');
    var inChat = this.isInChat();
    var showAvailableImage = inChat || operatorsAvailable || sameImageForBoth;
    var imageUrl = mobile ? this.settings.mobileAbsoluteCollapsedImageUrl(showAvailableImage) : this.settings.absoluteCollapsedImageUrl(showAvailableImage);
    this.setCollapsedImage(showAvailableImage); // Default to true if the operatorsAvailable flag hasn't been updated yet, as the widget is probably still loading

    if (imageUrl) {
      this.$el.addClass('purechat-has-image');
      this.ui.collapseImage.purechatDisplay();
    } else {
      this.ui.collapseImage.purechatDisplay('none');
      this.$el.removeClass('purechat-has-image');
    }

    if (this.showTab()) {
      this.ui.collapsedTabWrapper.purechatDisplay('block');
    } else {
      this.ui.collapsedTabWrapper.purechatDisplay('none');
    }

    if (this.settings.get('CollapsedStyle') === constants["a" /* default */].WidgetType.Button) {
      jquery_default()('.purechat-button-expand').purechatCss('visibility', 'visible');
      this.ui.collapseImage.purechatDisplay('none');
    }

    if (this.isInChat() || operatorsAvailable) {
      this.$el.find('.purechat-start-chat').purechatDisplay();
    } else {
      this.$el.find('.purechat-start-chat').purechatDisplay('none');
    }

    if (this.isHiddenMobile() && !this.settings.anyButtonEnabled()) {
      this.$el.purechatDisplay('none');
    }
  },
  initialize: function initialize() {
    var _this2 = this;

    no_conflict["b" /* Marionette */].LayoutView.prototype.initialize.call(this);
    this.settings = no_conflict["b" /* Marionette */].getOption(this, 'widgetSettings');
    this.cssModules = no_conflict["b" /* Marionette */].getOption(this, 'cssModules');
    var isDemo = this.settings.get('isDemo');
    var isOperator = this.settings.get('isOperator');
    var forceMobileSuperMinimize = this.settings.get('forceMobileSuperMinimize');
    this.preventExternalEventPropagation();
    this.registerMobileInputFocusHandler();

    if (this.isImageOnly()) {
      this.$el.addClass('purechat-image-only');
    }

    this.autoSuperMinimize();

    if (isDemo && !forceMobileSuperMinimize) {
      this.model.set('superMinimize', false);
      window.localStorage.superMinimize = false;
    } else {
      this.model.set('superMinimize', this.isSuperMinimized());
    }

    this.chooseWidgetTemplate();
    this.repositionWidget();
    this.bindWidgetSettingsChanges();
    this.bindAppCommands();

    this.settings.showPlaySoundCheckbox = function () {
      return !isOperator && !_this2.settings.useMobile();
    };

    this.settings.playSoundOnNewMessage = function () {
      return (window.localStorage[_this2._audioNotificationLocalStorageKey] || 'false').toLowerCase() === 'true';
    };

    if (isOperator) {
      var PCWidgetStyles = document.getElementById('pcwidget-styles');
      if (PCWidgetStyles) PCWidgetStyles.parentNode.removeChild(PCWidgetStyles);
    }
  },
  preventExternalEventPropagation: function preventExternalEventPropagation() {
    var _this3 = this;

    if (!this.model.get('isOperator')) {
      var events = 'blur change click dblclick focus focusin focusout ' + 'hover keydown keypress keyup mousedown mouseenter mouseleave ' + 'mousemove mouseout mouseover mouseup resize scroll select ' + 'submit drag dragstart dragend dragover dragenter dragleave drop touchstart';
      this.$el.on(events, function (e) {
        e.stopPropagation();

        if (e.type === 'click') {
          _this3.getOption('viewController').trigger('widget:click', e);
        }
      });
    }
  },
  registerMobileInputFocusHandler: function registerMobileInputFocusHandler() {
    var _this4 = this;

    if (!this.isMobile()) return;
    jquery_default()(window).on('resize', function () {
      var activeElement = document.activeElement;
      var inputIsFocused = activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA';
      var isInWidget = _this4.$(activeElement).length > 0;

      if (inputIsFocused && isInWidget) {
        no_conflict["c" /* _ */].defer(function () {
          return document.activeElement.scrollIntoView();
        });
      }
    });
  },
  registerFlyoutCloseClickHandler: function registerFlyoutCloseClickHandler() {
    var _this5 = this;

    jquery_default()(window).on('mouseup.purechat-flyout', function () {
      var flyoutView = _this5.getRegion('flyout').currentView;

      if (!flyoutView) return;
      flyoutView.hide();

      var header = _this5.$el.find('.purechat-collapsed .purechat-widget-header');

      _this5.resetIcons(header);
    });
  },
  stringToBoolean: function stringToBoolean(str) {
    if (!str) return false;
    if (typeof str === 'string') return str.toLowerCase() === 'true';
    return str;
  },
  isSuperMinimized: function isSuperMinimized() {
    // Ignore 'superMinimize' if Image type
    return this.isImageOnly() || this.settings.get('isDemo') ? false : this.stringToBoolean(window.localStorage.superMinimize);
  },
  setTitle: function setTitle(title, resourceKey) {
    this.setCollapsedTitle(title, resourceKey);
    this.setExpandedTitle(title, resourceKey);
  },
  setCollapsedTitle: no_conflict["c" /* _ */].debounce(function (title, resourceKey) {
    this.ui.collapsedTitle // eslint-disable-line no-invalid-this
    .html(title).attr('data-resourcekey', resourceKey);
  }, DEFAULT_DEBOUNCE),
  setExpandedTitle: function setExpandedTitle(title, resourceKey) {
    this.ui.title.text(title).attr('data-resourcekey', resourceKey);
    if (this.isPoppedOut()) window.document.title = title;
  },
  setMessagePreview: no_conflict["c" /* _ */].debounce(function (message) {
    var _this6 = this;

    this.ui.messagePreviewText // eslint-disable-line no-invalid-this
    .html(message).attr('title', message);
    this.ui.messagePreview // eslint-disable-line no-invalid-this
    .removeClass('purechat-animation-toastUpDown purechat-animation-toastDownUp');
    this.forceStopAnimation(this.ui.messagePreview.get(0)); // eslint-disable-line no-invalid-this

    var animationClass = this.isTop() ? 'purechat-animation-toastDownUp' : 'purechat-animation-toastUpDown'; // eslint-disable-line no-invalid-this
    // Remove the animation class once it's done

    this.ui.messagePreview.on(widget_layout_view_ANIMATION_EVENTS, function () {
      // eslint-disable-line no-invalid-this
      _this6.ui.messagePreview.off(widget_layout_view_ANIMATION_EVENTS); // eslint-disable-line no-invalid-this


      _this6.ui.messagePreview // eslint-disable-line no-invalid-this
      .removeClass('purechat-animate purechat-animation-toastUpDown purechat-animation-toastDownUp').purechatDisplay('none');
    }).purechatDisplay().addClass(animationClass);
  }, DEFAULT_DEBOUNCE),
  updateImageTransform: function updateImageTransform() {
    // Cannot exceed 100% scale, or poop will happen
    var operatorsAvailable = this.getOperatorsAvailable() || this.options.widgetSettings.get('UseAvailableImageForBoth');
    this.options.widgetSettings.set('AvailableImageScale', Math.min(DEFAULT_IMAGE_SCALE, this.options.widgetSettings.get('AvailableImageScale')), {
      silent: true
    });
    this.options.widgetSettings.set('UnavailableImageScale', Math.min(DEFAULT_IMAGE_SCALE, this.options.widgetSettings.get('UnavailableImageScale')), {
      silent: true
    });

    if (this.ui.collapseImage && this.ui.collapseImage.attr) {
      this.setCollapsedImage(operatorsAvailable);
    }
  },
  hideAdditionalDetails: function hideAdditionalDetails() {
    this.$el.find('.purechat-widget-sliding-panel').removeClass('expanded').addClass('collapsed');
    this.$el.find('.additional-details').purechatDisplay();
    this.$el.find('.purechat-widget-inner').removeClass('expanded');
    this.$el.purechatCss({
      width: this.maxWidth - ADDITIONAL_DETAILS_OFFSET
    });
  },
  showAdditionalDetails: function showAdditionalDetails() {
    var slidingPanel = this.$el.find('.purechat-widget-sliding-panel');
    var spinner = slidingPanel.find('.spinner');
    var headerHeight = this.$el.find('.purechat-widget-inner .purechat-widget-header').outerHeight();
    spinner.purechatDisplay();
    this.$el.find('.purechat-widget-inner').addClass('expanded');
    slidingPanel.find('.purechat-widget-header').purechatCss({
      height: headerHeight,
      lineHeight: headerHeight + 'px'
    });
    slidingPanel.find('.purechat-additional-content').purechatCss({
      top: headerHeight
    });
    slidingPanel.removeClass('collapsed').addClass('expanded');
    spinner.purechatDisplay('none');
  },
  executeCommand: function executeCommand(e) {
    e.preventDefault(); // This prevents any parent elements from capturing bubbling events when a child triggered them and the events are supposed to be different

    e.stopPropagation();
    if (this.settings.get('isInEditorMode')) return null;
    var sender = jquery_default()(e.currentTarget);
    var command = sender.data('trigger');
    var commandParams = sender.data('trigger-params');

    if (this.minimizeOnLoadTimeout) {
      this.minimizeOnLoadTimeout = clearTimeout(this.minimizeOnLoadTimeout);
    } // Allow clicks to stop the tab bar from minimizing


    this.cancelAutoSuperMinimize();
    return this.triggerMethod(command, commandParams, e);
  },
  setAutoExpandTimeout: function setAutoExpandTimeout() {
    var _this7 = this;

    var duration = this.settings.get('ExpandWidgetTimeout') * JUST_A_SEC;
    var timeout = setTimeout(function () {
      _this7.expand();

      clearTimeout(timeout);
    }, duration);
  },
  enablePurechatAssist: function enablePurechatAssist() {
    jquery_default()('html').addClass('purechat-assist');
  },
  disablePurechatAssist: function disablePurechatAssist() {
    jquery_default()('html').removeClass('purechat-assist');
  },
  setSuperMinimizeClasses: function setSuperMinimizeClasses() {
    this.$el.removeClass('purechat-widget-expanded purechat-widget-collapsed');
    this.$el.addClass('purechat-widget-super-collapsed');
    this.removeAnimationClasses();
    this.$el.addClass('purechat-animation-fadeInDownSmall purechat-animate purechat-animate-fast');
  },
  onSuperMinimize: function onSuperMinimize(args, e) {
    if (this.isPoppedOut()) return false;
    if (e) e.stopPropagation();
    if (this.model.get('expanded')) this.onCollapse();
    var flyoutView = this.getRegion('flyout').currentView;
    if (flyoutView) flyoutView.hide(true);
    this.setSuperMinimizeClasses();
    this.model.set('superMinimize', true);
    window.localStorage.superMinimize = true;
    this.disablePurechatAssist();
    this.trigger('minimized');
    return false; // NUKE THE EVENT FROM ORBIT
  },
  getRequiredSetting: function getRequiredSetting(setting) {
    var value = this.options.model.get(setting);
    return value === undefined ? true : Boolean(value);
  },
  onShowEmail: function onShowEmail(args, e) {
    if (this.settings.get('EmailButtonBehavior') === constants["a" /* default */].EmailButtonBehaviors.ShowEmailForm) {
      var model = new no_conflict["a" /* Backbone */].Model({
        EmailForm: true,
        InitialVisitorName: this.options.model.get('visitorName') || '',
        InitialVisitorFirstName: this.options.model.get('visitorFirstName') || '',
        InitialVisitorLastName: this.options.model.get('visitorLastName') || '',
        InitialVisitorCompany: this.options.model.get('visitorCompany') || '',
        InitialVisitorEmail: this.options.model.get('visitorEmail') || '',
        InitialVisitorQuestion: this.options.model.get('visitorQuestion') || '',
        InitialVisitorPhoneNumber: this.options.model.get('visitorPhoneNumber') || '',
        RequireFirstName: this.getRequiredSetting('RequireFirstName'),
        RequireLastName: this.getRequiredSetting('RequireLastName'),
        RequireCompany: this.getRequiredSetting('RequireCompany'),
        RequirePhoneNumber: this.getRequiredSetting('RequirePhoneNumber'),
        RequireEmail: this.getRequiredSetting('RequireEmail'),
        RequireQuestion: this.getRequiredSetting('RequireQuestion')
      });
      var viewController = this.options.viewController;
      var dataController = this.options.viewController.getDataController();
      var emailForm = new email_form_view({
        dataController: dataController,
        viewController: viewController,
        rm: this.options.rm,
        settings: this.settings,
        chatModel: viewController.chatModel,
        model: model
      });
      this.showFlyout('email', jquery_default()(e.currentTarget), emailForm);
    } else {
      this.showFlyout('email', jquery_default()(e.currentTarget));
    }
  },
  onShowPhoneNumber: function onShowPhoneNumber(args, e) {
    this.showFlyout('phone', jquery_default()(e.currentTarget));
  },
  onShowTwitter: function onShowTwitter(args, e) {
    this.showFlyout('twitter', jquery_default()(e.currentTarget));
  },
  onShowAddress: function onShowAddress(args, e) {
    this.showFlyout('address', jquery_default()(e.currentTarget));
  },
  showFlyout: function showFlyout(id, btn, view) {
    var flyoutView = this.getRegion('flyout').currentView;
    var header = this.$el.find('.purechat-collapsed .purechat-widget-header');

    if (this.isButtonActive(btn)) {
      if (flyoutView) flyoutView.hide();
      this.deactivateButton(btn);
      this.resetIcons(btn);
    } else {
      this.resetIcons(header);
      this.resetActiveButtons(header);
      this.activateButton(btn);
      this.swapCloseIcon(btn);

      if (flyoutView) {
        if (id === 'email' && view) {
          flyoutView.showEmailView(view, btn);
        } else if (id === 'twitter') {
          btn.find('.pc-svgicon').purechatDisplay('none');
          btn.find('.purechat-loading').purechatDisplay('inline-block');
          flyoutView.getView(id).loadScript().then(function () {
            flyoutView.showView(id, btn);
            btn.find('.pc-svgicon').purechatDisplay('inline-block');
            btn.find('.purechat-loading').purechatDisplay('none');
          });
        } else {
          flyoutView.showView(id, btn);
        }
      }
    }
  },
  resetIcons: function resetIcons(parentElement) {
    parentElement.find('use').each(function (i, el) {
      var useTag = jquery_default()(el);

      if (useTag.data('activeFlyoutIcon')) {
        useTag.attr(utils["a" /* default */].svgHrefAttr(), useTag.data('activeFlyoutIcon'));
      }
    });
  },
  swapCloseIcon: function swapCloseIcon(parentElement) {
    var useTag = parentElement.find('use');
    useTag.data('activeFlyoutIcon', useTag.attr(utils["a" /* default */].svgHrefAttr()));
    useTag.attr(utils["a" /* default */].svgHrefAttr(), "".concat(window.location, "#pc-svgicon-close"));
  },
  resetActiveButtons: function resetActiveButtons(parentElement) {
    parentElement.find('.purechat-btn').removeClass('purechat-btn-active');
  },
  deactivateButton: function deactivateButton(btn) {
    btn.removeClass('purechat-btn-active');
  },
  activateButton: function activateButton(btn) {
    btn.addClass('purechat-btn-active');
  },
  isButtonActive: function isButtonActive(btn) {
    return btn.hasClass('purechat-btn-active');
  },
  onCollapsedClick: function onCollapsedClick() {
    if (this.isSuperMinimized()) {
      this.onCollapse.apply(this, arguments);
    } else if (!this.isExpanded() && !this.isSuperMinimized()) {
      this.onExpand.apply(this, arguments);
    }
  },
  operatorsAvailableChanged: function operatorsAvailableChanged() {
    if (this.settings.get('isWidget')) {
      if (this.model.get('operatorsAvailable')) {
        this.$el.addClass('purechat-button-available');
        this.$el.removeClass('purechat-button-unavailable');
        this.$el.removeAttr('disabled', 'disabled');
        this.$el.find('.purechat-start-chat').purechatDisplay();
      } else {
        this.$el.removeClass('purechat-button-available');
        this.$el.addClass('purechat-button-unavailable'); // Only hide chatbox if no buttons are selected

        var isHideBehavior = this.options.widgetSettings.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget;

        if (isHideBehavior && !this.options.widgetSettings.anyButtonEnabled()) {
          this.$el.addClass('purechat-invisible').purechatDisplay('none');
          this.$el.attr('disabled', 'disabled');
        } else if (isHideBehavior) {
          this.onCollapse();
        }
      }

      this.updateCollapsedStyle();
    }
  },
  onExpand: function onExpand(e, externalArgs) {
    var _this8 = this;

    var isCollapseCommand = externalArgs.collapse;
    var superMinimize = externalArgs.superMinimize;
    var isPoppedOrHosted = this.options.widgetSettings.get('poppedOut') || this.options.widgetSettings.get('isDirectAccess');
    var isMobile = this.settings.useMobile() && !this.settings.isDesktopDimension();
    var isHideBehavior = this.settings.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget;
    var performPopout = !this.settings.get('isDemo') && (!this.settings.get('isDirectAccess') && this.settings.get('ForcePopout') && !this.isPoppedOut() || this.settings.get('usePrototypeFallback'));

    if (performPopout && !isPoppedOrHosted && !this.options.widgetSettings.get('widgetWasPoppedOut')) {
      var popoutWidget = function popoutWidget() {
        var viewController = _this8.options.viewController;

        var dataController = _this8.options.viewController.getDataController();

        viewController.popoutChatOnExpand(dataController, dataController.options, viewController.chatModel, viewController.state, isMobile);

        _this8.options.widgetSettings.set('widgetWasPoppedOut', true);
      };

      if (!isHideBehavior) {
        popoutWidget();
      } else {
        this.options.widgetSettings.get('dataController').checkChatAvailable().done(function (result) {
          _this8.model.set('operatorsAvailable', result.available);

          if (result.available) popoutWidget();
        });
      }
    } else {
      this.options.widgetSettings.get('dataController').checkChatAvailable().done(function (result) {
        _this8.model.set('operatorsAvailable', result.available); // The widget is visible if any buttons are turned on so we have to short circuit any
        // attempt to expand the widget.


        if (!result.available && isHideBehavior && _this8.options.widgetSettings.anyButtonEnabled()) return;

        if (!isCollapseCommand && !superMinimize) {
          _this8.$el.addClass('purechat-clickable').removeClass('purechat-not-clickable');

          _this8.expand();
        }
      });
    }

    this.resetMissedMessageCount();
    this.cancelAutoSuperMinimize();
  },
  mobileResize: function mobileResize() {
    this.collapseMobile();
  },
  expandMobile: function expandMobile(firstLoad, callback) {
    jquery_default()(window).off('resize.RepositionWidget');
    this.enablePurechatAssist();
    this.ui.expandMobileButton.purechatDisplay('none');
    this.$el.addClass('purechat-clickable').removeClass('purechat-not-clickable');
    var flyoutView = this.getRegion('flyout').currentView;
    if (flyoutView) flyoutView.hide(true);
    (callback || function () {}).call(this);
  },
  setExpandedClasses: function setExpandedClasses() {
    this.$el.removeClass('purechat-widget-super-collapse');
    this.$el.removeClass('purechat-widget-super-collapsed');
    this.$el.find('.purechat-btn-toolbar .purechat-btn-expand').purechatDisplay('none');
    this.$el.find('.purechat-btn-toolbar .purechat-btn-collapse').purechatDisplay('inline-block');
    this.$el.find('.purechat-widget-content').purechatDisplay('flex');
    this.$el.find('.purechat-widget-content').parent().find('div:last').purechatDisplay('block');
    this.ui.widgetCollapsed.purechatDisplay('none');
    this.ui.widgetExpanded.purechatDisplay('flex');
    this.$el.removeClass('purechat-widget-collapsed');
    this.$el.addClass('purechat-widget-expanded');
  },
  expand: function expand(firstLoad, inRoomOnLoad, args) {
    var _this9 = this;

    this.setExpandedClasses();

    var completeFnc = function completeFnc() {
      _this9.setExpandedClasses();

      _this9.showRoomHostAvatar(_this9.options.model.get('roomHostAvatarUrl'));

      _this9.model.set({
        expanded: true
      });

      if (args && args.expandSource) {
        localStorage.expandSource = args.expandSource;
      }

      _this9.setAttachedClass();

      _this9.trigger('expanded');

      _this9.triggerResizedEvent();
    };

    this.model.set('superMinimize', false);
    window.localStorage.superMinimize = false;

    if (!this.settings.get('isDemo')) {
      localStorage.expanded = true;
    }

    this.cancelAutoSuperMinimize();

    if (this.settings.useMobile() && !this.settings.isDesktopDimension() && !this.settings.get('isDirectAccess')) {
      this.expandMobile(firstLoad, completeFnc);

      if (firstLoad) {
        completeFnc();
        this.$el.off('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
      }
    } else {
      var flyoutView = this.getRegion('flyout').currentView;
      if (flyoutView) flyoutView.hide(true);

      if (!this.isHostedMobile() && !this.isPoppedOut() && !this.model.get('isOperator')) {
        this.$el.purechatCss({
          width: '373px'
        });
      }

      completeFnc();
    }
  },
  autoSuperMinimize: function autoSuperMinimize() {
    var _this10 = this;

    var isDemo = this.settings.get('isDemo');
    var isHosted = this.settings.get('isDirectAccess');
    var isMobileWidget = this.isMobile();
    var forceMobileSuperMinimize = this.settings.get('forceMobileSuperMinimize'); // Super-minimize by default on mobile, ignore if image type. It is also allowed
    // to auto super-minimize in demo mode when specified via query string.

    if (isHosted) return;
    if (!isMobileWidget) return;
    if (this.isExpanded() || this.isImageOnly()) return;
    if (isDemo && !forceMobileSuperMinimize) return;
    this.cancelAutoSuperMinimize();
    this.superMinimizeTimeoutId = setTimeout(function () {
      _this10.onSuperMinimize(null, null, true);

      _this10.superMinimizeTimeoutId = null;
    }, AUTO_SUPER_MINIMIZE_TIMEOUT_MS);
  },
  cancelAutoSuperMinimize: function cancelAutoSuperMinimize() {
    if (this.hasOwnProperty('superMinimizeTimeoutId')) {
      clearTimeout(this.superMinimizeTimeoutId);
      this.superMinimizeTimeoutId = null;
    }
  },
  collapseMobile: function collapseMobile(firstLoad, callback) {
    var isDirectAccess = this.settings.get('isDirectAccess');
    var killForPreview = this.options.widgetSettings.get('killForPreview');
    var isMobileRequest = this.settings.isMobileRequest();
    var allowedOnMobile = this.options.widgetSettings.isAllowedOnMobile();
    this.disablePurechatAssist();
    if (isDirectAccess || this.isPoppedOut()) return;
    if (!firstLoad) this.ui.expandMobileButton.purechatDisplay('block');

    if (!killForPreview && !isMobileRequest && !allowedOnMobile) {
      this.ui.expandMobileButton.removeAttr('style');
    }

    this.$el.addClass('purechat-not-clickable').removeClass('purechat-clickable');

    if (!this.widgetShown()) {
      this.ui.collapsedTitle.addClass('purechat-clickable');
    } else {
      this.ui.collapsedTitle.removeClass('purechat-animate purechat-animation-toast-x purechat-clickable');
    }

    (callback || function () {}).call(this);
    this.autoSuperMinimize();
    this.updateCollapsedStyle();
  },
  removeAnimationClasses: function removeAnimationClasses() {
    var el = this.$el.get(0);
    var prefix = 'purechat-animat'; // Include purechat-animate and purechat-animation-*

    var classes = el.className.split(' ').filter(function (c) {
      return c.lastIndexOf(prefix, 0) !== 0;
    });
    el.className = classes.join(' ').trim();
    this.forceStopAnimation(el);
  },
  // Trigger a reflow to force the animation to stop.
  // See https://css-tricks.com/restart-css-animation/#article-header-id-0
  forceStopAnimation: function forceStopAnimation(el) {
    void el.offsetWidth;
  },
  collapse: function collapse() {
    var _this11 = this;

    //show the collapsed state unless the widget is set to custom button.
    //In that case collapse to show a tab.
    if (!this.isInChat() || this.settings.get('Type') !== constants["a" /* default */].WidgetType.Button) {
      this.ui.widgetCollapsed.purechatDisplay('block');
      this.ui.widgetExpanded.purechatDisplay('none');
    } else {
      this.ui.widgetCollapsed.purechatDisplay('none');
      this.ui.widgetExpanded.purechatDisplay('flex');

      if (this.settings.useMobile() && !this.settings.isDesktopDimension()) {
        // Need to hide the "plus" button if on mobile
        this.$el.find('.purechat-expanded .purechat-menu .purechat-btn-expand').purechatDisplay('none');
        this.ui.widgetExpanded.off('click.ExpandWidgetForMobile').on('click.ExpandWidgetForMobile', function () {
          _this11.ui.widgetExpanded.off('click.ExpandWidgetForMobile');

          _this11.expand();
        });
      }
    }

    this.updateCollapsedStyle();
  },
  setCollapsedClasses: function setCollapsedClasses() {
    this.$el.removeClass('purechat-widget-expanded purechat-widget-super-collapsed');
    this.$el.addClass('purechat-widget-collapsed');
    this.$el.find('.purechat-btn-toolbar .purechat-btn-expand').purechatDisplay('block'); // Maybe might possibly need showHideMinmizeButton() here

    this.$el.find('.purechat-btn-toolbar .purechat-btn-collapse, .purechat-widget-content').purechatDisplay('none');
    this.$el.find('.purechat-widget-content').parent().find('div:last').purechatDisplay('none');
  },
  setFirstLoadCollapsedAnimationClass: function setFirstLoadCollapsedAnimationClass() {
    var _this12 = this;

    this.removeAnimationClasses();
    var animation = this.settings.get('PageLoadAnimation') || this.settings.get('DisplayWidgetAnimation');
    var inRoom = this.options.viewController.getDataController().checkInRoom();
    var isDemo = this.settings.get('isDemo');

    if (animation && !this.isExpanded() && (isDemo || !isDemo && !inRoom)) {
      this.$el.addClass("purechat-animation-".concat(animation, " purechat-animate")).on(widget_layout_view_ANIMATION_EVENTS, function () {
        _this12.$el.off(widget_layout_view_ANIMATION_EVENTS); // Just in case the preview needs to keep a flyout open, we check it after the
        // load animation is finished for the widget.


        if (_this12.settings.get('visibleFlyoutId')) {
          _this12.toggleFlyoutPreview(_this12.settings, _this12.settings.get('visibleFlyoutId'));
        }
      });
    }
  },
  setCollapsedAnimationClass: function setCollapsedAnimationClass() {
    this.removeAnimationClasses();
    this.$el.addClass('purechat-animate purechat-animate-fast purechat-animation-fadeInDownSmall');
  },
  onCollapse: function onCollapse(firstLoad) {
    var _this13 = this;

    window.localStorage.removeItem('expandSource');

    if (!this.settings.get('isDemo')) {
      window.localStorage.expanded = false;
      window.localStorage.superMinimize = false;
    }

    this.setCollapsedClasses();

    if (firstLoad) {
      this.setFirstLoadCollapsedAnimationClass();
    } else {
      this.setCollapsedAnimationClass();
    }

    var header = this.$el.find('.purechat-collapsed .purechat-widget-header');
    this.resetIcons(header);
    this.resetActiveButtons(header); // show the collapsed state unless the widget is set to custom button.
    // In that case collapse to show a tab.

    if (!this.isInChat() || this.settings.get('Type') !== constants["a" /* default */].WidgetType.Button) {
      this.ui.widgetCollapsed.purechatDisplay('block');
      this.ui.widgetExpanded.purechatDisplay('none');
    } else {
      this.ui.widgetCollapsed.purechatDisplay('none');
      this.ui.widgetExpanded.purechatDisplay('flex');

      if (this.settings.useMobile() && !this.settings.isDesktopDimension()) {
        // Need to hide the "plus" button if on mobile
        this.$el.find('.purechat-expanded .purechat-menu .purechat-btn-expand').purechatDisplay('none');
        this.ui.widgetExpanded.off('click.ExpandWidgetForMobile').on('click.ExpandWidgetForMobile', function () {
          _this13.ui.widgetExpanded.off('click.ExpandWidgetForMobile');

          _this13.expand();
        });
      }
    }

    this.model.set('superMinimize', false);
    this.model.set('expanded', false);
    this.trigger('collapsed');
    this.triggerResizedEvent();

    if (this.settings.useMobile() && !this.settings.isDesktopDimension() && !firstLoad) {
      this.collapseMobile(firstLoad);
    } else {
      this.setCollapsedWidth();
    }

    this.setUnavailableBehaviorClass();
  },
  onShow: function onShow() {
    this.setCollapsedMinWidth();
    this.triggerResizedEvent();
  },
  triggerResizedEvent: function triggerResizedEvent() {
    this.options.viewController.triggerResizedEvent();
  },
  flashNotification: function flashNotification(message) {
    widget_layout_view_notifier.notify(message, this.ui.title, this.$el);
    this.setMessagePreview(message);
  },
  incrementMissedMessageCount: function incrementMissedMessageCount() {
    this.missedMessageCount += 1;
    this.ui.missedMessageCount.text(this.missedMessageCount);
    this.ui.missedMessageCount.purechatDisplay('block');
  },
  resetMissedMessageCount: function resetMissedMessageCount() {
    this.ui.missedMessageCount.purechatDisplay('none');
    this.ui.missedMessageCount.text('');
    this.missedMessageCount = 0;
  },
  onRender: function onRender() {
    this.updateCollapsedStyle();
    this.ui.expandMobileButton.purechatDisplay('none');

    if (!this.settings.get('isWidget')) {
      this.$el.addClass('purechat-window');
      this.ui.content.addClass('purechat-window-content');
    } else {
      this.ui.content.addClass('purechat-widget-content');
    }

    this.operatorsAvailableChanged();
    this.setExpandedTitle(this.settings.get('title') || '');
    var inRoomOnLoad = this.settings.get('dataController').checkInRoom() !== null && typeof this.settings.get('dataController').checkInRoom() !== 'undefined';

    if (!this.settings.get('isDemo') && window.localStorage.expanded === 'true' && !this.settings.get('ForcePopout') && !this.settings.get('usePrototypeFallback') && (inRoomOnLoad || !this.settings.get('StartChatImmediately') && this.settings.get('UnavailableBehavior') !== constants["a" /* default */].UnavailableBehaviors.HideWidget)) {
      this.expand(true, inRoomOnLoad);
    } else if (this.model.get('superMinimize')) {
      this.onSuperMinimize(null, null, true);
      this.collapse();
    } else if ((this.settings.get('isDemo') || this.settings.get('poppedOut')) && this.isExpanded()) {
      this.expand();
    } else {
      this.onCollapse(true);
    }

    if (this.$el.hasClass('purechat-top')) {
      this.$el.find('.pc-icon-caret-down').removeClass('pc-icon-caret-down').addClass('pc-icon-caret-up');
    }

    if (!this.model.get('isOperator') && this.showTab()) {
      var isTop = this.$el.hasClass('purechat-top-left') || this.$el.hasClass('purechat-top-right');
      this.showChildView('flyout', new flyout_view({
        model: this.settings,
        isTop: isTop,
        widgetElement: this.$el
      }));
      if (!this.settings.get('isDemo')) this.registerFlyoutCloseClickHandler();
    }

    this.setAttachedClass();
    this.setCollapsedWidth();
    this.setUnavailableBehaviorClass();
  },
  onDestroy: function onDestroy() {
    jquery_default()(window).off('.purechat-flyout');
  },
  onAfterInsertion: function onAfterInsertion() {
    if (this.model.get('isOperator')) return;
    if (!this.isMobile()) return;

    if (this.$el.hasClass('purechat-widget-expanded')) {
      this.expandMobile();
    } else {
      this.collapseMobile(true);
    }
  },
  setAttachedClass: function setAttachedClass() {
    if (this.settings.get('AnchorToEdge') && !this.isMobile()) {
      this.$el.addClass('purechat-attached');
    }
  },
  setCollapsedWidth: function setCollapsedWidth() {
    if (!this.settings.get('Width')) return;
    if (this.isExpanded()) return;
    if (this.settings.get('isOperator')) return;
    if (this.settings.useMobile()) return;
    this.$el.purechatCss({
      width: this.settings.get('Width')
    });
  },
  setCollapsedMinWidth: function setCollapsedMinWidth() {
    if (this.isExpanded()) return;
    if (this.settings.get('isOperator')) return;
    var minWidth = 0;
    var header = this.$el.find('.purechat-collapsed .purechat-widget-header');
    var headerPadding = header.outerWidth() - header.width();
    var factor = 0;
    if (this.settings.get('ShowEmailButton')) factor += 1;
    if (this.settings.get('ShowPhoneButton')) factor += 1;
    if (this.settings.get('ShowTwitterButton')) factor += 1;
    if (this.settings.get('ShowAddressButton')) factor += 1;
    if (this.settings.get('ShowMinimizeWidgetButton')) factor += 1;
    if (this.getOperatorsAvailable()) factor += 1;

    if (factor === 0) {
      var textOuterWidth = header.find('.purechat-widget-title-link').outerWidth();
      minWidth = textOuterWidth + headerPadding;
    } else {
      var menu = header.find('.purechat-menu');
      minWidth = menu.outerWidth(true) + (header.outerWidth() - header.width());
    }

    this.$el.purechatCss({
      minWidth: minWidth
    });
  },
  setCollapsedImage: function setCollapsedImage(available) {
    if (this.isMobile()) {
      this.mobileCollapsedImageCss(available);
    } else {
      this.collapsedImageCss(available);
    }
  },
  setUnavailableBehaviorClass: function setUnavailableBehaviorClass() {
    var isHideBehavior = this.settings.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget;

    if (!this.model.get('operatorsAvailable') && isHideBehavior) {
      this.$el.addClass('purechat-unavailable-behavior-hide');
    } else {
      this.$el.removeClass('purechat-unavailable-behavior-hide');
    }
  },
  collapsedImageCss: function collapsedImageCss(available) {
    var baseScale = available ? this.settings.get('AvailableImageScale') : this.settings.get('UnavailableImageScale');
    var scale = baseScale / IMAGE_SCALE_BASE;
    var imgUrl = this.settings.absoluteCollapsedImageUrl(available);
    var scaledWidth = (available ? this.settings.get('AvailableImageWidth') : this.settings.get('UnavailableImageWidth')) * scale;
    var scaledHeight = (available ? this.settings.get('AvailableImageHeight') : this.settings.get('UnavailableImageHeight')) * scale;
    var baseXOffset = available ? this.settings.get('AvailableImageXOffset') : this.settings.get('UnavailableImageXOffset');
    var baseYOffset = available ? this.settings.get('AvailableImageYOffset') : this.settings.get('UnavailableImageYOffset');
    var imageTop = available ? this.settings.get('AvailableImageTop') : this.settings.get('UnavailableImageTop');
    var isMinimal = ('' + this.settings.get('StyleName')).toLowerCase() === 'minimal';
    var isClassic = ('' + this.settings.get('StyleName')).toLowerCase() === 'classic';
    if (!imgUrl) return; // Don't set an image if there's no one available and the behavior is set
    // to hidden. This way there's not a request for an image that doesn't get shown.

    var isHideBehavior = this.options.widgetSettings.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget;
    if (!this.getOperatorsAvailable() && isHideBehavior && !this.options.widgetSettings.anyButtonEnabled()) return;
    var css = {
      backgroundImage: "url(".concat(imgUrl, ")"),
      height: "".concat(scaledHeight, "px"),
      width: "".concat(scaledWidth, "px"),
      zIndex: imageTop ? IMAGE_BASE_ZINDEX : -IMAGE_BASE_ZINDEX
    };
    var yOffset = scaledHeight + baseYOffset;
    var xOffset = baseXOffset;

    if (this.isImageOnly() && isMinimal || !this.isImageOnly() && isClassic) {
      yOffset += LEGACY_IMAGE_OFFSET;
    }

    if (!this.isImageOnly() && !isClassic) {
      xOffset += LEGACY_IMAGE_OFFSET;
    }

    if (this.isTop()) {
      if (!this.isImageOnly()) yOffset += LEGACY_TOPY_IMAGE_OFFSET;
      css.marginBottom = "-".concat(yOffset, "px");
    } else {
      css.marginTop = "-".concat(yOffset, "px");
    }

    if (this.isLeft() || !this.isImageOnly()) {
      css.marginLeft = "".concat(xOffset, "px");
    } else {
      css.marginRight = "".concat(xOffset * -1, "px");
    }

    this.ui.collapseImage.purechatCss(css);
  },
  mobileCollapsedImageCss: function mobileCollapsedImageCss(available) {
    var imgUrl = this.settings.mobileAbsoluteCollapsedImageUrl(available);
    if (!imgUrl) return; // Don't set an image if there's no one available and the behavior is set
    // to hidden. This way there's not a request for an image that doesn't get shown.

    var isHideBehavior = this.options.widgetSettings.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget;
    if (!this.getOperatorsAvailable() && isHideBehavior && !this.options.widgetSettings.anyButtonEnabled()) return;
    this.ui.collapseImage.purechatCss('background-image', "url(".concat(imgUrl, ")"));
  },
  toggleFlyoutPreview: function toggleFlyoutPreview(model, id) {
    switch (id) {
      case 'email':
        return this.ui.emailFlyoutButton.click();

      case 'phone':
        return this.ui.phoneFlyoutButton.click();

      case 'twitter':
        return this.ui.twitterFlyoutButton.click();

      case 'address':
        return this.ui.addressFlyoutButton.click();

      default:
        var header = this.$el.find('.purechat-collapsed .purechat-widget-header');
        var flyoutView = this.getRegion('flyout').currentView;
        if (flyoutView) flyoutView.$el.purechatDisplay('none');
        this.resetIcons(header);
        this.resetActiveButtons(header);
    }
  },
  showFileTransferOverlay: function showFileTransferOverlay(e) {
    if (!this.isInChat()) return;
    if (!this.settings.isFileTransferEnabled()) return;
    if (this.settings.get('isOperator') && this.settings.get('isInvisible')) return;
    this.stopPropagation(e); // If from a browser event, we do some extra checking, else
    // just assume that it was called manually and show the overlay.

    if (e && e.originalEvent) {
      var dataTransfer = e.originalEvent.dataTransfer;
      dataTransfer.dropEffect = 'copy';
      dataTransfer.effectAllowed = 'copy'; // Verify that what's being dragged over is actually a file

      if (!dataTransfer.types || dataTransfer.types.every(function (t) {
        return t !== 'Files';
      })) return;
    } // This appends the file overlay instructions image into the div before its shown. We did
    // this so that the image isn't loaded in on render of the widget to cut down on the number
    // of requests for it. Once it's appended, it will stay until rerender or refresh.


    if (this.ui.fileOverlay.find('.purechat-file-overlay-instructions img').length === 0) {
      var imgUrl = "".concat(this.model.get('cdnServerUrl'), "/assets/files.png");
      var img = document.createElement('img');
      img.setAttribute('src', imgUrl);
      img.setAttribute('alt', 'Upload File');
      this.ui.fileOverlay.find('.purechat-file-overlay-instructions').append(img);
    }

    this.ui.fileOverlay.purechatDisplay('block');
  },
  hideFileTransferOverlay: function hideFileTransferOverlay(e) {
    if (!this.isInChat()) return;
    if (!this.settings.isFileTransferEnabled()) return;
    if (e && jquery_default.a.contains(this.ui.fileOverlay, e.currentTarget)) return;
    this.stopPropagation(e);
    this.ui.fileOverlay.purechatDisplay('none');
  },
  fileDropped: function fileDropped(e) {
    if (!this.isInChat()) return;
    if (!this.settings.isFileTransferEnabled()) return;
    this.stopPropagation(e);
    this.hideFileTransferOverlay();
    var service = this.getOption('viewController').getDataController();
    var dataTransfer = e.dataTransfer || e.originalEvent.dataTransfer;
    var room = this.getOption('rm').get('room') || {};
    Array.prototype.forEach.call(dataTransfer.files, function (file) {
      service.upload(file, room.id);
    });
  },
  stopPropagation: function stopPropagation(e) {
    if (e) {
      e.preventDefault();
      e.stopPropagation();
    }
  },
  isExpanded: function isExpanded() {
    return !!this.model.get('expanded');
  },
  isMobile: function isMobile() {
    return this.settings.get('RequestFromMobileDevice') && this.settings.get('MobileDisplayType') !== constants["a" /* default */].MobileDisplayTypes.SameAsDesktop && !this.settings.isDesktopDimension();
  },
  isHiddenMobile: function isHiddenMobile() {
    return this.settings.get('RequestFromMobileDevice') && this.settings.get('MobileDisplayType') === constants["a" /* default */].MobileDisplayTypes.Hidden && !this.settings.isDesktopDimension();
  },
  isTop: function isTop() {
    var position = this.isMobile() ? this.settings.get('MobilePosition') : this.settings.get('Position');
    return position === constants["a" /* default */].WidgetPosition.TopLeft || position === constants["a" /* default */].WidgetPosition.TopRight;
  },
  isLeft: function isLeft() {
    return this.settings.get('Position') === constants["a" /* default */].WidgetPosition.BottomLeft || this.settings.get('Position') === constants["a" /* default */].WidgetPosition.TopLeft;
  },
  isImageOnly: function isImageOnly() {
    return this.options.widgetSettings.get('CollapsedStyle') === constants["a" /* default */].WidgetType.Image;
  },
  isInChat: function isInChat() {
    return this.settings.get('dataController').checkInRoom();
  },
  isHostedMobile: function isHostedMobile() {
    return this.isMobile() && this.settings.get('isDirectAccess');
  },
  isPoppedOut: function isPoppedOut() {
    return this.model.get('poppedOut') || this.model.get('isPoppedOut');
  },
  showTab: function showTab() {
    return this.settings.get('CollapsedStyle') === constants["a" /* default */].WidgetType.Tab || this.settings.get('CollapsedStyle') === constants["a" /* default */].WidgetType.ImageTab;
  }
});
/* harmony default export */ var widget_layout_view = (WidgetLayout);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/api.model.js
function api_model_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { api_model_typeof = function _typeof(obj) { return typeof obj; }; } else { api_model_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return api_model_typeof(obj); }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

 // This model is going to act as a proxy to all the internal widget settings models

var ApiModel = no_conflict["a" /* Backbone */].Model.extend({
  viewController: null,
  widgetSettings: function widgetSettings() {
    return this.viewController ? this.viewController.options : null;
  },
  chatModel: function chatModel() {
    return this.viewController ? this.viewController.getChatModel() : null;
  },
  dataController: function dataController() {
    return this.viewController ? this.viewController.getDataController() : null;
  },
  setWidgetSetting: function setWidgetSetting(key, val) {
    this.widgetSettings().set(key, val);
  },
  setWidgetResource: function setWidgetResource(key, val) {
    var currentResources = this.viewController.options.get('StringResources');
    this.widgetSettings().set('StringResources', _objectSpread({}, currentResources, _defineProperty({}, key, val)));
  },
  getWidgetSetting: function getWidgetSetting(key) {
    this.widgetSettings().get(key);
  },
  getChatModel: function getChatModel(key) {
    this.chatModel().get(key);
  },
  regexs: {
    propAccess: {
      chatBox: /^chatbox\./i,
      strings: /^string\./i,
      visitor: /^visitor\./i
    },
    events: {
      chatBox: /^chatbox:/i,
      chatBoxPropChange: /^chatbox\.\w(\w|\d)*:/i,
      chat: /^chat:/i,
      email: /^email:/i,
      visitor: /^visitor\.\w(\w|\d)*/i
    }
  },
  mappings: {
    chatBox: {
      keys: {
        available: 'available',
        position: 'Position',
        layoutType: 'CollapsedStyle',
        unavailableBehavior: 'UnavailableBehavior',
        askForRating: 'AskForRating',
        askForFirstName: 'AskForFirstName',
        askForLastName: 'AskForLastName',
        askForEmail: 'AskForEmail',
        askForCompany: 'AskForCompany',
        askForQuestion: 'AskForQuestion',
        askForPhoneNumber: 'AskForPhoneNumber',
        enableTranscriptDownload: 'DownloadTranscript',
        forcePopout: 'ForcePopout',
        enableGoogleAnalytics: 'UsingGa',
        loadingAnimation: 'DisplayWidgetAnimation',
        availableImageXOffset: 'AvailableImageXOffset',
        availableImageYOffset: 'AvailableImageYOffset',
        availableImageScale: 'AvailableImageScale',
        availableImageOnTop: 'AvailableImageTop',
        availableCollapsedImageUrl: 'AvailableCollapsedWidgetImageUrl',
        availableImageHeight: 'AvailableImageHeight',
        availableImageWidth: 'AvailableImageWidth',
        useAvailableImageForBoth: 'chat_startedMessageeForBoth',
        unavailableImageXOffset: 'UnavailableImageXOffset',
        unavailableImageYOffset: 'UnavailableImageYOffset',
        unavailableImageScale: 'UnavailableImageScale',
        unavailableImageOnTop: 'UnavailableImageTop',
        unavailableCollapsedImageUrl: 'UnavailableCollapsedWidgetImageUrl',
        unavailableImageHeight: 'UnavailableImageHeight',
        unavailableImageWidth: 'UnavailableImageWidth',
        showMinimizeButton: 'ShowMinimizeWidgetButton',
        expanded: {
          propertyName: 'expanded',
          setter: function setter(key, value) {
            var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

            if (value) {
              this.viewController.widgetLayout.expand(false, false, {
                expandSource: options.expandSource
              });
            } else {
              this.viewController.widgetLayout.onCollapse(false);
            }
          }
        },
        initialState: 'initialState',
        currentState: 'state',
        enableAvailabilityPolling: 'enableAvailabilityPolling'
      },
      resourceKeys: {
        firstMessage: 'chat_startedMessage'
      },
      values: {
        position: {
          bottomLeft: 1,
          bottomRight: 2,
          topLeft: 3,
          topRight: 4
        },
        layoutType: {
          tab: 1,
          button: 2,
          image: 3,
          tabWithImage: 4
        },
        unavailableBehavior: {
          hide: 0,
          message: 1,
          email: 2
        },
        loadingAnimation: {
          none: 'none',
          flipInX: 'flipInX',
          flipInY: 'flipInY',
          fadeIn: 'fadeIn',
          fadeInUp: 'fadeInUp',
          fadeInDown: 'fadeInDown',
          fadeInLeft: 'fadeInLeft',
          fadeInRight: 'fadeInRight',
          fadeInUpBig: 'fadeInUpBig',
          fadeInDownBig: 'fadeInDownBig',
          fadeInLeftBig: 'fadeInLeftBig',
          fadeInRightBig: 'fadeInRightBig',
          slideInUp: 'slideInUp',
          slideInDown: 'slideInDown',
          slideInLeft: 'slideInLeft',
          slideInRight: 'slideInRight',
          bounceIn: 'bounceIn',
          bounceInUp: 'bounceInUp',
          bounceInDown: 'bounceInDown',
          bounceInLeft: 'bounceInLeft',
          bounceInRight: 'bounceInRight',
          rotateIn: 'rotateIn',
          rotateInDownLeft: 'rotateInDownLeft',
          rotateInDownRight: 'rotateInDownRight',
          rotateInUpLeft: 'rotateInUpLeft',
          rotateInUpRight: 'rotateInUpRight'
        }
      }
    },
    visitor: {
      keys: {
        firstName: 'visitorFirstName',
        lastName: 'visitorLastName',
        email: 'visitorEmail',
        avatarUrl: 'visitorAvatarUrl',
        phoneNumber: 'visitorPhoneNumber',
        question: 'visitorQuestion',
        company: 'visitorCompany',
        name: function name(details) {
          // map name to first/last name props.
          var firstName;
          var lastName;
          var indexOfSpace = details.value.indexOf(' ');

          if (indexOfSpace > 0) {
            firstName = details.value.substring(0, indexOfSpace);
            lastName = details.value.substring(indexOfSpace + 1);
          } else {
            firstName = details.value;
          }

          this.chatModel().set('visitorFirstName', firstName);
          this.chatModel().set('visitorLastName', lastName);
        }
      },
      values: {}
    }
  },
  reverseMapVisitorDetails: function reverseMapVisitorDetails(details) {
    var obj = {};

    for (var key in this.mappings.visitor.keys) {
      obj[key] = details[this.mappings.visitor.keys[key]];
    }

    return obj;
  },
  getMappedWidgetValue: function getMappedWidgetValue(propName, propVal) {
    if (typeof propVal === 'string' && this.mappings.chatBox.values[propName]) {
      for (var valKey in this.mappings.chatBox.values[propName]) {
        if (valKey.toLowerCase() == propVal.toLowerCase()) {
          return this.mappings.chatBox.values[propName][valKey];
        }
      }
    }

    return propVal;
  },
  getMappedWidgetResourceValue: function getMappedWidgetResourceValue(propName, propVal) {
    if (typeof propVal === 'string' && this.mappings.chatBox.values[propName]) {
      for (var valKey in this.mappings.chatBox.values[propName]) {
        if (valKey.toLowerCase() == propVal.toLowerCase()) {
          return this.mappings.chatBox.values[propName][valKey];
        }
      }
    }

    return propVal;
  },
  canSetChatBoxProp: function canSetChatBoxProp(pName) {
    switch (pName) {
      case 'available':
      case 'currentState':
        return false;

      default:
        return true;
    }
  },
  set: function set(propName, propVal) {
    no_conflict["a" /* Backbone */].Model.prototype.set.apply(this, arguments);

    if (api_model_typeof(propName) === 'object') {
      // A hash was passed in, rather than a propName, so we need to call this fnc recursively
      for (var prop in propName) {
        this.set(prop, propName[prop]);
      }
    } else {
      // Standard two params were specified, a name and a value
      var pName;

      if (this.regexs.propAccess.chatBox.test(propName)) {
        // Widget settings
        pName = propName.split(this.regexs.propAccess.chatBox);
        pName = pName.length > 1 ? pName[1] : null;
        var keys = this.mappings.chatBox.keys;
        var resourceKeys = this.mappings.chatBox.resourceKeys;

        if (pName && keys[pName]) {
          var defaultSetter = this.setWidgetSetting;
          var propertyKeyName = keys[pName];

          if (no_conflict["c" /* _ */].isObject(propertyKeyName)) {
            defaultSetter = propertyKeyName.setter || defaultSetter;
            propertyKeyName = propertyKeyName.propertyName;
          }

          propVal = this.getMappedWidgetValue(pName, propVal);
          defaultSetter.call(this, keys[pName], propVal); // Manually trigger an event that says the change is coming from a JS API call

          this.widgetSettings().trigger('api:change', this.widgetSettings, keys[pName], propVal);
        } else if (pName && resourceKeys[pName]) {
          var _defaultSetter = this.setWidgetResource;
          var _propertyKeyName = resourceKeys[pName];

          if (no_conflict["c" /* _ */].isObject(_propertyKeyName)) {
            _defaultSetter = _propertyKeyName.setter || _defaultSetter;
            _propertyKeyName = _propertyKeyName.propertyName;
          }

          propVal = this.getMappedWidgetResourceValue(pName, propVal);

          _defaultSetter.call(this, resourceKeys[pName], propVal); // Manually trigger an event that says the change is coming from a JS API call


          this.widgetSettings().trigger('api:change', this.widgetSettings, keys[pName], propVal);
        }
      } else if (this.regexs.propAccess.visitor.test(propName)) {
        // Visitor detail
        pName = propName.split(this.regexs.propAccess.visitor);
        pName = pName.length > 1 ? pName[1] : null;
        var mappingKey = this.mappings.visitor.keys[pName];

        if (pName && this.mappings.visitor.keys[pName]) {
          var isInChat = this.chatModel().get('roomId') || this.viewController.getDataController().checkInRoom();

          if (this.mappings.visitor.keys.question == mappingKey && !isInChat || this.mappings.visitor.keys.question != mappingKey) {
            if (typeof mappingKey === 'function') {
              mappingKey.call(this, {
                value: propVal
              });
            } else {
              this.chatModel().set(mappingKey, propVal, {
                silent: false
              });
              this.chatModel().trigger('api:change', this.chatModel(), this.mappings.visitor.keys[pName], propVal);
            }
          }
        }
      }
    }
  },
  getRequestedPropName: function getRequestedPropName(request, regex) {
    var pName = request.split(regex);
    return pName.length > 1 ? pName[1] : null;
  },
  get: function get(propName) {
    var pName = null;

    if (this.regexs.propAccess.chatBox.test(propName)) {
      // Widget settings
      pName = this.getRequestedPropName(propName, this.regexs.propAccess.chatBox);

      if (pName && this.mappings.chatBox.keys[pName]) {
        switch (pName) {
          case 'available':
            return this.chatModel() ? this.chatModel().get('operatorsAvailable') : null;

          case 'currentState':
            if (this.chatModel()) {
              var widgetState = this.chatModel().get('state');

              switch (widgetState) {
                case 'PCStateChatting':
                case 'PCStateInitializing':
                case 'PCStateActivating':
                  return 'inChat';

                case 'PCStateClosed':
                  return 'postChat';

                default:
                  return 'preChat';
              }
            } else {
              return null;
            }

          default:
            return this.widgetSettings() ? this.widgetSettings().get(this.mappings.chatBox.keys[pName]) : null;
        }
      }
    } else if (this.regexs.propAccess.visitor.test(propName)) {
      pName = this.getRequestedPropName(propName, this.regexs.propAccess.visitor);

      if (pName && this.mappings.visitor.keys[pName] && this.chatModel) {
        return this.chatModel().get(this.mappings.visitor.keys[pName]);
      }
    }

    return null;
  },
  on: function on(evtName) {
    var allow = this.regexs.events.chat.test(evtName) || this.regexs.events.chatBox.test(evtName) || this.regexs.events.email.test(evtName) || this.regexs.events.visitor.test(evtName) || this.regexs.events.chatBoxPropChange.test(evtName);

    if (allow) {
      // Currently, just do a shallow check to see if the event prefix matches ones we are allowing
      no_conflict["a" /* Backbone */].Model.prototype.on.apply(this, arguments);
      return;
    }

    throw new Error("\"".concat(evtName, "\" is not a valid purechatApi event"));
  },
  off: function off(evtName) {
    if (this.regexs.events.chat.test(evtName) || this.regexs.events.chatBox.test(evtName)) {
      no_conflict["a" /* Backbone */].Model.prototype.off.apply(this, arguments);
    }
  },
  clearViewController: function clearViewController() {
    this.viewController = null;
  },
  setViewController: function setViewController(viewController) {
    this.viewController = viewController;
  },
  clearWidgetSettings: function clearWidgetSettings() {
    this.widgetSettings = null;
  },
  setWidgetSettings: function setWidgetSettings(widgetSettings) {
    this.widgetSettings = widgetSettings;
  },
  clearChatModel: function clearChatModel() {
    this.chatModel = null;
  },
  setChatModel: function setChatModel(chatModel) {
    this.chatModel = chatModel;
  },
  unbindEvents: function unbindEvents() {
    for (var evt in this.events) {
      no_conflict["a" /* Backbone */].Model.prototype.off.apply(this, evt, this.events[evt]);
    }
  },
  bindEvents: function bindEvents() {
    for (var evt in this.events) {
      no_conflict["a" /* Backbone */].Model.prototype.on.apply(this, evt, this.events[evt]);
    }
  },
  initialize: function initialize() {
    // Wire up all events in events hash when the constructor is called
    this.bindEvents();
  },
  onDestroy: function onDestroy() {
    this.unbindEvents();
    no_conflict["a" /* Backbone */].Model.prototype.off.apply(this);
  }
});
/* harmony default export */ var api_model = (ApiModel);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/controllers/api.js
function api_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function api_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function api_createClass(Constructor, protoProps, staticProps) { if (protoProps) api_defineProperties(Constructor.prototype, protoProps); if (staticProps) api_defineProperties(Constructor, staticProps); return Constructor; }





var api_ApiController =
/*#__PURE__*/
function () {
  function ApiController(options) {
    api_classCallCheck(this, ApiController);

    this.options = options;
    this._publicApi = null;
    this.changeableRoomDetails = ['visitorName', 'visitorFirstName', 'visitorLastName', 'visitorEmail', 'visitorReferer', 'visitorPhoneNumber', 'additionalDetails'];

    no_conflict["c" /* _ */].extend(this, no_conflict["a" /* Backbone */].Events);
  }

  api_createClass(ApiController, [{
    key: "getPublicApi",
    value: function getPublicApi() {
      return this._publicApi;
    }
  }, {
    key: "getBaseApiEventObject",
    value: function getBaseApiEventObject() {
      return {
        chatboxId: this.options.get('Id')
      };
    }
  }, {
    key: "extendBaseApiEventObject",
    value: function extendBaseApiEventObject(obj) {
      return jquery_default.a.extend(this.getBaseApiEventObject(), obj || {});
    }
  }, {
    key: "bindWidgetLayoutPublicApiEvents",
    value: function bindWidgetLayoutPublicApiEvents() {
      var _this = this;

      if (!this.widgetLayout) return;
      this.widgetLayout.on('widget:resized', function (e) {
        _this.getPublicApi().trigger('resized', {
          widgetId: _this.getChatModel().id
        });

        _this.getPublicApi().trigger('chatbox:resize', _this.extendBaseApiEventObject({
          width: e.width,
          height: e.height
        }));
      });
      this.widgetLayout.on('expanded', function () {
        _this.getPublicApi().trigger('chatbox:expand', _this.extendBaseApiEventObject());
      });
      this.widgetLayout.on('collapsed', function () {
        _this.getPublicApi().trigger('chatbox:collapse', _this.extendBaseApiEventObject());
      });
      this.widgetLayout.on('minimized', function () {
        _this.getPublicApi().trigger('chatbox:minimize', _this.extendBaseApiEventObject());
      });
    }
  }, {
    key: "bindOptionsPublicApiEvents",
    value: function bindOptionsPublicApiEvents() {
      var _this2 = this;

      this.options.on('change:Position', function () {
        return _this2.widgetLayout.repositionWidget();
      });
    }
  }, {
    key: "bindChatModelPublicApiEvents",
    value: function bindChatModelPublicApiEvents() {
      var _this3 = this;

      this.getChatModel().on('widget:available widget:unavailable', function () {
        _this3.getPublicApi().trigger('chatbox.available:change', _this3.extendBaseApiEventObject({
          available: _this3.getChatModel().get('operatorsAvailable')
        }));
      });
      this.getChatModel().on('operator:join', function (operator) {
        _this3.getPublicApi().trigger('chat:operatorJoin', _this3.extendBaseApiEventObject({
          operatorName: operator.get('userDisplayName')
        }));
      });
      this.getChatModel().on('operator:leave', function (operator) {
        _this3.getPublicApi().trigger('chat:operatorLeave', _this3.extendBaseApiEventObject({
          operatorName: operator.get('userDisplayName')
        }));
      });
      this.getChatModel().on('change:visitorName', function (model, newVal) {});
      this.getChatModel().on('change:visitorFirstName', function (model, newVal) {
        _this3.getPublicApi().trigger('visitor.firstName:change', _this3.extendBaseApiEventObject({
          firstName: newVal
        }));

        _this3.getPublicApi().trigger('visitor.name:change', _this3.extendBaseApiEventObject({
          name: model.getFullName()
        }));
      });
      this.getChatModel().on('change:visitorLastName', function (model, newVal) {
        _this3.getPublicApi().trigger('visitor.lastName:change', _this3.extendBaseApiEventObject({
          lastName: newVal
        }));

        _this3.getPublicApi().trigger('visitor.name:change', _this3.extendBaseApiEventObject({
          name: model.getFullName()
        }));
      });
      this.getChatModel().on('change:visitorCompany', function (model, newVal) {
        _this3.getPublicApi().trigger('visitor.company:change', _this3.extendBaseApiEventObject({
          company: newVal
        }));
      });
      this.getChatModel().on('change:visitorEmail', function (model, newVal) {
        _this3.getPublicApi().trigger('visitor.email:change', _this3.extendBaseApiEventObject({
          email: newVal
        }));
      });
      this.getChatModel().on('change:visitorPhoneNumber', function (model, newVal) {
        _this3.getPublicApi().trigger('visitor.phoneNumber:change', _this3.extendBaseApiEventObject({
          phoneNumber: newVal
        }));
      });
      this.getChatModel().on('change:visitorQuestion', function (model, newVal) {
        _this3.getPublicApi().trigger('visitor.question:change', _this3.extendBaseApiEventObject({
          question: newVal
        }));
      });
      this.getChatModel().on('chat:restart', function () {
        _this3.getPublicApi().trigger('chatbox:restart', _this3.extendBaseApiEventObject());
      });
    }
  }, {
    key: "bindViewControllerPublicApiEvents",
    value: function bindViewControllerPublicApiEvents() {
      var _this4 = this;

      this.listenTo(this, 'chat:start', function (details) {
        _this4.getPublicApi().trigger('chat:start', _this4.extendBaseApiEventObject(_this4.getPublicApi().reverseMapVisitorDetails(details)));
      });
      this.listenTo(this, 'chat:end', function (details) {
        _this4.getPublicApi().trigger('chat:end', _this4.extendBaseApiEventObject(_this4.getPublicApi().reverseMapVisitorDetails(details)));
      });
      this.listenTo(this, 'chat:rate', function (details) {
        _this4.getPublicApi().trigger('chat:rate', _this4.extendBaseApiEventObject(details));
      });
      this.listenTo(this, 'widget:poppedOut', function () {
        _this4.getPublicApi().trigger('chatbox:poppedOut', _this4.extendBaseApiEventObject());
      });
      this.listenTo(this, 'email:send', function (details) {
        _this4.getPublicApi().trigger('email:send', _this4.extendBaseApiEventObject(_this4.getPublicApi().reverseMapVisitorDetails(details)));
      });
    }
  }, {
    key: "registerPublicApiEvents",
    value: function registerPublicApiEvents() {
      var _this5 = this;

      if (!this._publicApi) {
        // If the public API hasn't been initialized, let's new it up and pass a pointer of the widgetSettings to it
        this._publicApi = new api_model();

        this._publicApi.setViewController(this);
      }

      this.listenTo(this, 'state:changed', function (e) {
        var newEvent = {
          widgetId: _this5.getChatModel().id,
          state: e.newState.name
        };
        if (e.oldState) newEvent.previousState = e.oldState.name;

        _this5.getPublicApi().trigger('widget:state-changed', _this5.extendBaseApiEventObject(newEvent));

        _this5.getPublicApi().trigger('chatbox:state-changed', _this5.extendBaseApiEventObject(newEvent));
      });
      this.listenTo(this, 'widget:ready', function () {
        // Wire up all events that require the widget to be ready first
        _this5.bindWidgetLayoutPublicApiEvents();

        _this5.bindOptionsPublicApiEvents();

        _this5.bindChatModelPublicApiEvents();

        try {
          // Emit outward after all initial events are wired up
          _this5.getPublicApi().trigger('ready', _this5.extendBaseApiEventObject());
        } catch (e) {
          console.error(e);
        }

        try {
          _this5.getPublicApi().trigger('chatbox:ready', _this5.extendBaseApiEventObject());
        } catch (e) {
          console.error(e);
        }
      }); // Wire up all events that only need the view controller to be present

      this.bindViewControllerPublicApiEvents();
    }
  }, {
    key: "apiRoomDetailsChanged",
    value: function apiRoomDetailsChanged(model) {
      if (this.getDataController().chatServerConnection) {
        debugger;
        this.getDataController().chatServerConnection.setVisitorDetails(this.getDataController().connectionInfo.get('chatId'), this.getDataController().connectionInfo.get('roomType'), model.pick(this.changeableRoomDetails));
      }
    }
  }, {
    key: "triggerRoomChangedForApi",
    value: function triggerRoomChangedForApi() {
      this.getPublicApi().trigger('chat:change', this.extendBaseApiEventObject(this.getPublicApi().reverseMapVisitorDetails(this.getChatModel().pick(this.changeableRoomDetails))));
    }
  }, {
    key: "destroy",
    value: function destroy() {
      this.stopListening(this);
    }
  }]);

  return ApiController;
}();

/* harmony default export */ var api = (api_ApiController);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/chat_participants.collection.js




var chat_participants_collection_htmlDecode = function htmlDecode(value) {
  return jquery_default()('<div/>').html(value).text();
};

var ChatParticipant = no_conflict["a" /* Backbone */].RelationalModel.extend({
  idAttribute: 'userId'
});
var ChatParticipantCollection = no_conflict["a" /* Backbone */].Collection.extend({
  model: ChatParticipant,
  getOperatorTypingText: function getOperatorTypingText(resourceManger, isOperator) {
    var typingOperators = this.where({
      isTyping: true
    });

    if (!typingOperators || typingOperators.length === 0) {
      return isOperator ? '' : "<span>".concat(resourceManger.getResource('chat_idleText'), "</span>");
    }

    return '<span data-resourcekey="chat_typing">' + typingOperators.map(function (operator) {
      var displayName = operator.get('displayName').trim();

      var phrase = no_conflict["c" /* _ */].escape(resourceManger.getResource('chat_typing', {
        displayName: displayName
      }));

      return chat_participants_collection_htmlDecode(phrase);
    }).join(', ') + '...</span>';
  }
});
/* harmony default export */ var chat_participants_collection = (ChatParticipantCollection);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/chat.model.js



var Chat = no_conflict["a" /* Backbone */].RelationalModel.extend({
  defaults: function defaults() {
    return {
      participants: new chat_participants_collection()
    };
  },
  relations: [{
    type: no_conflict["a" /* Backbone */].HasMany,
    key: 'messages',
    relatedModel: 'Message',
    collectionType: 'MessageCollection',
    reverseRelation: {
      key: 'chat'
    }
  }, {
    type: no_conflict["a" /* Backbone */].HasMany,
    key: 'operators',
    relatedModel: 'Operator',
    collectionType: 'OperatorCollection',
    reverseRelation: {
      key: 'chat'
    }
  }, {
    type: no_conflict["a" /* Backbone */].HasMany,
    key: 'participants',
    relatedModel: 'ChatParticipant',
    collectionType: 'ChatParticipantCollection',
    reverseRelation: {
      key: 'chat'
    }
  }],
  getFullName: function getFullName() {
    var fullName = 'Visitor';
    var firstName = this.get('visitorFirstName');
    var lastName = this.get('visitorLastName');

    if (firstName) {
      fullName = firstName;
      if (lastName) fullName += ' ' + lastName;
    } else if (lastName) {
      fullName = lastName;
    }

    return fullName;
  },
  restartChat: function restartChat() {
    this.set('visitorQuestion', null);
    this.get('operators').reset();
    this.get('messages').reset();
    this.set('state', constants["a" /* default */].WidgetStates.Inactive);
    this.trigger('chat:restart');
  },
  chatUserNames: function chatUserNames() {
    return this.get('operators').map(function (operator) {
      return operator.get('userDisplayName');
    }).join(', ');
  },
  isInChat: function isInChat() {
    return this.get('userId') && this.get('chatId') && this.get('authToken');
  },
  initialize: function initialize() {
    var _this = this;

    this.get('operators').on('add', function (model) {
      // Operator joined the chat!
      _this.trigger('operator:join', model);
    }).on('remove', function (model) {
      // Operator left the chat!
      _this.trigger('operator:leave', model);
    });
  }
});
/* harmony default export */ var chat_model = (Chat);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/models/message.model.js
var message_model = __webpack_require__(157);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/messages.collection.js


var MessageCollection = no_conflict["a" /* Backbone */].Collection.extend({
  model: message_model["a" /* default */],
  add: function add(models) {
    if (models) {
      var temp = no_conflict["c" /* _ */].isArray(models) ? models : [models];
      temp.forEach(function (next) {
        next.timeAdded = new Date().getTime();
      });
    }

    return no_conflict["a" /* Backbone */].Collection.prototype.add.apply(this, arguments);
  },
  comparator: function comparator(a, b) {
    if (a.sortOrder !== b.sortOrder) {
      return a.sortOrder < b.sortOrder ? -1 : 1;
    }

    var sortDate = a.get('date').getTime() - b.get('date').getTime();

    if (sortDate === 0) {
      return a.cid < b.cid ? -1 : 1;
    }

    return sortDate;
  }
});
/* harmony default export */ var messages_collection = (MessageCollection);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/operators.collection.js

var Operator = no_conflict["a" /* Backbone */].RelationalModel.extend({
  idAttribute: 'userId'
});
var OperatorCollection = no_conflict["a" /* Backbone */].Collection.extend({
  model: Operator
});
/* harmony default export */ var operators_collection = (OperatorCollection);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/triggers/base-controller.js
function base_controller_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function base_controller_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function base_controller_createClass(Constructor, protoProps, staticProps) { if (protoProps) base_controller_defineProperties(Constructor.prototype, protoProps); if (staticProps) base_controller_defineProperties(Constructor, staticProps); return Constructor; }




var DEFAULT_TRIGGER_DELAY = 1000;
var Triggers = {}; //Time conversion constants

Triggers.MILLISECONDS_IN_SECOND = 1000;
Triggers.SECONDS_IN_MINUTE = 60;
Triggers.MINUTES_IN_HOUR = 60;
Triggers.HOURS_IN_DAY = 24;
Triggers.MILLISECONDS_IN_DAY = Triggers.HOURS_IN_DAY * Triggers.MINUTES_IN_HOUR * Triggers.SECONDS_IN_MINUTE * Triggers.MILLISECONDS_IN_SECOND; // This constant controls how long we wait on each succesive dismissal of the widget when it is popped up via trigger;

Triggers.DISMISS_DELAYS_DAYS = [0, 1, 3, 7, 30, 365];
Triggers.CHECKIN_INTERVAL_SECONDS = 5;
Triggers.MAX_CHECKIN_INTERVAL_SECOND = 60;
var DismissSettings = no_conflict["a" /* Backbone */].Model.extend({
  storageKeys: ['_purechatSessionStart', '_purechatLastCheckin', '_purechatDismissTime', '_pureChatTimeSettingsVersion', '_purechatDismissCount'],
  defaults: {
    _purechatSessionStart: new Date(),
    _purechatPageStart: new Date(),
    _purechatLastCheckin: new Date(),
    _purechatDismissCount: 0
  },
  fetchDate: function fetchDate(nextKey) {
    var val = window.localStorage.getItem(this.formatPropName(nextKey));

    if (!no_conflict["c" /* _ */].isUndefined(val) && !no_conflict["c" /* _ */].isNaN(val) && !no_conflict["c" /* _ */].isNull(val)) {
      this.set(nextKey, new Date(window.localStorage.getItem(this.formatPropName(nextKey))));
    }
  },
  fetchInt: function fetchInt(nextKey) {
    var val = window.localStorage.getItem(this.formatPropName(nextKey));

    if (!no_conflict["c" /* _ */].isUndefined(val) && !no_conflict["c" /* _ */].isNaN(val) && !no_conflict["c" /* _ */].isNull(val)) {
      this.set(nextKey, parseInt(window.localStorage.getItem(this.formatPropName(nextKey)), 10));
    }
  },
  formatPropName: function formatPropName(prop) {
    return this.widgetId + '_' + prop;
  },
  fetch: function fetch() {
    this.fetchDate('_purechatSessionStart');
    this.fetchDate('_purechatLastCheckin');
    this.fetchDate('_purechatDismissTime');
    this.fetchInt('_pureChatTimeSettingsVersion');
    this.fetchInt('_purechatDismissCount');
  },
  save: function save() {
    var _this = this;

    this.storageKeys.forEach(function (nextKey) {
      var val = _this.get(nextKey);

      if (!no_conflict["c" /* _ */].isUndefined(val) && !no_conflict["c" /* _ */].isNaN(val) && !no_conflict["c" /* _ */].isNull(val)) {
        window.localStorage.setItem(_this.formatPropName(nextKey), _this.get(nextKey));
      } else {
        window.localStorage.removeItem(_this.formatPropName(nextKey));
      }
    });
  },
  resetTimeCounters: function resetTimeCounters() {
    this.set({
      _purechatDismissTime: null
    });
  },
  updateEventLoop: function updateEventLoop() {
    this.set('_purechatLastCheckin', new Date());
    window.localStorage.setItem(this.formatPropName('_purechatLastCheckin'), this.get('_purechatLastCheckin'));
  },
  initialize: function initialize() {
    no_conflict["c" /* _ */].bindAll(this, 'updateEventLoop');

    setInterval(this.updateEventLoop, Triggers.CHECKIN_INTERVAL_SECONDS * Triggers.MILLISECONDS_IN_SECOND);
  }
});

var base_controller_BaseControllerSettings =
/*#__PURE__*/
function () {
  function BaseControllerSettings(purechatController) {
    base_controller_classCallCheck(this, BaseControllerSettings);

    this.purechatController = purechatController;
    this.widgetSettings = purechatController.options;
    this.enabled = this.widgetSettings.get(this.enabledWidgetSettingKey) && !this.isPoppedOut() && !this.isHosted() && !this.isDemoChat() && !this.isMobile() && !this.popOutAutomatically();

    if (this.enabled) {
      //bind these functions to "this" to make them easier to pass around.
      no_conflict["c" /* _ */].bindAll(this, 'onCollapse');

      if (!BaseControllerSettings.dismissSettings) {
        BaseControllerSettings.dismissSettings = new DismissSettings();
        BaseControllerSettings.dismissSettings.widgetId = this.widgetSettings.get('Id');
        BaseControllerSettings.dismissSettings.fetch();
      }

      var settingsVersion = BaseControllerSettings.dismissSettings.get('_pureChatTimeSettingsVersion');
      var currentWidgetSettings = this.widgetSettings.get('WidgetSettingsVersion');

      if (!settingsVersion || settingsVersion != currentWidgetSettings) {
        BaseControllerSettings.dismissSettings.resetTimeCounters();
        BaseControllerSettings.dismissSettings.set('_pureChatTimeSettingsVersion', currentWidgetSettings);
      }

      if (this.isNewSession()) {
        BaseControllerSettings.dismissSettings.set('_purechatSessionStart', new Date());
      }

      this.purechatController.getPublicApi().on('chatbox:collapse', this.onCollapse);
      this.startTesting();
      BaseControllerSettings.dismissSettings.save();
    }
  }

  base_controller_createClass(BaseControllerSettings, [{
    key: "isPoppedOut",
    value: function isPoppedOut() {
      return this.widgetSettings.get('isPoppedOut');
    }
  }, {
    key: "isHosted",
    value: function isHosted() {
      return this.widgetSettings.get('isDirectAccess');
    }
  }, {
    key: "isDemoChat",
    value: function isDemoChat() {
      return this.widgetSettings.get('isDemo');
    }
  }, {
    key: "isMobile",
    value: function isMobile() {
      return this.widgetSettings.get('RequestFromMobileDevice');
    }
  }, {
    key: "isWidgetAvailable",
    value: function isWidgetAvailable() {
      return this.purechatController.chatModel.get('operatorsAvailable');
    }
  }, {
    key: "popOutAutomatically",
    value: function popOutAutomatically() {
      return this.widgetSettings.get('ForcePopout') || false;
    }
  }, {
    key: "onCollapse",
    value: function onCollapse() {
      BaseControllerSettings.dismissSettings.set('_purechatDismissCount', BaseControllerSettings.dismissSettings.get('_purechatDismissCount') + 1);
      this.stopTesting();
      BaseControllerSettings.dismissSettings.set('_purechatDismissTime', new Date());
      BaseControllerSettings.dismissSettings.save();
      this.purechatController.getPublicApi().off('chatbox:collapse', this.onCollapse);
    }
  }, {
    key: "getDismissDelay",
    value: function getDismissDelay() {
      return Triggers.DISMISS_DELAYS_DAYS[Math.min(BaseControllerSettings.dismissSettings.get('_purechatDismissCount'), Triggers.DISMISS_DELAYS_DAYS.length - 1)] * Triggers.MILLISECONDS_IN_DAY;
    }
  }, {
    key: "isNewSession",
    value: function isNewSession() {
      return new Date() - BaseControllerSettings.dismissSettings.get('_purechatLastCheckin') > Triggers.MAX_CHECKIN_INTERVAL_SECOND * Triggers.MILLISECONDS_IN_SECOND;
    }
  }, {
    key: "startTesting",
    value: function startTesting() {
      var dismissTime = BaseControllerSettings.dismissSettings.get('_purechatDismissTime');
      var dismissLimit = this.getDismissDelay();

      if (!dismissTime || new Date() - dismissTime > dismissLimit) {
        BaseControllerSettings.dismissSettings.on('change:_purechatLastCheckin', this.eventCheckChange);
        if (this.onStart) this.onStart();
      }
    }
  }, {
    key: "removeEventListeners",
    value: function removeEventListeners() {
      BaseControllerSettings.dismissSettings.off('change:_purechatLastCheckin', this.eventCheckChange);
    }
  }, {
    key: "stopTesting",
    value: function stopTesting() {
      this.removeEventListeners();
      BaseControllerSettings.dismissSettings.resetTimeCounters();
      BaseControllerSettings.dismissSettings.set('_purechatDismissTime', new Date());
      BaseControllerSettings.dismissSettings.save();
      if (this.onStop) this.onStop();
    }
  }, {
    key: "triggerEvent",
    value: function triggerEvent(delay) {
      var _this2 = this;

      this.purechatController.getDataController().checkChatAvailable().done(function (result) {
        if (!result.available) return;

        _this2.removeEventListeners();

        setTimeout(function () {
          if (_this2.purechatController.chatModel.get('expanded')) return;

          _this2.stopTesting();

          _this2.purechatController.getPublicApi().set('chatbox.expanded', true, {
            expandSource: no_conflict["b" /* Marionette */].getOption(_this2, 'expandSource')
          });
        }, delay || DEFAULT_TRIGGER_DELAY);
      });
    }
  }]);

  return BaseControllerSettings;
}();

Triggers.BaseControllerSettings = base_controller_BaseControllerSettings;
/* harmony default export */ var base_controller = (Triggers);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/triggers/time-based.js
function time_based_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { time_based_typeof = function _typeof(obj) { return typeof obj; }; } else { time_based_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return time_based_typeof(obj); }

function time_based_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function time_based_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function time_based_createClass(Constructor, protoProps, staticProps) { if (protoProps) time_based_defineProperties(Constructor.prototype, protoProps); if (staticProps) time_based_defineProperties(Constructor, staticProps); return Constructor; }

function time_based_possibleConstructorReturn(self, call) { if (call && (time_based_typeof(call) === "object" || typeof call === "function")) { return call; } return time_based_assertThisInitialized(self); }

function time_based_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function time_based_getPrototypeOf(o) { time_based_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return time_based_getPrototypeOf(o); }

function time_based_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) time_based_setPrototypeOf(subClass, superClass); }

function time_based_setPrototypeOf(o, p) { time_based_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return time_based_setPrototypeOf(o, p); }



var time_based_TimeBasedTrigger =
/*#__PURE__*/
function (_Triggers$BaseControl) {
  time_based_inherits(TimeBasedTrigger, _Triggers$BaseControl);

  function TimeBasedTrigger() {
    time_based_classCallCheck(this, TimeBasedTrigger);

    return time_based_possibleConstructorReturn(this, time_based_getPrototypeOf(TimeBasedTrigger).apply(this, arguments));
  }

  time_based_createClass(TimeBasedTrigger, [{
    key: "onStart",
    value: function onStart() {
      var _this = this;

      var expandWidgetTimeoutType = this.widgetSettings.get('ExpandWidgetTimeoutType'); //Do we want to trigger based on thst session start or the page start.

      var startTimeKey = expandWidgetTimeoutType === 1 ? '_purechatSessionStart' : '_purechatPageStart';
      var timeSinceSessionStart = new Date() - base_controller.BaseControllerSettings.dismissSettings.get(startTimeKey);
      var maxSessionLength = this.widgetSettings.get('ExpandWidgetTimeout') * base_controller.MILLISECONDS_IN_SECOND;
      var delay = maxSessionLength - timeSinceSessionStart;
      this.timeout = setTimeout(function () {
        return _this.triggerEvent();
      }, delay);
    }
  }, {
    key: "onStop",
    value: function onStop() {
      clearTimeout(this.timeout);
      this.timeout = undefined;
    }
  }, {
    key: "expandSource",
    get: function get() {
      return 'time-trigger';
    }
  }, {
    key: "enabledWidgetSettingKey",
    get: function get() {
      return 'ExpandWidgetTimeoutEnabled';
    }
  }]);

  return TimeBasedTrigger;
}(base_controller.BaseControllerSettings);

/* harmony default export */ var time_based = (time_based_TimeBasedTrigger);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/triggers/url-based.js
function url_based_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { url_based_typeof = function _typeof(obj) { return typeof obj; }; } else { url_based_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return url_based_typeof(obj); }

function url_based_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function url_based_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function url_based_createClass(Constructor, protoProps, staticProps) { if (protoProps) url_based_defineProperties(Constructor.prototype, protoProps); if (staticProps) url_based_defineProperties(Constructor, staticProps); return Constructor; }

function url_based_possibleConstructorReturn(self, call) { if (call && (url_based_typeof(call) === "object" || typeof call === "function")) { return call; } return url_based_assertThisInitialized(self); }

function url_based_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function url_based_getPrototypeOf(o) { url_based_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return url_based_getPrototypeOf(o); }

function url_based_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) url_based_setPrototypeOf(subClass, superClass); }

function url_based_setPrototypeOf(o, p) { url_based_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return url_based_setPrototypeOf(o, p); }



var url_based_UrlBasedTrigger =
/*#__PURE__*/
function (_Triggers$BaseControl) {
  url_based_inherits(UrlBasedTrigger, _Triggers$BaseControl);

  function UrlBasedTrigger() {
    url_based_classCallCheck(this, UrlBasedTrigger);

    return url_based_possibleConstructorReturn(this, url_based_getPrototypeOf(UrlBasedTrigger).apply(this, arguments));
  }

  url_based_createClass(UrlBasedTrigger, [{
    key: "onStart",
    value: function onStart() {
      var _this = this;

      var testUrls = this.widgetSettings.get('TriggerUrls');
      var triggerPageExpandTimeout = this.widgetSettings.get('TriggerPageExpandTimeout');
      var url = window.location.href.replace('http://', '').replace('https://', '');
      testUrls.filter(function (next) {
        return _this.testUrl(url, next);
      }).forEach(function () {
        return _this.triggerEvent(triggerPageExpandTimeout * base_controller.MILLISECONDS_IN_SECOND);
      });
    }
  }, {
    key: "testUrl",
    value: function testUrl(currentUrl, currentTest) {
      return currentUrl.toLowerCase().indexOf(currentTest.Url.toLowerCase()) >= 0;
    }
  }, {
    key: "expandSource",
    get: function get() {
      return 'url-trigger';
    }
  }, {
    key: "enabledWidgetSettingKey",
    get: function get() {
      return 'EnableTriggerPageSpecific';
    }
  }]);

  return UrlBasedTrigger;
}(base_controller.BaseControllerSettings);

/* harmony default export */ var url_based = (url_based_UrlBasedTrigger);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCWidgetState.js
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

function PCWidgetState_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCWidgetState_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCWidgetState_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCWidgetState_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCWidgetState_defineProperties(Constructor, staticProps); return Constructor; }






var defaultUiVisiblity = {
  popoutButton: false,
  closeButton: false,
  restartButton: false,
  removeWidgetButton: false,
  requeueButton: false,
  leaveButton: false,
  cannedResponsesButton: false
};
var WIDGET_STATE_CLASSES = ['purechat-state-activating', 'purechat-state-chatting', 'purechat-state-closed', 'purechat-state-email-form', 'purechat-state-inactive', 'purechat-state-initializing', 'purechat-state-unavaiable', 'purechat-state-unsupported'].join(' ');
var DEFAULT_AVAIL_TIMEOUT = 20 * 1000;
var DEFAULT_UNAVAIL_TIMEOUT = 10 * 60 * 1000; // split the event name on the ":"

var splitter = /(^|:)(\w)/gi; // take the event section ("section1:section2:section3")
// and turn it in to uppercase name

function getEventName(match, prefix, eventName) {
  return eventName.toUpperCase();
} // As crappy as this is, maintain a scoped reference to an array of poll intervals because the WidgetState isn't always getting disposed properly,
// So a timeout is still being called even when we don't want it to


var pollIntervals = [];

var PCWidgetState_PCWidgetState =
/*#__PURE__*/
function () {
  function PCWidgetState(options) {
    PCWidgetState_classCallCheck(this, PCWidgetState);

    this.options = options;

    no_conflict["c" /* _ */].extend(this, no_conflict["a" /* Backbone */].Events);
  }

  PCWidgetState_createClass(PCWidgetState, [{
    key: "setChatModel",
    value: function setChatModel(model) {
      this.chatModel = model;
    }
  }, {
    key: "getChatModel",
    value: function getChatModel() {
      return this.chatModel;
    }
  }, {
    key: "setWidgetView",
    value: function setWidgetView(view) {
      this.widgetView = view;
      this.listenTo(this.widgetView, 'all');
    }
  }, {
    key: "getWidgetView",
    value: function getWidgetView() {
      return this.widgetView;
    }
  }, {
    key: "setWidgetSettings",
    value: function setWidgetSettings(settings) {
      this.settings = settings;
    }
  }, {
    key: "getWidgetSettings",
    value: function getWidgetSettings() {
      return this.settings;
    }
  }, {
    key: "setResources",
    value: function setResources(resources) {
      this.resources = resources;
    }
  }, {
    key: "getResources",
    value: function getResources() {
      return this.resources;
    }
  }, {
    key: "setDataController",
    value: function setDataController(dc) {
      this.dc = dc;
    }
  }, {
    key: "getDataController",
    value: function getDataController() {
      return this.dc;
    }
  }, {
    key: "setViewController",
    value: function setViewController(vc) {
      this.vc = vc;
    }
  }, {
    key: "getViewController",
    value: function getViewController() {
      return this.vc;
    }
  }, {
    key: "getResource",
    value: function getResource(key, data) {
      return this.resources.getResource(key, data);
    }
  }, {
    key: "disable",
    value: function disable() {
      this.getDataController().connectionInfo.set('disabled', true);
      this.getDataController().connectionInfo.set('chatActiveInOtherWindow', true);
      this.getWidgetView().$el.purechatDisplay('none');
    }
  }, {
    key: "enable",
    value: function enable() {
      this.getDataController().connectionInfo.set('disabled', false);
      this.getDataController().connectionInfo.set('chatActiveInOtherWindow', false);
      this.getWidgetView().$el.purechatDisplay('block');
    }
  }, {
    key: "syncWithContact",
    value: function syncWithContact() {
      var _this = this;

      var d = jquery_default.a.Deferred();
      this.getDataController().getContactInfo().done(function (info) {
        if (!info) return d.resolve();

        var chatModel = _this.getChatModel();

        if (!chatModel.get('visitorFirstName')) chatModel.set('visitorFirstName', info.firstName);
        if (!chatModel.get('visitorLastName')) chatModel.set('visitorLastName', info.lastName);
        if (!chatModel.get('visitorCompany')) chatModel.set('visitorCompany', info.company);
        if (!chatModel.get('visitorEmail')) chatModel.set('visitorEmail', info.email);
        if (!chatModel.get('visitorPhoneNumber')) chatModel.set('visitorPhoneNumber', info.phone);
        return d.resolve();
      });
      return d.promise();
    }
  }, {
    key: "showConnectingWithTimeout",
    value: function showConnectingWithTimeout() {
      var _this2 = this;

      this.clearConnectingTimeout();
      this.connectingTimeout = setTimeout(function () {
        if (!_this2.connectingTimeout) return;
      }, 500);
    }
  }, {
    key: "clearConnectingTimeout",
    value: function clearConnectingTimeout() {
      if (this.connectingTimeout) {
        clearTimeout(this.connectingTimeout);
        delete this.connectingTimeout;
      }
    } //events

  }, {
    key: "onEnter",
    value: function onEnter() {
      var _this3 = this;

      this.getWidgetView().$el.removeClass(WIDGET_STATE_CLASSES).addClass("purechat-state-".concat(this.name));
      this.listenTo(this.getWidgetView(), 'all', function () {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }

        return _this3.triggerMethod.apply(_this3, args);
      });

      if (this.stateSettings) {
        if (this.stateSettings.UiVisiblity) {
          var view = this.getWidgetView();

          no_conflict["c" /* _ */].chain(this.stateSettings.UiVisiblity).defaults(defaultUiVisiblity).pairs().filter(function (_ref) {
            var _ref2 = _slicedToArray(_ref, 1),
                key = _ref2[0];

            return view.ui[key];
          }).each(function (_ref3) {
            var _ref4 = _slicedToArray(_ref3, 2),
                key = _ref4[0],
                show = _ref4[1];

            view.ui[key].purechatDisplay(show ? undefined : 'none');
          });
        }

        var dc = this.getDataController();
        var connectionInfo = dc.connectionInfo;
        var shouldBeInRoom = this.stateSettings.shouldBeInRoom;

        if (!this.chatModel.get('isOperator') && !no_conflict["c" /* _ */].isUndefined(shouldBeInRoom)) {
          if (shouldBeInRoom) {
            this.listenTo(connectionInfo, 'change:isInChat', function (model, isInChat) {
              if (!isInChat) _this3.chatModel.set('state', constants["a" /* default */].WidgetStates.Closed);
            });
          } else {
            this.listenTo(connectionInfo, 'change:isInChat', function (model, isInChat) {
              if (!isInChat) return;

              var settings = _this3.getWidgetSettings();

              var isMobile = settings.useMobile() && !settings.isDesktopDimension();
              if (!isMobile) _this3.widgetView.expand();

              _this3.getChatModel().set('state', constants["a" /* default */].WidgetStates.Chatting);
            });
          }
        }
      }

      this.listenTo(this.options, 'change:enableAvailabilityPolling', function (model, startPolling) {
        if (startPolling) {
          // Only start polling immediately if we're in the inactive state
          if (_this3.name === 'inactive') _this3.startAvailabilityPolling(true);
        } else {
          // Stop polling if this was set AND the widget is currently collapsed, regardless of state
          if (!_this3.getChatModel().get('expanded') && _this3.TestingStartedFromApi) {
            _this3.stopAvailabilityPolling();
          }
        }
      });
      app.events.trigger('footer:show');
    }
  }, {
    key: "onExit",
    value: function onExit() {
      this.clearConnectingTimeout();
      this.stopListening(this.widgetView, 'all');
      this.stopAvailabilityPolling(true);
    }
  }, {
    key: "clearPolling",
    value: function clearPolling() {
      pollIntervals.forEach(function (p) {
        return clearInterval(p);
      });
      pollIntervals = [];
    }
  }, {
    key: "testAvailability",
    value: function testAvailability() {
      var _this4 = this;

      if (this.getViewController().pageActivity || this.lastCheck && new Date() - this.lastCheck > 120000) {
        this.lastCheck = new Date();
        this.getDataController().checkChatAvailable().done(function (result) {
          _this4.clearPolling();

          _this4.checkAvailTimeout = result.available ? DEFAULT_AVAIL_TIMEOUT : DEFAULT_UNAVAIL_TIMEOUT;

          if (result.available || result.reason !== 'AccountActivity') {
            pollIntervals.push(setTimeout(function () {
              return _this4.testAvailability();
            }, _this4.checkAvailTimeout));
          } else {
            _this4.stopAvailabilityPolling();
          }

          _this4.getChatModel().set('operatorsAvailable', result.available);
        });
      } else {
        //If there is now activity we want to test faster so that the widget updates itself quickly
        //When they return to our page.
        this.checkAvailTimeout = DEFAULT_AVAIL_TIMEOUT;
        this.clearPolling();
        pollIntervals.push(setTimeout(function () {
          return _this4.testAvailability();
        }, 1500));
      }
    }
  }, {
    key: "startAvailabilityPolling",
    value: function startAvailabilityPolling(fromApi) {
      var _this5 = this;

      // Kill all polls first!
      this.clearPolling();
      this.checkAvailTimeout = DEFAULT_AVAIL_TIMEOUT;
      this.testAvailability();
      if (!this.TestingStatus) pollIntervals.push(setTimeout(function () {
        return _this5.testAvailability();
      }, this.checkAvailTimeout));
      this.TestingStatus = true;
      this.TestingStartedFromApi = fromApi || false;
    }
  }, {
    key: "stopAvailabilityPolling",
    value: function stopAvailabilityPolling(forceStop) {
      if (!this.options.get('enableAvailabilityPolling') || this.name === 'chatting' || this.name === 'activating' || forceStop) {
        this.TestingStatus = false;
        this.clearPolling();
      }
    }
  }, {
    key: "onPopOutChat",
    value: function onPopOutChat() {
      var settings = this.getWidgetSettings();
      var chatModel = this.getChatModel();
      var dataController = this.getDataController();
      this.getChatModel().set('poppedOut', true);
      this.disable();
      dataController.connectionInfo.persistLocalStorage();
      var params = jquery_default.a.param({
        widgetId: settings.get('widgetId'),
        userId: dataController.connectionInfo.get('userId'),
        displayName: dataController.connectionInfo.get('visitorName'),
        authToken: dataController.connectionInfo.get('authToken'),
        roomId: dataController.connectionInfo.get('roomId'),
        roomType: dataController.connectionInfo.get('roomType'),
        chatId: dataController.connectionInfo.get('chatId'),
        contactId: window.localStorage.getItem('i'),
        origin: encodeURIComponent(chatModel.get('origin'))
      });
      var url = "".concat(this.settings.get('pureServerUrl') || config_production_default.a.dashboardRootUrl, "/visitorwidget/chatwindow?").concat(params);
      window.openedWindow = window.open(url, 'purechatwindow', 'menubar=no, location=no, resizable=yes, scrollbars=no, status=no, width=480, height=640');
      this.getViewController().trigger('widget:poppedOut');
    }
  }, {
    key: "getOperatorsAvailable",
    value: function getOperatorsAvailable() {
      var chatModel = this.getChatModel();
      return typeof chatModel.get('operatorsAvailable') !== 'undefined' ? chatModel.get('operatorsAvailable') : true;
    }
  }, {
    key: "getInitialTitleResourceKey",
    value: function getInitialTitleResourceKey() {
      var settings = this.getWidgetSettings();
      var isMobile = settings.useMobile() && !settings.isDesktopDimension();
      var isAvailable = this.getOperatorsAvailable();
      if (isMobile && isAvailable) return 'mobile_title_initial';
      if (isMobile && !isAvailable) return 'mobile_title_unavailable_initial';
      if (!isMobile && isAvailable) return 'title_initial';
      return 'title_unavailable_initial';
    }
  }, {
    key: "destroy",
    value: function destroy() {
      var dc = this.getDataController();
      var connectionInfo = dc.connectionInfo;
      this.stopListening(this.options);
      this.stopListening(this.widgetView);
      this.stopListening(connectionInfo);
      this.stopListening(this);
    }
  }, {
    key: "triggerMethod",
    value: function triggerMethod() {
      return this._triggerMethod(this, arguments);
    }
  }, {
    key: "_triggerMethod",
    value: function _triggerMethod(context, event, args) {
      var noEventArg = arguments.length < 3;

      if (noEventArg) {
        args = event;
        event = args[0];
      } // get the method name from the event name


      var methodName = 'on' + event.replace(splitter, getEventName);
      var method = this[methodName];
      var result; // call the onMethodName if it exists

      if (no_conflict["c" /* _ */].isFunction(method)) {
        // pass all args, except the event name
        result = method.apply(this, noEventArg ? no_conflict["c" /* _ */].rest(args) : args);
      } // trigger the event, if a trigger method exists


      if (no_conflict["c" /* _ */].isFunction(this.trigger)) {
        if (noEventArg + args.length > 1) {
          this.trigger.apply(this, noEventArg ? args : [event].concat(no_conflict["c" /* _ */].drop(args, 0)));
        } else {
          this.trigger(event);
        }
      }

      return result;
    }
  }]);

  return PCWidgetState;
}();

/* harmony default export */ var states_PCWidgetState = (PCWidgetState_PCWidgetState);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateActivating.js
function PCStateActivating_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateActivating_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateActivating_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateActivating_typeof(obj); }

function PCStateActivating_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateActivating_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateActivating_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateActivating_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateActivating_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateActivating_possibleConstructorReturn(self, call) { if (call && (PCStateActivating_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateActivating_assertThisInitialized(self); }

function PCStateActivating_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function PCStateActivating_getPrototypeOf(o) { PCStateActivating_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateActivating_getPrototypeOf(o); }

function PCStateActivating_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateActivating_setPrototypeOf(subClass, superClass); }

function PCStateActivating_setPrototypeOf(o, p) { PCStateActivating_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateActivating_setPrototypeOf(o, p); }



/*
The activating state. Presents a loading/please-wait screen to the user, then makes the necessary handshakes to connect to a chat room.

If userId and authToken are specified, this will connect to the chat server with those credentials. If they are not specified, this
will connect to Pure Server to obtain those credentials before connecting to the chat server.
*/

var PCStateActivating_PCStateActivating =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateActivating_inherits(PCStateActivating, _PCWidgetState);

  function PCStateActivating() {
    PCStateActivating_classCallCheck(this, PCStateActivating);

    return PCStateActivating_possibleConstructorReturn(this, PCStateActivating_getPrototypeOf(PCStateActivating).apply(this, arguments));
  }

  PCStateActivating_createClass(PCStateActivating, [{
    key: "onEnter",
    value: function onEnter() {
      states_PCWidgetState.prototype.onEnter.apply(this, arguments);
      this.showConnectingWithTimeout();
      this.clearConnectingTimeout();
      this.getChatModel().set('state', constants["a" /* default */].WidgetStates.Chatting);
    }
  }, {
    key: "name",
    get: function get() {
      return 'activating';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        UiVisiblity: {}
      };
    }
  }]);

  return PCStateActivating;
}(states_PCWidgetState);

/* harmony default export */ var states_PCStateActivating = (PCStateActivating_PCStateActivating);
// EXTERNAL MODULE: ./Scripts/constants/index.js + 1 modules
var Scripts_constants = __webpack_require__(25);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/views/emoji_picker.view.js + 1 modules
var emoji_picker_view = __webpack_require__(621);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/models/emojis.collection.js + 1 modules
var emojis_collection = __webpack_require__(217);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/views/emoji_list.view.js + 1 modules
var emoji_list_view = __webpack_require__(302);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/emojis.json
var emojis = __webpack_require__(204);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/emoji_autocomplete.html
var emoji_autocomplete = __webpack_require__(657);
var emoji_autocomplete_default = /*#__PURE__*/__webpack_require__.n(emoji_autocomplete);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/emoji_autocomplete.view.js






var COLUMNS = 10;
var MAX_RESULTS = 30;
var EmojiAutocompleteView = no_conflict["b" /* Marionette */].LayoutView.extend({
  template: emoji_autocomplete_default.a,
  className: 'purechat-card purechat-card-flex purechat-card-bordered',
  regions: {
    filteredList: '.purechat-filtered-emojis'
  },
  childEvents: {
    emojiSelected: 'emojiSelected',
    emojiHovered: 'emojiHovered'
  },
  ui: {
    footer: '.purechat-card-footer'
  },
  onRender: function onRender() {
    this.updateList(this.getOption('filter'));
  },
  emojiHovered: function emojiHovered(view, model) {
    this.collection.each(function (m) {
      return m.set('selected', false);
    });
    model.set('selected', true);
  },
  emojiSelected: function emojiSelected(view, model) {
    this.triggerMethod('emojiSelected', model);
  },
  selectNext: function selectNext() {
    this.collection.selectNext();
  },
  selectPrev: function selectPrev() {
    this.collection.selectPrev();
  },
  selectUp: function selectUp() {
    this.collection.selectPrev(COLUMNS);
  },
  selectDown: function selectDown() {
    this.collection.selectNext(COLUMNS);
  },
  getSelected: function getSelected() {
    return this.collection.findWhere({
      selected: true
    });
  },
  updateList: function updateList(filter) {
    if (this.collection) this.stopListening(this.collection);
    this.collection = this.createFilteredCollection(filter);
    this.listenTo(this.collection, 'change', this.updateFooterText.bind(this));
    if (this.collection.length > 0) this.collection.first().set('selected', true);
    var view = new emoji_list_view["a" /* default */]({
      collection: this.collection
    });
    this.showChildView('filteredList', view);
  },
  createFilteredCollection: function createFilteredCollection(filter) {
    var filteredEmojis = no_conflict["c" /* _ */].take(emojis.filter(function (emoji) {
      return emoji.names.some(function (name) {
        return name.indexOf(filter) > -1;
      }) || emoji.tags.some(function (tag) {
        return tag.indexOf(filter) > -1;
      });
    }).map(function (emoji) {
      emoji.selected = false;
      return emoji;
    }), MAX_RESULTS);

    return new emojis_collection["a" /* default */](filteredEmojis);
  },
  updateFooterText: function updateFooterText() {
    var selectedEmoji = this.collection.findWhere({
      selected: true
    });
    if (!selectedEmoji) return;
    var text = "".concat(selectedEmoji.get('emoji'), "&nbsp;:").concat(selectedEmoji.get('names')[0], ":");
    this.ui.footer.html(text);
  },
  isEmpty: function isEmpty() {
    return this.collection.length === 0;
  }
});
/* harmony default export */ var emoji_autocomplete_view = (EmojiAutocompleteView);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/views/message_list.view.js + 11 modules
var message_list_view = __webpack_require__(312);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/autocomplete.view.js



var KEY_CODES = {
  UP: 38,
  DOWN: 40,
  ENTER: 13,
  ESCAPE: 27
};

var escapeRegExp = function escapeRegExp(text) {
  return String(text).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
};

var AutocompleteItemView = no_conflict["b" /* Marionette */].ItemView.extend({
  tagName: 'li',
  template: no_conflict["c" /* _ */].template('<%= obj.name %>'),
  events: {
    'click': 'select',
    'mouseover': 'highlight'
  },
  highlight: function highlight() {
    var parent = this.getOption('parent');
    parent.highlight(this.$el);
  },
  select: function select() {
    var parent = this.getOption('parent');
    parent.select(this.model);
    parent.hide();
    return false;
  }
});
var AutocompleteView = no_conflict["b" /* Marionette */].ItemView.extend({
  tagName: 'ul',
  className: 'text-small',
  template: false,
  wait: 100,
  currentPhrase: null,
  minLength: 1,
  isVisible: false,
  views: [],
  initialize: function initialize(options) {
    no_conflict["c" /* _ */].extend(this, options);

    this.filterCollection = no_conflict["c" /* _ */].throttle(this.filterCollection, this.wait);
  },
  onRender: function onRender() {
    this.input.attr('autocomplete', 'off');
    this.input.on('keyup.purechat-autocomplete', this.keyup.bind(this)).on('keydown.purechat-autocomplete', this.keydown.bind(this));
    jquery_default()(document).on('click.purechat-autocomplete', this.onWindowClick.bind(this));
  },
  onDestroy: function onDestroy() {
    this.input.off('.purechat-autocomplete');
    jquery_default()(document).off('.purechat-autocomplete');
  },
  keyup: function keyup() {
    var phrase = this.input.val();
    if (!this.isChanged(phrase)) return;

    if (this.isValid(phrase)) {
      this.filterCollection(phrase);
    } else {
      this.hide();
    }

    this.currentPhrase = phrase;
  },
  keydown: function keydown(e) {
    if (!this.isVisible) return;
    if (e.keyCode === KEY_CODES.UP) return this.move(-1);
    if (e.keyCode === KEY_CODES.DOWN) return this.move(1);
    if (e.keyCode === KEY_CODES.ENTER && !e.shiftKey) return this.onEnter();
    if (e.keyCode === KEY_CODES.ESCAPE) return this.hide();
  },
  onEnter: function onEnter() {
    this.$el.children('.purechat-highlight').click();
    this.input.parents('form').trigger('submit');
    return false;
  },
  onWindowClick: function onWindowClick(e) {
    if (jquery_default.a.contains(this.$el.get(0), e.target)) return;
    this.hide();
  },
  filterCollection: function filterCollection(phrase) {
    var _this = this;

    var matchStart = window.CurrentUser.get('cannedResponseSettings').get('MatchStartOfCannedResponse');
    var term = "".concat(matchStart ? '^' : '').concat(escapeRegExp(phrase));
    var matcher = new RegExp(term, 'im');
    var filtered = this.collection.toArray().filter(function (model) {
      var isMatchingWidget = !model.get('widgetId') || model.get('widgetId') === _this.getOption('widgetId');

      if (!isMatchingWidget) return false;
      return matcher.test(model.get('title')) || matcher.test(model.label());
    });
    this.loadResult(filtered);
  },
  loadResult: function loadResult(model) {
    this.show().reset();

    if (model.length) {
      model.forEach(this.addItem.bind(this));
      this.show();
    } else {
      this.hide();
    }
  },
  addItem: function addItem(model) {
    var view = new AutocompleteItemView({
      model: model,
      parent: this
    });
    this.$el.append(view.render().$el);
    this.views.push(view);
  },
  move: function move(delta) {
    var current = this.$el.children('.purechat-highlight');
    var siblings = this.$el.children();
    var index = current.index() + delta;
    if (delta === -1 && current.length === 0) index = siblings.length - 1;
    if (index === siblings.length) index = 0;
    var next = siblings.eq(index);

    if (next.length > 0) {
      current.removeClass('purechat-highlight');
      siblings.eq(index).addClass('purechat-highlight');
      this.scrollIntoView(next);
    }

    return false;
  },
  highlight: function highlight(el) {
    var current = this.$el.children('.purechat-highlight');
    current.removeClass('purechat-highlight');
    el.addClass('purechat-highlight');
  },
  isChanged: function isChanged(phrase) {
    return this.currentPhrase !== phrase;
  },
  isValid: function isValid() {
    var phrase = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    return phrase.length > this.minLength;
  },
  select: function select(model) {
    var value = model.label(); // This is done so that the cursor goes to the end of the text.

    this.input.focus();
    this.input.val('');
    this.input.val(value.trim());
    this.currentPhrase = value;
    this.onSelect(model);
  },
  reset: function reset() {
    this.views.forEach(function (view) {
      return view.destroy();
    });
    this.$el.empty();
    this.views = [];
  },
  hide: function hide() {
    this.triggerMethod('hideAutocomplete');
    this.isVisible = false;
    return this;
  },
  show: function show() {
    this.triggerMethod('showAutocomplete');
    this.isVisible = true;
    return this;
  },
  scrollIntoView: function scrollIntoView(element) {
    var parentHeight = this.getOption('parent').height();
    var elementTop = element.position().top;
    var elementBottom = elementTop + element.outerHeight();
    var isVisible = elementTop >= 0 && elementBottom <= parentHeight;
    if (isVisible) return;
    var el = element.get(0);
    if (elementTop < 0 && elementBottom <= parentHeight) return el.scrollIntoView(true);
    if (elementTop >= 0 && elementBottom > parentHeight) return el.scrollIntoView(false);
  },
  onSelect: function onSelect() {},
  onClose: function onClose() {}
});
/* harmony default export */ var autocomplete_view = (AutocompleteView);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/emots.json
var emots = __webpack_require__(658);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/message_list_wrapper.html
var message_list_wrapper = __webpack_require__(659);
var message_list_wrapper_default = /*#__PURE__*/__webpack_require__.n(message_list_wrapper);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/message_list_wrapper.view.js
/* eslint-disable no-invalid-this */












var EMOJI_REGEX = new RegExp('([\\s.]|&nbsp;|^)(\:[a-z_]{2,})(?=[\\s.]|&nbsp;|$)', 'gim');
var COLON_REGEX = new RegExp('(^:|:$)', 'gim');
var OPERATOR_TEXTAREA_MAX_HEIGHT = 171;
var TEXTAREA_MAX_HEIGHT = 66; // font-size * line-height * rows

var TWO_SECONDS = 2000;
var RESIZE_THROTTLE = 200;
var K_CODE = [38, 38, 40, 40, 37, 39, 37, 39]; // eslint-disable-line no-magic-numbers

var FORM_BORDER_WIDTH = 2;
var AutocompleteViewCollection = no_conflict["a" /* Backbone */].Collection.extend({
  model: no_conflict["a" /* Backbone */].Model.extend({
    label: function label() {
      return this.get('name');
    }
  })
});
var MessageListWrapperView = no_conflict["b" /* Marionette */].LayoutView.extend({
  template: message_list_wrapper_default.a,
  className: 'purechat-message-list-view',
  cannedResponseCollection: null,
  regions: {
    messages: '.purechat-messages',
    autocomplete: '.purechat-autocomplete',
    emojis: '.purechat-emojis',
    emojiAutocomplete: '.purechat-emoji-autocomplete'
  },
  ui: {
    textInput: 'textarea',
    form: 'form',
    userStatus: '.purechat-user-status',
    showPrevious: '.purechat-showPrevious',
    filePicker: '.purechat-file-picker',
    autocomplete: '.purechat-autocomplete'
  },
  templateHelpers: function templateHelpers() {
    var settings = this.getOption('settings');
    return {
      isFileTransferEnabled: function isFileTransferEnabled() {
        return settings.isFileTransferEnabled();
      },
      isMobile: function isMobile() {
        return settings.useMobile() && !settings.isDesktopDimension();
      },
      isOperator: function isOperator() {
        return settings.get('isOperator');
      },
      isInvisible: function isInvisible() {
        return settings.get('isInvisible');
      },
      iconRootUrl: function iconRootUrl() {
        return utils["a" /* default */].iconRootUrl(settings.get('isDemo'));
      },
      svgHrefAttr: function svgHrefAttr() {
        return utils["a" /* default */].svgHrefAttr();
      }
    };
  },
  modelEvents: {
    change: function change(model) {
      this.triggerMethod('roomHostChanged', model);
    }
  },
  events: {
    'keydown textarea': 'keyDown',
    'keyup textarea': 'keyUp',
    'paste textarea': 'handlePaste',
    'submit form': 'postMessage',
    'click form': function formClick(e) {
      if (e.target.tagName.toLowerCase() !== 'button') {
        this.ui.textInput.get(0).focus();
        if (!this.options.settings.get('isOperator')) this.hideEmojis();
      }
    },
    'click .purechat-btn-emoji': 'showEmojis',
    'click .purechat-btn-file-transfer': 'showFilePicker',
    'change @ui.filePicker': 'fileSelected',
    'refreshAutoCompleteSource textarea': function textAreaRefresh() {
      var region = this.getRegion('autocomplete');

      if (region.hasView()) {
        region.currentView.hide();
        var responses = new AutocompleteViewCollection(window.CurrentUser.get('cannedResponses').toAutocompleteList());
        region.currentView.collection = responses;
      }
    },
    'disableAutoComplete textarea': function textAreaDisableAutoComplete() {
      if (this.getRegion('autocomplete').hasView()) {
        this.getRegion('autocomplete').reset();
      }
    },
    'enableAutoComplete textarea': function textAreaEnabledAutoComplete() {
      if (!this.getRegion('autocomplete').hasView()) {
        this.renderAutocomplete();
      }
    },
    'resize textarea': 'resizeTextArea'
  },
  childEvents: {
    showPrevious: function showPrevious() {
      this.trigger('showPrevious');
    },
    emojiSelected: function emojiSelected(view, model) {
      var val = this.ui.textInput.val();
      var emoji = model.get('emoji');

      if (this.emojiMatch) {
        this.replaceEmojiAutocompleteText(emoji);
        this.hideEmojiAutocomplete();
      } else {
        this.ui.textInput.val(val + model.get('emoji')).focus();
        this.hideEmojis();
      }
    },
    hideAutocomplete: function hideAutocomplete() {
      this.ui.autocomplete.purechatDisplay('none');
    },
    showAutocomplete: function showAutocomplete() {
      var formHeight = this.$('.purechat-send-form').outerHeight();
      this.ui.autocomplete.css({
        bottom: "".concat(formHeight + FORM_BORDER_WIDTH, "px")
      });
      this.ui.autocomplete.purechatDisplay('block');
    }
  },
  getLastMessageWithId: function getLastMessageWithId(currentMessageId) {
    var last = null;
    this.collection.forEach(function (model) {
      if (model.get('userId') && model.get('messageId') !== currentMessageId) {
        last = model;
      }
    });
    return last;
  },
  initialize: function initialize() {
    var _this = this;

    if (window.PureChatEvents) {
      this.listenTo(window.PureChatEvents.bus, 'dashboard:layout:chat-selected', this.onShow);
    }

    this.getOption('viewController').on('widget:click', function (e) {
      if (!jquery_default()(e.target).hasClass('purechat-btn-emoji')) {
        _this.hideEmojis();
      }
    });
    this.kCodePosition = -1;
  },
  onDestroy: function onDestroy() {
    jquery_default()(window).off('resize.ScrollToTopMobile');
    this.$el.find('.purechat-message-display').off('scroll');
    this.getOption('viewController').off('widget:click');
  },
  renderMessageListView: function renderMessageListView() {
    var chatModel = no_conflict["b" /* Marionette */].getOption(this, 'chatModel');
    var rm = no_conflict["b" /* Marionette */].getOption(this, 'rm');
    var settings = no_conflict["b" /* Marionette */].getOption(this, 'settings');
    var viewController = no_conflict["b" /* Marionette */].getOption(this, 'viewController');
    this.showChildView('messages', new message_list_view["a" /* default */]({
      rm: rm,
      model: chatModel,
      collection: chatModel.get('messages'),
      settings: settings,
      viewController: viewController,
      chatModel: chatModel
    }));
  },
  renderEmojiView: function renderEmojiView() {
    if (this.options.settings.get('isOperator')) return;
    this.showChildView('emojis', new emoji_picker_view["a" /* default */]({
      viewController: this.getOption('viewController'),
      registerClose: true
    }));
  },
  renderAutocomplete: function renderAutocomplete() {
    var _this2 = this;

    var rm = no_conflict["b" /* Marionette */].getOption(this, 'rm');
    this.showChildView('autocomplete', new autocomplete_view({
      collection: new AutocompleteViewCollection(this.cannedResponseCollection),
      input: this.ui.textInput,
      parent: this.ui.autocomplete,
      widgetId: rm.get('room').widgetId,
      onSelect: function onSelect() {
        return _this2.resizeTextArea();
      }
    }));
  },
  onRender: function onRender() {
    var isOperator = this.options.settings.get('isOperator');
    this.renderMessageListView();
    this.renderEmojiView();

    if (isOperator) {
      this.cannedResponseCollection = window.CurrentUser.get('cannedResponses');

      if (window.CurrentUser.get('cannedResponses').length === 0) {
        this.cannedResponseCollection = this.options.settings.get('cannedResponses').filter(function (response) {
          return response.content !== '===separator===';
        }).map(function (response) {
          return {
            title: response.name,
            name: jquery_default()('<div/>').html(response.content).text(),
            widgetId: response.get('WidgetId')
          };
        });
      } else {
        this.cannedResponseCollection = window.CurrentUser.get('cannedResponses').toAutocompleteList();
      }

      this.renderAutocomplete();
    }

    this.getRegion('emojis').$el.purechatDisplay('none');
  },
  onShow: function onShow() {
    var _this3 = this;

    no_conflict["c" /* _ */].defer(function () {
      if (_this3.ui.textInput.is(':visible')) _this3.ui.textInput.focus();
    });
  },
  keyDown: function keyDown(e) {
    this.resizeTextArea();
    var emojiAutocompleteRegion = this.getRegion('emojiAutocomplete');

    if (e.keyCode === constants["a" /* default */].KeyCodes.Enter && !e.shiftKey) {
      if (e.ctrlKey) {
        this.ui.textInput.val(this.ui.textInput.val() + '\n');
        return true;
      } else if (emojiAutocompleteRegion.hasView()) {
        // get selected emoji, replace text in textarea with emoji,
        var selectedEmoji = emojiAutocompleteRegion.currentView.getSelected();
        this.replaceEmojiAutocompleteText(selectedEmoji.get('emoji'));
        this.hideEmojiAutocomplete();
        return false;
      } else {
        this.triggerMethod('typingChange', false);
        this.activity = false;
        this.ui.form.submit();
        return false;
      }
    }

    var keyCodes = constants["a" /* default */].KeyCodes;
    var emojiAutoCompleteKeys = [keyCodes.Enter, keyCodes.Escape, keyCodes.LeftArrow, keyCodes.RightArrow, keyCodes.UpArrow, keyCodes.DownArrow, keyCodes.Tab];

    if (emojiAutocompleteRegion.hasView() && emojiAutoCompleteKeys.indexOf(e.keyCode) > -1) {
      e.preventDefault();
      e.stopPropagation();
      return false;
    }

    return true;
  },
  keyUp: function keyUp(e) {
    var _this4 = this;

    if (this.typingTimeout) {
      clearTimeout(this.typingTimeout);
      this.typingTimeout = null;
    }

    this.typingTimeout = setTimeout(function () {
      try {
        var activity = _this4.ui.textInput.val().length > 0;
        _this4.activity = activity;

        _this4.triggerMethod('typingChange', activity);
      } catch (ex) {
        /* Do Nothing */
      }
    }, TWO_SECONDS);

    if (this.ui.textInput.val() && !this.activity) {
      this.triggerMethod('typingChange', true);
      this.activity = true;
    }

    var emojiAutocompleteRegion = this.getRegion('emojiAutocomplete');

    if (!emojiAutocompleteRegion.hasView()) {
      this.checkForEmojiAutocomplete(this.ui.textInput.val());
    } else {
      switch (e.keyCode) {
        case constants["a" /* default */].KeyCodes.Escape:
          this.hideEmojiAutocomplete();
          break;

        case constants["a" /* default */].KeyCodes.LeftArrow:
          emojiAutocompleteRegion.currentView.selectPrev();
          break;

        case constants["a" /* default */].KeyCodes.UpArrow:
          emojiAutocompleteRegion.currentView.selectUp();
          break;

        case constants["a" /* default */].KeyCodes.RightArrow:
          emojiAutocompleteRegion.currentView.selectNext();
          break;

        case constants["a" /* default */].KeyCodes.DownArrow:
          emojiAutocompleteRegion.currentView.selectDown();
          break;

        case constants["a" /* default */].KeyCodes.Tab:
          if (e.shiftKey) {
            emojiAutocompleteRegion.currentView.selectPrev();
          } else {
            emojiAutocompleteRegion.currentView.selectNext();
          }

          break;

        default:
          this.checkForEmojiAutocomplete(this.ui.textInput.val());
      }

      this.updateKCodePosition(e.keyCode);
    }
  },
  handlePaste: function handlePaste(e) {
    var _this5 = this;

    if (!this.options.settings.isFileTransferEnabled()) return;
    var items = e.originalEvent.clipboardData.items;

    if (!items) {
      this.resizeTextArea();
      return;
    }

    var service = this.getOption('viewController').getDataController();
    Array.prototype.forEach.call(items, function (item) {
      // Firefox supports just copying a file, so when pasting strings, we need
      // to check for that explicitly, and on the next tick, resize the text area
      // when the text is pasted in. Le sigh
      if (item.type === 'text/plain' && item.kind === 'string') {
        setTimeout(function () {
          return _this5.resizeTextArea();
        }, 0);
        return;
      }

      if (item.type.indexOf('image/') !== 0) return;
      var file = item.getAsFile();
      if (!file) return;

      var isOperator = _this5.options.settings.get('isOperator');

      if (isOperator && window.PureChatEvents) {
        window.PureChatEvents.trigger('dashboard:chats:image-pasted', {
          file: file,
          onUpload: function onUpload() {
            return service.upload(file);
          }
        });
      } else {
        service.upload(file);
      }
    });
  },
  resizeTextArea: no_conflict["c" /* _ */].throttle(function () {
    var _this6 = this;

    var el = this.ui.textInput.get(0);
    var isOperator = this.options.settings.get('isOperator');
    var isIE = !isOperator && this.options.settings.get('BrowserDetails').Browser === 'InternetExplorer';
    window.requestAnimationFrame(function () {
      if (!el) return;
      el.style.cssText = 'height:auto !important; padding:0 !important;';
      var height = el.scrollHeight - (isIE && el.value.length > 0 ? 1 : 0);
      var maxHeight = isOperator ? OPERATOR_TEXTAREA_MAX_HEIGHT : TEXTAREA_MAX_HEIGHT;
      if (height === el.offsetHeight) return;
      var newCss = "height:".concat(height, "px !important;max-height:").concat(maxHeight, "px !important;");

      if ((isIE || isOperator) && el.scrollHeight > maxHeight) {
        newCss += '-ms-overflow-style:scrollbar !important;';
      }

      el.style.cssText = newCss;

      if (isOperator) {
        var formHeight = _this6.$('.purechat-send-form').outerHeight();

        _this6.ui.autocomplete.css({
          bottom: "".concat(formHeight + FORM_BORDER_WIDTH, "px")
        });
      }
    });
  }, RESIZE_THROTTLE),
  convertLegacyEmotsToEmoji: function convertLegacyEmotsToEmoji(message) {
    var emotified = message;
    emots.forEach(function (emot) {
      if (!emot.deprecated) {
        var regex = new RegExp("([\\s.]|&nbsp;|^)(".concat(emot.regex, ")(?=[\\s.]|&nbsp;|$)"), 'gim');
        var matches = message.match(regex);

        if (matches) {
          matches.forEach(function (match) {
            emotified = emotified.replace(match.trim(), emot.emoji);
          });
        }
      }
    });
    return emotified;
  },
  replaceMessageVariables: function replaceMessageVariables(message) {
    var settings = no_conflict["b" /* Marionette */].getOption(this, 'settings'); // Only support variables for the operator side of the chat.

    if (!settings.get('isOperator')) return message;
    var rm = no_conflict["b" /* Marionette */].getOption(this, 'rm');
    var room = rm.get('room'); // Only do this for visitor rooms

    if (room.roomType !== Scripts_constants["k" /* RoomType */].Visitor) return message;
    return message.replace(/{visitorName}/gi, room.visitorFirstName).replace(/{visitorEmail}/gi, room.visitorEmail).replace(/{pageName}/gi, room.visitorReferer).replace(/{websiteName}/gi, room.widgetName).replace(/{operatorName}/gi, rm.get('userDisplayName')).replace(/{operatorEmail}/gi, window.CurrentUser.get('email')).replace(/{companyName}/gi, window.Session.get('Company'));
  },
  postMessage: function postMessage(e) {
    e.stopPropagation();
    e.preventDefault();
    var emotified = this.convertLegacyEmotsToEmoji(this.ui.textInput.val());
    var replaced = this.replaceMessageVariables(emotified);
    this.triggerMethod('newMessage', replaced);
    this.ui.textInput.val('');
    this.ui.autocomplete.purechatDisplay('none');
    this.resizeTextArea();
  },
  typing: function typing(userId, userDisplayName, isTyping) {
    this.model.get('participants').set({
      userId: userId,
      displayName: userDisplayName,
      isTyping: isTyping
    }, {
      remove: false
    });
    this.ui.userStatus.html(this.model.get('participants').getOperatorTypingText(this, this.model.get('isOperator')));
  },
  showEmojis: function showEmojis() {
    var emojiRegion = this.getRegion('emojis');
    emojiRegion.$el.purechatDisplay('flex');
    emojiRegion.currentView.open();
  },
  hideEmojis: function hideEmojis() {
    var emojiRegion = this.getRegion('emojis');
    emojiRegion.$el.purechatDisplay('none');
    emojiRegion.currentView.close();
  },
  checkForEmojiAutocomplete: function checkForEmojiAutocomplete(value) {
    var matches = value.match(EMOJI_REGEX);

    if (!matches || matches.length === 0) {
      this.hideEmojiAutocomplete();
      return;
    }

    this.emojiMatch = no_conflict["c" /* _ */].first(matches).trim();
    this.showEmojiAutocomplete();
  },
  showEmojiAutocomplete: function showEmojiAutocomplete() {
    var region = this.getRegion('emojiAutocomplete');
    var filter = this.emojiMatch.replace(COLON_REGEX, '');
    if (region.hasView()) region.currentView.destroy();
    var view = new emoji_autocomplete_view({
      filter: filter
    });
    this.showChildView('emojiAutocomplete', view);
    region.$el.purechatDisplay('flex');

    if (region.currentView.isEmpty()) {
      this.hideEmojiAutocomplete();
    }
  },
  hideEmojiAutocomplete: function hideEmojiAutocomplete() {
    var region = this.getRegion('emojiAutocomplete');
    if (!region.hasView()) return;
    region.$el.purechatDisplay('none');
    region.currentView.destroy();
    this.emojiMatch = null;
  },
  replaceEmojiAutocompleteText: function replaceEmojiAutocompleteText(emoji) {
    var value = this.ui.textInput.val();
    this.ui.textInput.val(value.replace(this.emojiMatch, emoji)).focus();
  },
  showFilePicker: function showFilePicker() {
    this.ui.filePicker.click();
  },
  fileSelected: function fileSelected() {
    if (!this.ui.filePicker.val()) return;
    if (!this.options.settings.isFileTransferEnabled()) return;
    var service = data_singleton["a" /* default */].getInstance();
    Array.prototype.forEach.call(this.ui.filePicker.get(0).files, function (file) {
      service.upload(file);
    });
    this.ui.filePicker.val(null);
  },
  updateKCodePosition: function updateKCodePosition(keyCode) {
    var region = this.getRegion('emojiAutocomplete');

    if (!region.hasView()) {
      this.kCodePosition = -1;
      return;
    }

    var next = K_CODE[this.kCodePosition + 1];

    if (next === keyCode) {
      this.kCodePosition += 1;
    } else {
      this.kCodePosition = -1;
    }

    if (this.kCodePosition === K_CODE.length - 1) {
      this.replaceEmojiAutocompleteText('🕹️');
      this.hideEmojiAutocomplete();
      this.kCodePosition = -1;
    }
  }
});
/* harmony default export */ var message_list_wrapper_view = (MessageListWrapperView);
// EXTERNAL MODULE: ./Content/images/avatars/1avatar-operator-skinny.png
var _1avatar_operator_skinny = __webpack_require__(318);
var _1avatar_operator_skinny_default = /*#__PURE__*/__webpack_require__.n(_1avatar_operator_skinny);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateChatting.js
function PCStateChatting_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateChatting_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateChatting_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateChatting_typeof(obj); }

function PCStateChatting_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateChatting_possibleConstructorReturn(self, call) { if (call && (PCStateChatting_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateChatting_assertThisInitialized(self); }

function PCStateChatting_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }

function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = PCStateChatting_getPrototypeOf(object); if (object === null) break; } return object; }

function PCStateChatting_getPrototypeOf(o) { PCStateChatting_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateChatting_getPrototypeOf(o); }

function PCStateChatting_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateChatting_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateChatting_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateChatting_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateChatting_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateChatting_setPrototypeOf(subClass, superClass); }

function PCStateChatting_setPrototypeOf(o, p) { PCStateChatting_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateChatting_setPrototypeOf(o, p); }










var ONE_THOUSAND = 1000;
var CLOSE_CHAT_THROTTLE = 800;
var SAFARI_CONFIRMATION_TIMEOUT = 500;

var PCStateChatting_htmlDecode = function htmlDecode(value) {
  return jquery_default()('<div/>').html(value).text();
};

var PCStateChatting_PCStateChatting =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateChatting_inherits(PCStateChatting, _PCWidgetState);

  PCStateChatting_createClass(PCStateChatting, [{
    key: "name",
    get: function get() {
      return 'chatting';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        shouldBeInRoom: true,
        UiVisiblity: {
          popoutButton: true,
          closeButton: true,
          requeueButton: true,
          cannedResponsesButton: true
        }
      };
    }
  }]);

  function PCStateChatting(options) {
    var _this;

    PCStateChatting_classCallCheck(this, PCStateChatting);

    _this = PCStateChatting_possibleConstructorReturn(this, PCStateChatting_getPrototypeOf(PCStateChatting).call(this, options));
    _this.typing = {};
    _this.isUserAlone = true;
    _this.mobileAnimationInterval = null;
    _this.noOperatorMessageTimeout = null;
    _this.onCloseChat = no_conflict["c" /* _ */].throttle(_this.onCloseChat.bind(PCStateChatting_assertThisInitialized(_this)), CLOSE_CHAT_THROTTLE, {
      trailing: false
    });
    return _this;
  }

  PCStateChatting_createClass(PCStateChatting, [{
    key: "onEnter",
    value: function onEnter() {
      var _this2 = this;

      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      states_PCWidgetState.prototype.onEnter.apply(this, args);
      var startImmediately = this.options.get('StartChatImmediately');
      var isMobile = this.options.get('RequestFromMobileDevice') && (this.options.get('poppedOut') || this.options.get('isDirectAccess'));
      this.getWidgetView().$el.purechatDisplay(); // This needs to be created ahead of time because as soon as
      // we connect the chat server will start sending messages

      var chatModel = this.getChatModel();
      chatModel.set({
        RequestFromMobileDevice: this.options.get('RequestFromMobileDevice')
      });
      this.messageView = new message_list_wrapper_view({
        rm: this.getResources(),
        model: chatModel,
        collection: this.getChatModel().get('messages'),
        settings: this.getWidgetSettings(),
        viewController: this.getViewController(),
        chatModel: this.getChatModel()
      });
      this.getWidgetView().showChildView('content', this.messageView);
      this.listenTo(this.messageView, 'showPrevious', function () {
        if (_this2.chatModel.get('PreviousTranscriptId')) {
          _this2.getDataController().getPreviousChat({
            chatId: _this2.chatModel.get('PreviousTranscriptId')
          }).done(function (previousChatResult) {
            _this2.appendPreviousChatResults(previousChatResult);
          });
        }
      });
      this.showConnectingWithTimeout();
      var chatId = this.getDataController().connectionInfo.get('roomId');
      var widgetId = this.getDataController().getOption('widgetId');
      var accountId = this.settings.get('AccountId');
      var chatServerUrl = this.getDataController().connectionInfo.get('chatServerUrl');
      logger["a" /* default */].log(logger["a" /* default */].LEVELS.DEBUG, "Attempting to connect to chat server WidgetId: ".concat(widgetId, ", ChatId: ").concat(chatId, ", AccountId: ").concat(accountId), '', false, chatServerUrl, '');
      this.getDataController().connectToChatServer(this).done(function () {
        _this2.clearConnectingTimeout();

        try {
          var hasOperators = _this2.chatModel.get('operators') && _this2.chatModel.get('operators').length > 0;
          var isProactiveChat = _this2.status && _this2.status.initialData && _this2.status.initialData.initiator && _this2.status.initialData.initiator === 1;

          if (!_this2.chatModel.get('isOperator') && !hasOperators && !isProactiveChat) {
            var d = new Date();
            d.setTime(0);

            _this2.chatModel.get('messages').add({
              date: d,
              type: startImmediately ? constants["a" /* default */].MessageTypes.Message : constants["a" /* default */].MessageTypes.Note,
              message: _this2.getResource('chat_startedMessage'),
              resourceKey: 'chat_startedMessage',
              avatarUrl: isMobile ? _1avatar_operator_skinny_default.a : null
            });
          }

          if (no_conflict["c" /* _ */].isFunction(_this2.getDataController().setCurrentPage) && !_this2.options.get('isOperator')) {
            _this2.getDataController().setCurrentPage(document.location.href);
          }

          _this2.messageView.on('newMessage', function (message) {
            return _this2.getDataController().newMessage(message);
          });

          _this2.listenTo(_this2.messageView, 'typingChange', function (typing) {
            return _this2.getDataController().setTypingIndicator(typing);
          });

          _this2.getWidgetView().$el.find('.purechat-start-chat-button-container button').html('Back to Chat<i style="margin-left: .5em;" class="fa fa-chevron-right"></i>');

          _this2.getWidgetView().onShow();

          _this2.getDataController().sendRoomHistory();

          _this2.getViewController().trigger('stateChanged', constants["a" /* default */].WidgetStates.Chatting);

          if (_this2.settings.get('RequestFromMobileDevice') && _this2.settings.get('MobileDisplayType') === constants["a" /* default */].MobileDisplayTypes.MobileOptimized) {
            jquery_default()(window).trigger('resize.ResizeChatContent');

            _this2.getWidgetView().$el.find('.purechat-send-form-message').off('blur.ResizeWindow').on('blur.ResizeWindow', function () {
              jquery_default()(window).trigger('resize.ResizeChatContent');
            });

            if (_this2.options.get('isDirectAccess')) {
              jquery_default()('.direct-container-header').purechatDisplay('none');
            }
          }

          _this2.getWidgetView().trigger('resized');

          var room = _this2.options.get('room');

          if (room && room.closed) {
            chatModel.set('state', constants["a" /* default */].WidgetStates.Closed);
            return;
          }

          _this2.getViewController().trigger('chat:start', chatModel.pick(['visitorEmail', 'visitorName', 'visitorPhoneNumber', 'visitorQuestion', 'visitorFirstName', 'visitorLastName', 'visitorCompany']));

          var settings = _this2.getWidgetSettings(); // If visitor sent message, start a timer to show the no operator message.
          // This timer will get cleared out if an operator joins before it expires.


          if (_this2.isUserAlone && !_this2.chatModel.get('isOperator') && !settings.get('StartChatAutomatically') && !settings.get('AskForQuestion')) {
            var addMessageFnc = function addMessageFnc() {
              var messageDate = new Date();
              messageDate = _this2.convertToUserTime(messageDate);

              _this2.chatModel.get('messages').add({
                date: messageDate,
                type: constants["a" /* default */].MessageTypes.Note,
                message: no_conflict["c" /* _ */].escape(_this2.getResource('chat_noOperatorMessage')),
                resourceKey: 'chat_noOperatorMessage',
                isClosedChat: false
              });

              _this2.chatModel.set('noOperatorMessageSeen', true);
            };

            if (!_this2.noOperatorMessageTimeout) {
              _this2.noOperatorMessageTimeout = setTimeout(addMessageFnc, settings.get('NoOperatorMessageTimeout') * 1000);
            }
          }

          if (_this2.options.get('room') && _this2.options.get('room').roomType !== 1 && !_this2.options.get('room').isDemo) {
            var previousChatDeferred = _this2.getDataController().getPreviousChat({
              chatId: _this2.options.get('room') ? _this2.options.get('room').id : -1
            });

            previousChatDeferred.done(function (previousChatResult) {
              if (previousChatResult) _this2.appendPreviousChatResults(previousChatResult);
            });
          }
        } catch (exception) {
          /* Do Nothing? Not sure what should be done about an error */
        }
      }).fail(function (error) {
        _this2.clearConnectingTimeout(); // Connection failed,  remove the connection state


        _this2.getDataController().connectionInfo.clearLocalStorage();

        _this2.getChatModel().set('state', constants["a" /* default */].WidgetStates.Inactive); // Log connection failed


        _this2.logFailedConnection(error);
      });
      chatModel.on('roomHostChanged', function () {
        // Update the text and avatar in the header, if it exists
        var roomHostAvatarUrl = chatModel.get('roomHostAvatarUrl');
        var roomHostName = chatModel.get('roomHostName');

        _this2.getWidgetView().showRoomHostAvatar(roomHostAvatarUrl);

        _this2.updateRoomHostName(roomHostName);
      });
    }
  }, {
    key: "updateRoomHostName",
    value: function updateRoomHostName(name) {
      var widgetView = this.getWidgetView();

      if (name) {
        widgetView.setExpandedTitle(this.getResource('chat_nowChattingWith', {
          chatUserNames: [name]
        }), 'chat_nowChattingWith');
      } else {
        var titleResourceKey = this.getInitialTitleResourceKey();
        widgetView.setExpandedTitle(this.getResource(titleResourceKey), null, titleResourceKey);
      }
    }
  }, {
    key: "onSelectionShow",
    value: function onSelectionShow() {
      this.messageView.getChildView('messages').updateScroll();
    }
  }, {
    key: "appendPreviousChatResults",
    value: function appendPreviousChatResults(previousChatResult, delayIncrement) {
      var self = this;

      if (previousChatResult) {
        previousChatResult.forEach(function (next) {
          var lastTimeString = null;
          var lastMessage = null;
          var currentDelay = 0;
          next.Records.forEach(function (nextMessage) {
            function triggerOnMessage() {
              if (nextMessage.Type === constants["a" /* default */].MessageTypes.Join) {
                self.onJoined(nextMessage.UserId, nextMessage.Name, -1, nextMessage.Name, nextMessage.DateCreatedJsTicks / ONE_THOUSAND, true, true);
              } else if (nextMessage.Type === constants["a" /* default */].MessageTypes.Leave) {
                self.onLeft(nextMessage.UserId, nextMessage.Name, -1, nextMessage.Name, nextMessage.DateCreatedJsTicks / ONE_THOUSAND, true, true);
              } else {
                self.onMessage({
                  userId: nextMessage.UserId,
                  userDisplayName: nextMessage.Name,
                  roomId: -1,
                  roomDisplayName: nextMessage.Name,
                  time: nextMessage.DateCreatedJsTicks / ONE_THOUSAND,
                  message: nextMessage.Message,
                  isHistory: true,
                  timeElpased: 0,
                  protocolVersion: 0,
                  avatarUrl: nextMessage.AvatarUrl,
                  fromOperator: nextMessage.UserId > 0,
                  roomUtcOffset: 0,
                  type: nextMessage.Type,
                  messageId: 0,
                  isClosedChat: true
                });
              }
            }

            if (delayIncrement) {
              setTimeout(triggerOnMessage, currentDelay);
              currentDelay = currentDelay + delayIncrement;
            } else {
              triggerOnMessage();
            }

            lastTimeString = nextMessage.DateCreatedString + ' at ' + nextMessage.TimeCreatedString;
            lastMessage = nextMessage;
          });

          if (lastTimeString !== null) {
            var addSeparator = function addSeparator() {
              date = self.convertToUserTime(date);
              self.chatModel.get('messages').add({
                date: date,
                type: constants["a" /* default */].MessageTypes.Separator,
                message: lastTimeString,
                isClosedChat: true
              });
            };

            var date = new Date();
            date.setTime(lastMessage.DateCreatedJsTicks);

            if (delayIncrement) {
              setTimeout(addSeparator, currentDelay);
              currentDelay = currentDelay + delayIncrement;
            } else {
              addSeparator();
            }
          }

          self.chatModel.set('PreviousTranscriptId', next.Id);

          if (next.PreviousTranscriptId) {
            self.chatModel.set('HasMoreTransactions', true);
          } else {
            self.chatModel.set('HasMoreTransactions', false);
          }
        });
      }
    }
  }, {
    key: "onExit",
    value: function onExit() {
      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      states_PCWidgetState.prototype.onExit.apply(this, args);
      this.chatModel.get('operators').reset();
      this.chatModel.get('participants').reset();

      if (this.unbindEvents) {
        this.unbindEvents();
      }

      this.getDataController().unbindHandlerEvents();
    }
  }, {
    key: "onRoomChanged",
    value: function onRoomChanged(args) {
      this.onRoomDetailsChanged(args.room);
    } // Throttle this function to prevent people from mashing on the X button
    // over and over again.

  }, {
    key: "onCloseChat",
    value: function onCloseChat() {
      var _this3 = this;

      var settings = this.getWidgetSettings();
      var isMobile = settings.useMobile() && !settings.isDesktopDimension();
      var areYouSure = 'Are you sure you want to end this chat?';

      var onCloseFnc = function onCloseFnc(context) {
        if (context.noOperatorMessageTimeout) {
          clearTimeout(context.noOperatorMessageTimeout);
          context.noOperatorMessageTimeout = null;
        }

        context.getDataController().closeChat().done(function () {
          return context.getChatModel().set('state', constants["a" /* default */].WidgetStates.Closed);
        });
      }; // Safari Mobile will create an invisible overlay that will block all clicks
      // when you display a confirmation dialog. The only way to resolve it is to
      // wait a little bit before displaying it.


      var safariMobileSafeConfirmationDialog = function safariMobileSafeConfirmationDialog() {
        setTimeout(function () {
          if (window.confirm(areYouSure)) onCloseFnc(_this3);
        }, SAFARI_CONFIRMATION_TIMEOUT);
      };

      if (isMobile) {
        safariMobileSafeConfirmationDialog();
      } else {
        onCloseFnc(this);
      }
    }
  }, {
    key: "onExpanded",
    value: function onExpanded() {}
  }, {
    key: "flashMobileNotificationIcon",
    value: function flashMobileNotificationIcon() {
      var self = this;

      if (this.settings.get('RequestFromMobileDevice') && this.settings.get('MobileDisplayType') === constants["a" /* default */].MobileDisplayTypes.MobileOptimized && typeof this.mobileAnimationInterval !== 'number') {
        var elem = this.getWidgetView().$el;
        var triggerElems = elem.hasClass('purechat-widget-collapsed') && elem.find('.purechat-expanded').is(':visible') ? elem : [];

        if (triggerElems.length > 0) {
          var visibleIcon = elem.find('.purechat-title-image-out-of-way-hilight').filter(':visible');
          visibleIcon.addClass('flash');
          var isFlashing = true;
          this.mobileAnimationInterval = setInterval(function () {
            if (isFlashing) {
              visibleIcon.removeClass('flash');
              isFlashing = false;
            } else {
              visibleIcon.addClass('flash');
              isFlashing = true;
            }
          }, 1000);
          triggerElems.off('click.StopNotification').on('click.StopNotification', function (e) {
            var sender = jquery_default()(e.currentTarget);
            self.mobileAnimationInterval = clearInterval(self.mobileAnimationInterval);
            visibleIcon.removeClass('flash');
            triggerElems.off('click.StopNotification');
            sender.trigger('click');
          });
        }
      }
    }
  }, {
    key: "convertToUserTime",
    value: function convertToUserTime(date) {
      if (this.chatModel && this.chatModel.get && this.chatModel.get('isOperator')) {
        // We are on the dashboard, so we can use the CurrentUser to get the UTC offset
        var isInDaylightSavings = window.CurrentUser.get('isInDaylightSavings');
        var utcDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
        return new Date(utcDate.getTime() + (window.CurrentUser.get('accountUtcOffset') + (isInDaylightSavings ? 60 : 0)) * 60000);
      }

      return date;
    }
  }, {
    key: "onMessage",
    value: function onMessage(message) {
      var _this4 = this;

      // If we receive a message with an id that matches and existing message, update it.
      if (message.id) {
        var existingMessage = this.chatModel.get('messages').findWhere({
          id: message.id
        });

        if (existingMessage) {
          existingMessage.set(message);
          return;
        }
      }

      if (this.chatModel.get('isOperator') && message.userId != this.chatModel.get('userId')) {
        notifier.notify('New message!');
      } // Add the message to the display area


      if (message.type !== constants["a" /* default */].MessageTypes.Message || message.message !== null && typeof message.message === 'string') {
        var date = new Date();
        date.setTime(message.time * 1000);
        date = this.convertToUserTime(date);
        var chatMessage = {
          id: message.id,
          date: date,
          type: message.type,
          message: message.message,
          userName: message.userDisplayName,
          myMessage: message.userId === this.chatModel.get('userId'),
          time: utils["a" /* default */].toHourMinuteString(date),
          avatarUrl: message.avatarUrl,
          fromOperator: message.fromOperator,
          visitorAvatarUrl: this.settings.get('room') && this.settings.get('room').visitorAvatarUrl ? this.settings.get('room').visitorGravatarHash : '',
          rootUrl: this.chatModel.get('cdnServerUrl'),
          userId: message.userId,
          messageId: message.messageId,
          isClosedChat: message.isClosedChat
        };

        if (chatMessage.type === constants["a" /* default */].MessageTypes.File) {
          chatMessage.status = message.status;
        }

        this.chatModel.get('messages').add(chatMessage);

        if (message.userId != this.chatModel.get('userId') && !message.isHistory) {
          app.events.trigger('notifications:newMessage');
        }
      }

      var settings = this.getWidgetSettings();
      var isMobile = settings.useMobile() && !settings.isDesktopDimension();
      var isDemo = settings.get('isDemo');
      var isExpanded = this.chatModel.get('expanded');

      if (this.chatModel.get('userId') != message.userId && this.chatModel.get('isOperator') == false && this.chatModel.get('isWidget') == true && (!isExpanded && !isMobile || isMobile) && !isDemo && message.isHistory == false) {
        this.getWidgetView().flashNotification(message.message);
      }

      if (!isExpanded && !message.isHistory) {
        this.getWidgetView().incrementMissedMessageCount();
      } // If visitor sent message, start a timer to show the no operator message.
      // This timer will get cleared out if an operator joins before it expires.


      if (this.isUserAlone && !this.chatModel.get('isOperator') && message.message !== this.chatModel.get('Question') && this.chatModel.get('messages').length === 2) {
        var addMessageFnc = function addMessageFnc() {
          var messageDate = new Date();
          if (isDemo) messageDate.setTime(message.time * 1000 + 1);
          messageDate = _this4.convertToUserTime(messageDate);

          _this4.chatModel.get('messages').add({
            date: messageDate,
            type: constants["a" /* default */].MessageTypes.Note,
            message: no_conflict["c" /* _ */].escape(_this4.getResource('chat_noOperatorMessage')),
            resourceKey: 'chat_noOperatorMessage',
            isClosedChat: message.isClosedChat
          });

          _this4.chatModel.set('noOperatorMessageSeen', true);
        };

        if (isDemo) {
          addMessageFnc();
        } else if (!this.noOperatorMessageTimeout) {
          this.noOperatorMessageTimeout = setTimeout(addMessageFnc, settings.get('NoOperatorMessageTimeout') * 1000);
        }
      } // All this hokey logic makes the chats scroll from the bottom in the new dashboard when there aren't enough messages to make the container overflow


      jquery_default()('body').trigger('ChatMessageAdded');
      this.flashMobileNotificationIcon();
    }
  }, {
    key: "onDeleteMessage",
    value: function onDeleteMessage(args) {
      var messages = this.chatModel.get('messages');
      var message = messages.findWhere({
        id: args.messageId
      }) || messages.findWhere({
        serverId: args.messageId
      }) || messages.findWhere({
        id: parseInt(args.messageId, 10)
      });
      if (!message) return;
      messages.remove(message);
    }
  }, {
    key: "onTyping",
    value: function onTyping(userId, userDisplayName, roomId, roomDisplayName, isTyping, time) {
      this.messageView.typing(userId, userDisplayName, isTyping);
    }
  }, {
    key: "onRoomClosed",
    value: function onRoomClosed(roomId) {
      if (!this.options.get('isOperator') && !localStorage.roomId && this.getDataController().connectionInfo.get('roomId') == roomId) {
        this.onCloseChat(true);
      }
    }
  }, {
    key: "onRoomDestroyed",
    value: function onRoomDestroyed(roomId, roomDisplayName, time, reasonCode) {
      this.chatModel.set('closedReasonCode', reasonCode);

      if (reasonCode === constants["a" /* default */].ClosedReasonCodes.NoOperatorJoined) {
        this.chatModel.set('state', constants["a" /* default */].WidgetStates.EmailForm);
      } else {
        this.chatModel.set('state', constants["a" /* default */].WidgetStates.Closed);
      }
    }
  }, {
    key: "onUserDestroyed",
    value: function onUserDestroyed() {
      this.chatModel.set('state', constants["a" /* default */].WidgetStates.Closed);
    }
  }, {
    key: "onRoomDetailsChanged",
    value: function onRoomDetailsChanged(args) {
      // For now, just set the roomAvatar and the roomHostName
      this.chatModel.set({
        roomHostAvatarUrl: args.roomHostAvatarUrl || null,
        roomHostName: args.roomHostName || null,
        visitorEmail: args.visitorEmail || this.chatModel.get('visitorEmail'),
        visitorName: args.visitorName || this.chatModel.get('visitorName'),
        visitorPhoneNumber: args.visitorPhoneNumber || this.chatModel.get('visitorPhoneNumber'),
        visitorFirstName: args.visitorFirstName || this.chatModel.get('visitorFirstName'),
        visitorLastName: args.visitorLastName || this.chatModel.get('visitorLastName'),
        visitorCompany: args.visitorCompany || this.chatModel.get('visitorCompany')
      });
      this.getViewController().triggerRoomChangedForApi();
    }
  }, {
    key: "onJoined",
    value: function onJoined(userId, userDisplayName, roomId, roomDisplayName, time, isHistory, isClosedChat) {
      var isDifferentUser = userId !== this.chatModel.get('userId');

      if (this.chatModel.get('isOperator') || isDifferentUser) {
        var date = new Date();
        date.setTime(time * 1000);
        date = this.convertToUserTime(date);
        this.chatModel.get('messages').add({
          date: date,
          type: constants["a" /* default */].MessageTypes.Separator,
          important: true,
          message: PCStateChatting_htmlDecode(no_conflict["c" /* _ */].escape(this.getResource('chat_joinMessage', {
            displayName: jquery_default.a.trim(userDisplayName)
          }))),
          username: userDisplayName,
          resourceKey: 'chat_joinMessage',
          time: utils["a" /* default */].toHourMinuteString(date),
          isClosedChat: isClosedChat
        });
      }

      if (isDifferentUser) {
        this.isUserAlone = false;

        if (this.noOperatorMessageTimeout) {
          clearTimeout(this.noOperatorMessageTimeout);
          this.noOperatorMessageTimeout = null;
        }

        this.chatModel.get('operators').add({
          userDisplayName: userDisplayName,
          userId: userId
        });

        if (this.chatModel.get('operators').length > 0) {
          if (!this.chatModel.get('isOperator')) {
            this.getWidgetView().setExpandedTitle(PCStateChatting_htmlDecode(this.getResource('chat_nowChattingWith', {
              chatUserNames: this.chatModel.chatUserNames()
            })), 'chat_nowChattingWith');

            if (!this.getWidgetView().widgetShown()) {
              var resourceKey = this.getTitleResourceKey();
              this.getWidgetView().setCollapsedTitle(PCStateChatting_htmlDecode(this.getResource(resourceKey)), resourceKey);
            }
          }
        } else {
          this.isUserAlone = true;
        }
      }
    }
  }, {
    key: "onLeft",
    value: function onLeft(userId, userDisplayName, roomId, roomDisplayName, time, isHistory, isClosedChat) {
      var isDifferentUser = userId !== this.chatModel.get('userId');

      if (this.chatModel.get('isOperator') || isDifferentUser) {
        var date = new Date();
        date.setTime(time * 1000);
        date = this.convertToUserTime(date);
        this.chatModel.get('messages').add({
          date: date,
          type: constants["a" /* default */].MessageTypes.Separator,
          message: this.getResource('chat_leftMessage', {
            displayName: jquery_default.a.trim(userDisplayName)
          }),
          resourceKey: 'chat_leftMessage',
          time: utils["a" /* default */].toHourMinuteString(date),
          isClosedChat: isClosedChat
        });
      }

      if (isDifferentUser) {
        this.chatModel.get('operators').remove(userId);

        if (!this.chatModel.get('isOperator') && this.chatModel.chatUserNames().length > 0) {
          this.getWidgetView().setTitle(PCStateChatting_htmlDecode(this.getResource('chat_nowChattingWith', {
            chatUserNames: this.chatModel.chatUserNames()
          })), 'chat_nowChattingWith');
        } else {
          var titleResourceKey = this.getInitialTitleResourceKey();
          this.getWidgetView().setTitle(PCStateChatting_htmlDecode(this.getResource(titleResourceKey)), titleResourceKey);
        }
      }
    }
  }, {
    key: "getTitleResourceKey",
    value: function getTitleResourceKey() {
      var settings = this.getWidgetSettings();
      var isMobile = settings.useMobile() && !settings.isDesktopDimension();
      var available = this.chatModel.get('operatorsAvailable');
      if (isMobile) return available ? 'mobile_title_initial' : 'mobile_title_unavailable_initial';
      return available ? 'title_initial' : 'title_unavailable_initial';
    }
  }, {
    key: "logFailedConnection",
    value: function logFailedConnection(error) {
      var accountId = this.settings.get('AccountId');
      var chatId = this.getDataController().connectionInfo.get('roomId');
      var userId = this.chatModel.get('userId');
      var chatServerUrl = this.getDataController().connectionInfo.get('chatServerUrl');
      var message = "Failed to connect to chat server. Account: ".concat(accountId, "; ChatId: ").concat(chatId, "; User: ").concat(userId, "; Error: ").concat(JSON.stringify(error));
      logger["a" /* default */].log(logger["a" /* default */].LEVELS.DEBUG, message, '', false, chatServerUrl, '');
    }
  }, {
    key: "destroy",
    value: function destroy() {
      this.stopListening(this.messageView);

      _get(PCStateChatting_getPrototypeOf(PCStateChatting.prototype), "destroy", this).call(this);
    }
  }]);

  return PCStateChatting;
}(states_PCWidgetState);

if (window.PureChatEvents) {
  window.PureChatEvents.on('roomclosed', function (roomId) {
    if (typeof window._pcwi !== 'undefined') {
      window._pcwi.state.triggerMethod('roomClosed', roomId);
    }
  });
}

/* harmony default export */ var states_PCStateChatting = (PCStateChatting_PCStateChatting);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/message_chat_closed.model.js


var MessageChatClosed = message_model["a" /* default */].extend({
  sortOrder: constants["a" /* default */].MessageSortOrders.Closed,
  defaults: {
    date: new Date(),
    message: 'Thanks for chatting!',
    resourceKey: 'chat_closedMessage',
    type: constants["a" /* default */].MessageTypes.Closed
  }
});
/* harmony default export */ var message_chat_closed_model = (MessageChatClosed);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateClosed.js
function PCStateClosed_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateClosed_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateClosed_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateClosed_typeof(obj); }

function PCStateClosed_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateClosed_possibleConstructorReturn(self, call) { if (call && (PCStateClosed_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateClosed_assertThisInitialized(self); }

function PCStateClosed_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function PCStateClosed_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { PCStateClosed_get = Reflect.get; } else { PCStateClosed_get = function _get(target, property, receiver) { var base = PCStateClosed_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return PCStateClosed_get(target, property, receiver || target); }

function PCStateClosed_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = PCStateClosed_getPrototypeOf(object); if (object === null) break; } return object; }

function PCStateClosed_getPrototypeOf(o) { PCStateClosed_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateClosed_getPrototypeOf(o); }

function PCStateClosed_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateClosed_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateClosed_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateClosed_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateClosed_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateClosed_setPrototypeOf(subClass, superClass); }

function PCStateClosed_setPrototypeOf(o, p) { PCStateClosed_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateClosed_setPrototypeOf(o, p); }











/*
The state after a chat has been closed by the operator. Display a "thanks" message.
*/

var PCStateClosed_PCStateClosed =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateClosed_inherits(PCStateClosed, _PCWidgetState);

  PCStateClosed_createClass(PCStateClosed, [{
    key: "name",
    get: function get() {
      return 'closed';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        shouldBeInRoom: false,
        UiVisiblity: {
          restartButton: true,
          removeWidgetButton: true
        }
      };
    }
  }]);

  function PCStateClosed(options) {
    PCStateClosed_classCallCheck(this, PCStateClosed);

    return PCStateClosed_possibleConstructorReturn(this, PCStateClosed_getPrototypeOf(PCStateClosed).call(this, options));
  }

  PCStateClosed_createClass(PCStateClosed, [{
    key: "handleRoomClose",
    value: function handleRoomClose(response, room) {
      var _this = this;

      var visitorIPAddress = typeof response !== 'undefined' && response !== null && typeof response.visitorIPAddress === 'string' ? response.visitorIPAddress : '';
      var visitorIPAddressId = typeof response !== 'undefined' && response !== null && response.Id ? response.Id : -1;
      var roomName = typeof room !== 'undefined' && room !== null && typeof room.name === 'string' ? room.name : '';
      var visitorReferer = typeof room !== 'undefined' && room !== null && room.visitorReferer === 'string' ? room.visitorReferer : '';
      var roomId = typeof room !== 'undefined' && room !== null && typeof room.id !== 'undefined' ? room.id : '';
      var isOperator = this.options.get('isOperator');

      if (isOperator && room.roomType && room.roomType === Scripts_constants["k" /* RoomType */].Visitor) {
        jquery_default.a.ajax({
          url: "".concat(this.options.get('apiServerUrl'), "/ExternalApps"),
          type: 'GET',
          data: {
            chatId: this.getDataController().connectionInfo.get('roomId')
          }
        }).done(function (result) {
          var myel = jquery_default()(_this.getWidgetView().el);

          no_conflict["c" /* _ */].each(result, function (show, key) {
            var el = myel.find('#export-' + key);

            if (show) {
              el.purechatDisplay();
            } else {
              el.purechatDisplay('none');
            }
          });
        });
      }

      this.getWidgetView().$el.purechatDisplay(); //Need to set this to false so that it will be down on the next page load.

      localStorage.expanded = false;
      this.getDataController().connectionInfo.set('chatClosed', true);
      this.getDataController().connectionInfo.set('chatServerUrl', null);
      this.getDataController().connectionInfo.persistLocalStorage();
      this.getWidgetView().setExpandedTitle(this.getResource('title_chatClosed'), 'title_chatClosed');
      var resourceKey = this.getTitleResourceKey();
      this.getWidgetView().setCollapsedTitle(this.getResource(resourceKey), resourceKey);
      this.getWidgetView().clearRoomHostAvatar(); //ensure that we are visible;

      this.getWidgetView().onShow();
      var m = new no_conflict["a" /* Backbone */].Model({
        isOperator: isOperator,
        roomId: roomId,
        visitorIPAddress: visitorIPAddress,
        visitorIPAddressId: visitorIPAddressId,
        visitorName: roomName,
        visitorReferrer: visitorReferer,
        closedReasonCode: this.chatModel.get('closedReasonCode')
      });

      if (!isOperator) {
        m.set({
          GoogId: this.getWidgetSettings().get('GoogId'),
          GaTrackingTab: this.getWidgetSettings().get('GaTrackingTab'),
          GaTrackingChat: this.getWidgetSettings().get('GaTrackingChat'),
          GaTrackingEmail: this.getWidgetSettings().get('GaTrackingEmail'),
          GaTrackingThumbs: this.getWidgetSettings().get('GaTrackingThumbs'),
          GAUpThumbEvent: this.getWidgetSettings().get('GAUpThumbEvent'),
          GADownThumbEvent: this.getWidgetSettings().get('GADownThumbEvent'),
          GAEventCategory: this.getWidgetSettings().get('GAEventCategory'),
          UsingGa: this.getWidgetSettings().get('UsingGa'),
          AskForRating: this.getWidgetSettings().get('AskForRating'),
          CtaButton: this.getWidgetSettings().get('CtaButton'),
          DownloadTranscript: this.getWidgetSettings().get('DownloadTranscript')
        });
      } else {
        m.set({
          GoogId: '',
          GaTrackingTab: false,
          GaTrackingChat: false,
          GaTrackingEmail: false,
          GaTrackingThumbs: false,
          GAUpThumbEvent: false,
          GADownThumbEvent: false,
          GAEventCategory: false,
          UsingGa: false
        });
      }

      this._initialCollection = no_conflict["b" /* Marionette */].getOption(this, 'chatModel').get('messages');
      var closedViewParams = {
        rm: this.getResources(),
        model: m,
        collection: this._initialCollection,
        settings: this.options,
        viewController: this.getViewController(),
        chatModel: this.getChatModel()
      };
      this.closeMessage = !isOperator ? new message_list_view["a" /* default */](closedViewParams) : new window.ClosedOperatorView(closedViewParams);
      this.listenTo(this.closeMessage, 'chat:rated', function (up) {
        _this.getDataController().rateChat(up);

        if (up) {
          utils["a" /* default */].GaEvent(_this.getWidgetSettings(), 'GaTrackingThumbs', 'GAUpThumbEvent');
        } else {
          utils["a" /* default */].GaEvent(_this.getWidgetSettings(), 'GaTrackingThumbs', 'GADownThumbEvent');
        }

        _this.getViewController().triggerResizedEvent();

        _this.getViewController().trigger('chat:rate', {
          rating: up
        });
      });
      this.getWidgetView().showChildView('content', this.closeMessage);

      if (!isOperator) {
        var htmlDecode = function htmlDecode(value) {
          return jquery_default()('<div/>').html(value).text();
        };

        var closedDate = new Date();

        this._initialCollection.add({
          date: closedDate,
          type: constants["a" /* default */].MessageTypes.Separator,
          important: true,
          message: htmlDecode(no_conflict["c" /* _ */].escape(this.getResource('title_chatClosed'))),
          resourceKey: 'title_chatClosed',
          time: utils["a" /* default */].toHourMinuteString(closedDate),
          isClosedChat: true
        });

        this._initialCollection.add(new message_chat_closed_model());
      }

      this.chatModel.set({
        roomHostAvatarUrl: null,
        roomHostName: null
      });

      if (this.options.get('isDirectAccess')) {
        jquery_default()('.direct-container-header').purechatDisplay('block');
      }

      app.events.trigger('footer:hide');

      if (no_conflict["c" /* _ */].isFunction(this.getDataController().unbindHandlerEvents)) {
        this.getDataController().unbindHandlerEvents();
      }

      this.getViewController().trigger('chat:end', this.chatModel.pick(['visitorEmail', 'visitorName', 'visitorPhoneNumber', 'visitorQuestion', 'visitorFirstName', 'visitorLastName', 'visitorCompany']));
    }
  }, {
    key: "onSelectionShow",
    value: function onSelectionShow() {
      if (this.closeMessage && this.closeMessage.updateScroll) this.closeMessage.updateScroll();
    }
  }, {
    key: "onEnter",
    value: function onEnter() {
      var _this2 = this;

      states_PCWidgetState.prototype.onEnter.apply(this, arguments);
      var room = this.options.get('room') || {}; // Todo: this should be switched to use roomType once old chat server is gone

      var roomId = Number(room.id);
      this.getWidgetView().chatAutoStarted = false;

      if (this.chatModel.get('isOperator')) {
        if (!isNaN(roomId)) {
          jquery_default.a.ajax({
            type: 'get',
            dataType: 'json',
            url: "".concat(this.options.get('apiServerUrl'), "/api/Widgets/GetVisitorIPAddress/").concat(room.id || -1)
          }).done(function (response) {
            return _this2.handleRoomClose(response, room);
          });
        } else {
          this.handleRoomClose(null, room);
        }
      } else {
        var visitorAuthCookieName = config_production_default.a.authCookieName + 'Visitor';
        document.cookie = visitorAuthCookieName + '=; Domain=.purechat.com; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
        this.handleRoomClose(null, null);
      }
    }
  }, {
    key: "onExport",
    value: function onExport(args) {
      window.PureChatEvents.trigger('export:' + args.app, {
        chatId: this.options.get('room').id,
        visitorEmail: this.options.get('room').visitorEmail,
        visitorName: this.options.get('room').visitorName
      });
    }
  }, {
    key: "onRestartChat",
    value: function onRestartChat() {
      var _this3 = this;

      var inRoom = this.getDataController().checkInRoom(); //If the room was just closed then expanded is false,
      //need to make sure we make it expanded again.

      localStorage.expanded = true;
      this.syncWithContact().done(function () {
        if (inRoom) {
          _this3.getChatModel().set('state', constants["a" /* default */].WidgetStates.Activating);
        } else {
          _this3.getDataController().restartChat().done(function () {
            _this3.getChatModel().restartChat();

            _this3.getViewController().resetVisitorQuestion();

            _this3.getViewController().trigger('widget:restart');
          });
        }
      });
    }
  }, {
    key: "getTitleResourceKey",
    value: function getTitleResourceKey() {
      var settings = this.getWidgetSettings();
      var isMobile = settings.useMobile() && !settings.isDesktopDimension();
      var available = this.chatModel.get('operatorsAvailable');
      return isMobile ? available ? 'mobile_title_initial' : 'mobile_title_unavailable_initial' : available ? 'title_initial' : 'title_unavailable_initial';
    }
  }, {
    key: "destroy",
    value: function destroy() {
      this.stopListening(this.closeMessage);

      PCStateClosed_get(PCStateClosed_getPrototypeOf(PCStateClosed.prototype), "destroy", this).call(this);
    }
  }]);

  return PCStateClosed;
}(states_PCWidgetState);

/* harmony default export */ var states_PCStateClosed = (PCStateClosed_PCStateClosed);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateEmailForm.js
function PCStateEmailForm_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateEmailForm_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateEmailForm_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateEmailForm_typeof(obj); }

function PCStateEmailForm_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateEmailForm_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateEmailForm_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateEmailForm_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateEmailForm_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateEmailForm_possibleConstructorReturn(self, call) { if (call && (PCStateEmailForm_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateEmailForm_assertThisInitialized(self); }

function PCStateEmailForm_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function PCStateEmailForm_getPrototypeOf(o) { PCStateEmailForm_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateEmailForm_getPrototypeOf(o); }

function PCStateEmailForm_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateEmailForm_setPrototypeOf(subClass, superClass); }

function PCStateEmailForm_setPrototypeOf(o, p) { PCStateEmailForm_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateEmailForm_setPrototypeOf(o, p); }






 // This is an intermediate state that can be used when transitioning from the in-chat state
// when the chat isn't answered in a set amount of time

var PCStateEmailForm_PCStateEmailForm =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateEmailForm_inherits(PCStateEmailForm, _PCWidgetState);

  function PCStateEmailForm() {
    PCStateEmailForm_classCallCheck(this, PCStateEmailForm);

    return PCStateEmailForm_possibleConstructorReturn(this, PCStateEmailForm_getPrototypeOf(PCStateEmailForm).apply(this, arguments));
  }

  PCStateEmailForm_createClass(PCStateEmailForm, [{
    key: "getRequiredSetting",
    value: function getRequiredSetting(setting) {
      var value = this.getWidgetSettings().get(setting);
      return value === undefined ? true : Boolean(value);
    }
  }, {
    key: "buildInitialQuestionFromMessageList",
    value: function buildInitialQuestionFromMessageList() {
      var userId = this.chatModel.get('userId');
      var myMessages = this.chatModel.get('messages').filter(function (m) {
        return m.get('userId') === userId;
      });
      var message = ''; // Currently, the email cannot handle new lines, so let's just put a white space here

      myMessages.forEach(function (m) {
        if (message.length === 0) {
          message = m.get('message');
        } else {
          message += ' ' + m.get('message');
        }
      });
      return message;
    }
  }, {
    key: "onEnter",
    value: function onEnter() {
      var _this = this;

      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      states_PCWidgetState.prototype.onEnter.apply(this, args);
      var initialQuestion = this.buildInitialQuestionFromMessageList();
      var widgetView = this.getWidgetView();
      this.getDataController().connectionInfo.set('chatClosed', true);
      this.getDataController().connectionInfo.persistLocalStorage();
      this.getWidgetView().setTitle(this.getResource('title_emailForm'), 'title_emailForm');
      var model = new no_conflict["a" /* Backbone */].Model({
        EmailForm: true,
        InitialVisitorName: this.getViewController().getChatModel().get('visitorName') || '',
        InitialVisitorFirstName: this.getViewController().getChatModel().get('visitorFirstName') || '',
        InitialVisitorLastName: this.getViewController().getChatModel().get('visitorLastName') || '',
        InitialVisitorCompany: this.getViewController().getChatModel().get('visitorCompany') || '',
        InitialVisitorEmail: this.getViewController().getChatModel().get('visitorEmail') || '',
        InitialVisitorQuestion: initialQuestion || this.getViewController().getChatModel().get('visitorQuestion') || '',
        InitialVisitorPhoneNumber: this.getViewController().getChatModel().get('visitorPhoneNumber') || '',
        RequireFirstName: this.getRequiredSetting('RequireFirstName'),
        RequireLastName: this.getRequiredSetting('RequireLastName'),
        RequireCompany: this.getRequiredSetting('RequireCompany'),
        RequirePhoneNumber: this.getRequiredSetting('RequirePhoneNumber'),
        RequireEmail: this.getRequiredSetting('RequireEmail'),
        RequireQuestion: this.getRequiredSetting('RequireQuestion')
      });
      model.on('formSubmit', function (data) {
        var form = jquery_default()(_this.getWidgetView().el).find('.purechat-form.purechat-email-form');
        app.events.trigger('widget:spinner:show');

        _this.getDataController().submitEmailForm(data).done(function (result) {
          if (result.success) {
            var emailSent = new email_sent_view({
              rm: _this.getResources(),
              model: model
            });

            _this.getWidgetView().showChildView('content', emailSent);

            _this.getWidgetView().ui.restartButton.purechatDisplay('inline-block');

            _this.getWidgetView().$el.find('.purechat-btn-restart').on('click.RestartChat', function (e) {
              _this.restartChat.call(_this, e);
            });

            _this.getViewController().trigger('email:send', data);
          } else {
            form.find('.purechat-email-error').purechatDisplay('block');
          }
        }).always(function () {
          app.events.trigger('widget:spinner:hide');
        });
      });
      this.listenTo(this.getViewController().getChatModel(), 'change', function (cModel) {
        model.set({
          InitialVisitorName: cModel.get('visitorName') || '',
          InitialVisitorFirstName: cModel.get('visitorFirstName') || '',
          InitialVisitorLastName: cModel.get('visitorLastName') || '',
          InitialVisitorEmail: cModel.get('visitorEmail') || '',
          InitialVisitorCompany: cModel.get('visitorCompany') || '',
          InitialVisitorQuestion: cModel.get('visitorQuestion') || '',
          InitialVisitorPhoneNumber: cModel.get('visitorPhoneNumber') || ''
        });
      }); // Set the fromMissed flag so that this displays correctly both in the
      // preview as well as when the email form is displayed after a chat is
      // not responded to.

      var isDemo = this.options.get('isDemo');
      var fromMissed = this.options.get('requestedState') !== 'PCStateEmailForm';
      this.options.fromMissed = fromMissed && !isDemo;
      var emailForm = new email_form_view({
        viewController: this.getViewController(),
        rm: this.getResources(),
        settings: this.options,
        chatModel: this.chatModel,
        model: model
      });
      widgetView.showChildView('content', emailForm);
      widgetView.onShow();
    }
  }, {
    key: "onExpanded",
    value: function onExpanded() {
      this.getWidgetView().setTitle(this.getResource('title_emailForm'), 'title_emailForm');
    }
  }, {
    key: "onCollapsed",
    value: function onCollapsed() {
      var titleResourceKey = this.getInitialTitleResourceKey();
      this.getWidgetView().setTitle(this.getResource(titleResourceKey));
    }
  }, {
    key: "restartChat",
    value: function restartChat(e) {
      var _this2 = this;

      e.stopPropagation();
      var sender = jquery_default()(e.currentTarget);
      sender.off('click.RestartChat');
      this.getDataController().restartChat().done(function () {
        _this2.getChatModel().restartChat();

        _this2.getViewController().resetVisitorQuestion();

        _this2.getViewController().trigger('widget:restart');
      }).fail(function () {
        throw new Error('Failed to send email. Please try again!');
      });
    }
  }, {
    key: "onExit",
    value: function onExit() {
      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      states_PCWidgetState.prototype.onExit.apply(this, args);
      if (this.unbindEvents) this.unbindEvents();
    }
  }, {
    key: "name",
    get: function get() {
      return 'emailForm';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        UiVisibility: {
          popoutButton: true,
          closeButton: true,
          requeueButton: true
        }
      };
    }
  }]);

  return PCStateEmailForm;
}(states_PCWidgetState);

/* harmony default export */ var states_PCStateEmailForm = (PCStateEmailForm_PCStateEmailForm);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/StartChatForm.html
var StartChatForm = __webpack_require__(660);
var StartChatForm_default = /*#__PURE__*/__webpack_require__.n(StartChatForm);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/start_chat_form.view.js




var START_CHAT_FORM_DELAY = 1000;
var StartChatFormView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: StartChatForm_default.a,
  className: 'purechat-start-chat-form purechat-card',
  events: {
    'submit form': 'startChatSubmit',
    'keydown textarea': 'keyDown',
    'change @ui.userDisplayFirstName': 'triggerFirstNameChange',
    'change @ui.userDisplayLastName': 'triggerLastNameChange',
    'change @ui.userCompany': 'triggerCompanyChange',
    'change @ui.email': 'triggerEmailChange',
    'change @ui.question': 'triggerQuestionChange',
    'change @ui.phoneNumber': 'triggerPhoneNumberChange'
  },
  modelEvents: {
    change: 'render'
  },
  ui: {
    form: '.purechat-form',
    userDisplayName: '.purechat-name-input',
    userDisplayFirstName: '.purechat-firstname-input',
    userDisplayLastName: '.purechat-lastname-input',
    userDisplayCompany: '.purechat-company-input',
    email: '.purechat-email-input',
    question: '.purechat-question-input',
    userDisplayNameError: '.please-entername',
    emailError: '.please-enteremail',
    questionError: '.please-enterquestion',
    phoneNumber: '.purechat-phonenumber-input',
    unavailablePhoneNumber: '.purechat-unavailablephone-input',
    phoneNumberError: '.please-enterphonenumber',
    unavailablePhoneError: '.please-enterunavailablephone',
    userDisplayFirstNameError: '.please-enterfirstname',
    userDisplayLastNameError: '.please-enterlastname',
    userDisplayCompanyError: '.please-entercompany'
  },
  // So, after thinking this blank event does absolutely nothing, apparently it
  // does some black fuckin' magic to the textarea to make the start chat stuff
  // actually work. So if you stumble upon this, thinking it can be removed because
  // it's empty: DO NOT. NO TOUCHY....NOOOO TOUCHY
  keyDown: function keyDown() {},
  triggerFirstNameChange: function triggerFirstNameChange() {
    var userDisplayFirstName = jquery_default.a.trim(this.ui.userDisplayFirstName.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorFirstName', userDisplayFirstName, {
      silent: true
    });
  },
  triggerLastNameChange: function triggerLastNameChange() {
    var userDisplayLastName = jquery_default.a.trim(this.ui.userDisplayLastName.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorLastName', userDisplayLastName, {
      silent: true
    });
  },
  triggerCompanyChange: function triggerCompanyChange() {
    var userDisplayCompany = jquery_default.a.trim(this.ui.userDisplayCompany.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorCompany', userDisplayCompany, {
      silent: true
    });
  },
  triggerEmailChange: function triggerEmailChange() {
    var userEmail = jquery_default.a.trim(this.ui.email.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorEmail', userEmail, {
      silent: true
    });
  },
  triggerPhoneNumberChange: function triggerPhoneNumberChange() {
    var phoneNumberVal = jquery_default.a.trim(this.ui.phoneNumber.val());
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorPhoneNumber', phoneNumberVal, {
      silent: true
    });
  },
  triggerQuestionChange: function triggerQuestionChange() {
    var initialQuestion = this.ui.question.val();
    var chatModel = this.options.viewController.getChatModel();
    chatModel.set('visitorQuestion', initialQuestion, {
      silent: true
    });
  },
  startChatSubmit: function startChatSubmit(e) {
    try {
      e.preventDefault();
      this.ui.form.prop('disabled', true);
      var formType = no_conflict["b" /* Marionette */].getOption(this, 'FormType');
      var isEmailForm = this.model.get('EmailForm');
      var startImmediately = this.options.settings.get('StartChatImmediately');
      var askForFirstName = isEmailForm ? this.model.get('EmailFormAskForFirstName') : this.model.get('AskForFirstName') && !startImmediately;
      var askForLastName = isEmailForm ? this.model.get('EmailFormAskForLastName') : this.model.get('AskForLastName') && !startImmediately;
      var askForCompany = isEmailForm ? this.model.get('EmailFormAskForCompany') : this.model.get('AskForCompany') && !startImmediately;
      var askForPhoneNumber = isEmailForm ? this.model.get('EmaiLFormAskForPhoneNumber') : this.model.get('AskForPhoneNumber') && !startImmediately;
      var askForEmail = this.model.get('AskForEmail') && (isEmailForm || !startImmediately);
      var askForQuestion = this.model.get('AskForQuestion') || startImmediately;
      var userDisplayName = null;
      var userDisplayFirstName = null;

      if (askForFirstName) {
        userDisplayFirstName = jquery_default.a.trim(this.ui.userDisplayFirstName.val());
      }

      var userDisplayLastName = null;

      if (askForLastName) {
        userDisplayLastName = jquery_default.a.trim(this.ui.userDisplayLastName.val());
      }

      var userDisplayCompany = null;

      if (askForCompany) {
        userDisplayCompany = jquery_default.a.trim(this.ui.userDisplayCompany.val());
      }

      var userEmail = null;

      if (askForEmail || formType === 'email') {
        userEmail = this.ui.email.val();
      }

      var initialQuestion = this.ui.question.val() || this.model.get('InitialVisitorQuestion');
      this.ui.form.find('[class*="please"]').purechatDisplay('none');

      if (typeof userDisplayFirstName === 'string' && userDisplayFirstName.length === 0 && this.model.get('RequireFirstName')) {
        this.ui.userDisplayFirstNameError.purechatDisplay('block');
        this.options.viewController.triggerResizedEvent();
        return false;
      }

      if (typeof userDisplayLastName === 'string' && userDisplayLastName.length === 0 && this.model.get('RequireLastName')) {
        this.ui.userDisplayLastNameError.purechatDisplay('block');
        this.options.viewController.triggerResizedEvent();
        return false;
      }

      if (typeof userEmail === 'string' && userEmail.length === 0 && this.model.get('RequireEmail')) {
        this.ui.emailError.purechatDisplay('block');
        this.options.viewController.triggerResizedEvent();
        return false;
      }

      if (typeof userDisplayCompany === 'string' && userDisplayCompany.length === 0 && this.model.get('RequireCompany')) {
        this.ui.userDisplayCompanyError.purechatDisplay('block');
        this.options.viewController.triggerResizedEvent();
        return false;
      }

      var phoneNumberVal = this.ui.phoneNumber.val() || this.ui.unavailablePhoneNumber.val() || this.model.get('InitialVisitorPhoneNumber');

      if (formType === 'email' && askForPhoneNumber) {
        if (phoneNumberVal.length === 0 && this.model.get('RequirePhoneNumber')) {
          this.ui.unavailablePhoneError.purechatDisplay('block');
          this.options.viewController.triggerResizedEvent();
          return false;
        }

        this.ui.unavailablePhoneError.purechatDisplay('none');
        this.options.viewController.triggerResizedEvent();
        this.ui.unavailablePhoneNumber.val(phoneNumberVal);
      } else if (askForPhoneNumber) {
        if (phoneNumberVal.length === 0 && this.model.get('RequirePhoneNumber')) {
          this.ui.phoneNumberError.purechatDisplay('block');
          this.options.viewController.triggerResizedEvent();
          return false;
        }

        this.ui.phoneNumberError.purechatDisplay('none');
        this.options.viewController.triggerResizedEvent();
        this.ui.phoneNumber.val(phoneNumberVal);
      }

      if (askForQuestion && (initialQuestion === null || jquery_default.a.trim(initialQuestion) === '') && this.model.get('RequireQuestion')) {
        this.ui.questionError.purechatDisplay('block');
        this.options.viewController.triggerResizedEvent();
        return false;
      }

      userDisplayFirstName = userDisplayFirstName || this.options.viewController.getPublicApi().get('visitor_firstName') || this.model.get('InitialVisitorFirstName');
      userDisplayLastName = userDisplayLastName || this.options.viewController.getPublicApi().get('visitor_lastName') || this.model.get('InitialVisitorLastName');
      userDisplayCompany = userDisplayCompany || this.options.viewController.getPublicApi().get('visitor_company') || this.model.get('InitialVisitorCompany');
      userEmail = userEmail || this.options.viewController.getPublicApi().get('visitor_email') || this.model.get('InitialVisitorEmail');
      initialQuestion = initialQuestion || this.options.viewController.getPublicApi().get('visitor_question');
      phoneNumberVal = phoneNumberVal || this.options.viewController.getPublicApi().get('visitor_phonenumber');

      if (!userDisplayFirstName && !userDisplayLastName) {
        userDisplayName = 'Visitor';
        userDisplayFirstName = 'Visitor';
      }

      userDisplayName = jquery_default.a.trim("".concat(userDisplayFirstName, " ").concat(userDisplayLastName));
      this.model.set({
        Name: userDisplayName,
        FirstName: userDisplayFirstName,
        LastName: userDisplayLastName,
        Company: userDisplayCompany,
        Email: userEmail,
        Question: initialQuestion,
        PhoneNumber: phoneNumberVal
      });
      this.model.trigger('formSubmit', {
        visitorName: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayName || ''), true),
        visitorFirstName: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayFirstName || ''), true),
        visitorLastName: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayLastName || ''), true),
        visitorCompany: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userDisplayCompany || ''), true),
        visitorEmail: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(userEmail || ''), true),
        visitorQuestion: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(initialQuestion || ''), false),
        visitorPhoneNumber: utils["a" /* default */].escapeHtml(utils["a" /* default */].stripDangerousTags(phoneNumberVal || ''), true)
      });
    } finally {
      this.ui.form.prop('disabled', true);
    }
  },
  isMobile: function isMobile() {
    return this.options.settings.useMobile() && this.options.settings.isDesktopDimension();
  },
  initialize: function initialize() {
    this.startChatSubmit = no_conflict["c" /* _ */].debounce(this.startChatSubmit.bind(this), START_CHAT_FORM_DELAY, true);
  }
});
/* harmony default export */ var start_chat_form_view = (StartChatFormView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/StartChatFormAutomatically.html
var StartChatFormAutomatically = __webpack_require__(661);
var StartChatFormAutomatically_default = /*#__PURE__*/__webpack_require__.n(StartChatFormAutomatically);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/start_chat_form_automatically.view.js





var StartChatFormAutomaticallyView = start_chat_form_view.extend({
  template: StartChatFormAutomatically_default.a,
  className: 'purechat-start-chat-formauto',
  templateHelpers: function templateHelpers() {
    var self = this;
    return {
      isMobile: function isMobile() {
        return self.isMobile();
      },
      personalAvatarUrl: function personalAvatarUrl() {
        return typeof window.personalAvatarUrl !== 'undefined' ? window.personalAvatarUrl : _1avatar_operator_skinny_default.a;
      }
    };
  },
  isMobile: function isMobile() {
    return this.options.settings.useMobile() && !this.options.settings.isDesktopDimension();
  },
  format: function format(message) {
    var messageFormatted = utils["a" /* default */].formatWhitespace(message.replace(/\n/g, ' <br/> '));
    var messageLinkified = utils["a" /* default */].linkify(messageFormatted);
    return messageLinkified;
  },
  keyDown: function keyDown(e) {
    if (e.keyCode === constants["a" /* default */].KeyCodes.Enter && !e.shiftKey) {
      if (e.ctrlKey) {
        this.ui.question.val(this.ui.question.val() + '\n');
        return true;
      } else {
        // start your submit function
        this.startChatSubmit(e);
        return false;
      }
    }

    return true;
  },
  initialize: function initialize() {
    var _this = this;

    this._originalOnRender = this.onRender;

    this.onRender = function () {
      return _this._originalOnRender();
    };
  },
  onRender: function onRender() {
    var _this2 = this;

    var thought = this.$('.purechat-new-thought').html();
    this.$('.purechat-new-thought').html(this.format(thought));
    this.getOption('settings').on('change', function () {
      var newThought = _this2.getOption('settings').get('StringResources').chat_startedMessage;

      _this2.$('.purechat-new-thought').html(_this2.format(newThought));
    });
  }
});
/* harmony default export */ var start_chat_form_automatically_view = (StartChatFormAutomaticallyView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateInactive.js
function PCStateInactive_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateInactive_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateInactive_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateInactive_typeof(obj); }

function PCStateInactive_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateInactive_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateInactive_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateInactive_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateInactive_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateInactive_possibleConstructorReturn(self, call) { if (call && (PCStateInactive_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateInactive_assertThisInitialized(self); }

function PCStateInactive_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function PCStateInactive_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { PCStateInactive_get = Reflect.get; } else { PCStateInactive_get = function _get(target, property, receiver) { var base = PCStateInactive_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return PCStateInactive_get(target, property, receiver || target); }

function PCStateInactive_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = PCStateInactive_getPrototypeOf(object); if (object === null) break; } return object; }

function PCStateInactive_getPrototypeOf(o) { PCStateInactive_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateInactive_getPrototypeOf(o); }

function PCStateInactive_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateInactive_setPrototypeOf(subClass, superClass); }

function PCStateInactive_setPrototypeOf(o, p) { PCStateInactive_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateInactive_setPrototypeOf(o, p); }








/*
The state before a chat is started. Features a textbox for the user to enter their name and a button
to begin the chat. Switches the widget state to InitializingState upon the button being pressed
*/

var PCStateInactive_PCStateInactive =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateInactive_inherits(PCStateInactive, _PCWidgetState);

  function PCStateInactive() {
    PCStateInactive_classCallCheck(this, PCStateInactive);

    return PCStateInactive_possibleConstructorReturn(this, PCStateInactive_getPrototypeOf(PCStateInactive).apply(this, arguments));
  }

  PCStateInactive_createClass(PCStateInactive, [{
    key: "getRequiredSetting",
    value: function getRequiredSetting(setting) {
      var value = this.getWidgetSettings().get(setting);
      return value === undefined ? true : Boolean(value);
    }
  }, {
    key: "onEnter",
    value: function onEnter() {
      var _this = this;

      states_PCWidgetState.prototype.onEnter.apply(this, arguments);
      this.getDataController().checkChatAvailable().done(function (result) {
        var chatModel = _this.getViewController().getChatModel();

        _this.getWidgetView().$el.find('.purechat-start-chat-button-container button').html('Start Chat');

        if (!result.available && (result.reason === 'WidgetDisabled' || result.reason === 'ChatQuotaExceeded' || result.reason === 'IpIsbanned')) {
          _this.getWidgetSettings().set('UnavailableBehavior', constants["a" /* default */].UnavailableBehaviors.ShowMessage);
        }

        chatModel.set('operatorsAvailable', result.available);

        var isDemo = _this.options.get('isDemo');

        var goToEmailForm = isDemo && _this.options.get('requestedState') === constants["a" /* default */].WidgetStates.EmailForm;

        if (result.available) {
          _this.getWidgetView().onShow();

          var settings = _this.getWidgetSettings();

          var isMobile = settings.useMobile() && !settings.isDesktopDimension();

          var titleResourceKey = _this.getInitialTitleResourceKey(); // Only show the title once


          if (isMobile && !_this.getWidgetView().widgetShown()) {
            _this.getWidgetView().setTitle(_this.getResource(titleResourceKey), titleResourceKey);
          } else {
            _this.getWidgetView().setExpandedTitle(_this.getResource(titleResourceKey), titleResourceKey);
          }

          var model = new no_conflict["a" /* Backbone */].Model({
            AskForFirstName: _this.getWidgetSettings().get('AskForFirstName'),
            AskForLastName: _this.getWidgetSettings().get('AskForLastName'),
            AskForEmail: _this.getWidgetSettings().get('AskForEmail'),
            AskForCompany: _this.getWidgetSettings().get('AskForCompany'),
            AskForQuestion: _this.getWidgetSettings().get('AskForQuestion'),
            AskForPhoneNumber: _this.getWidgetSettings().get('AskForPhoneNumber'),
            InitialVisitorFirstName: chatModel.get('visitorFirstName') || '',
            InitialVisitorLastName: chatModel.get('visitorLastName') || '',
            InitialVisitorEmail: chatModel.get('visitorEmail') || '',
            InitialVisitorCompany: chatModel.get('visitorCompany') || '',
            InitialVisitorQuestion: chatModel.get('visitorQuestion') || '',
            InitialVisitorPhoneNumber: chatModel.get('visitorPhoneNumber') || '',
            RequireFirstName: _this.getRequiredSetting('RequireFirstName'),
            RequireLastName: _this.getRequiredSetting('RequireLastName'),
            RequireCompany: _this.getRequiredSetting('RequireCompany'),
            RequirePhoneNumber: _this.getRequiredSetting('RequirePhoneNumber'),
            RequireEmail: _this.getRequiredSetting('RequireEmail'),
            RequireQuestion: _this.getRequiredSetting('RequireQuestion')
          });
          var viewConstructor = !_this.getWidgetSettings().get('StartChatImmediately') ? start_chat_form_view : start_chat_form_automatically_view;
          _this.chatForm = new viewConstructor({
            viewController: _this.getViewController(),
            rm: _this.getResources(),
            model: model,
            settings: _this.options
          });
          model.on('formSubmit', function (data) {
            return _this.getViewController().onFormSubmitted(data);
          });

          if (_this.settings.browserIsUnsupported()) {
            chatModel.set('state', constants["a" /* default */].WidgetStates.Unsupported);
          } else if (goToEmailForm) {
            chatModel.set('state', constants["a" /* default */].WidgetStates.EmailForm);
          } else {
            _this.getWidgetView().showChildView('content', _this.chatForm);

            _this.listenTo(chatModel, 'change:operatorsAvailable', function (m, available) {
              if (!available) chatModel.set('state', constants["a" /* default */].WidgetStates.Unavailable);
            });

            _this.listenTo(chatModel, 'change', function (cModel) {
              model.set({
                InitialVisitorName: cModel.get('visitorName') || '',
                InitialVisitorFirstName: cModel.get('visitorFirstName') || '',
                InitialVisitorLastName: cModel.get('visitorLastName') || '',
                InitialVisitorEmail: cModel.get('visitorEmail') || '',
                InitialVisitorCompany: cModel.get('visitorCompany') || '',
                InitialVisitorQuestion: cModel.get('visitorQuestion') || '',
                InitialVisitorPhoneNumber: cModel.get('visitorPhoneNumber') || ''
              });
            });

            if (_this.widgetView.model.get('expanded') || _this.getWidgetSettings().get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget) {
              if (_this.widgetView.model.get('expanded')) {
                _this.getWidgetView().setTitle(_this.getResource('title_initial_open'), 'title_initial_open');
              }

              if (!window._pcWidgetInitializer.disableAvailabilityPings) {
                _this.startAvailabilityPolling();
              }
            }

            if (_this.options.get('enableAvailabilityPolling')) _this.startAvailabilityPolling();
          }
        } else {
          if (goToEmailForm) {
            chatModel.set('state', constants["a" /* default */].WidgetStates.EmailForm);
          } else {
            chatModel.set('state', constants["a" /* default */].WidgetStates.Unavailable);
          }
        }
      });
    }
  }, {
    key: "onExit",
    value: function onExit() {
      // Cleanup events we don't need anymore on the chat model for repeat chats so we don't have a leakey bucket
      states_PCWidgetState.prototype.onExit.apply(this, arguments);
      this.stopListening(this.getViewController().getChatModel());
    }
  }, {
    key: "onExpanded",
    value: function onExpanded() {
      var inRoom = this.getDataController().checkInRoom();

      if (inRoom) {
        this.getChatModel().set('state', constants["a" /* default */].WidgetStates.Activating);
      } else {
        this.getWidgetView().setExpandedTitle(this.getResource('title_initial_open'), 'title_initial_open');

        if (!window._pcWidgetInitializer.disableAvailabilityPings) {
          this.startAvailabilityPolling();
        }
      }
    }
  }, {
    key: "onCollapsed",
    value: function onCollapsed() {
      var titleResourceKey = this.getInitialTitleResourceKey();
      this.getWidgetView().setTitle(this.getResource(titleResourceKey), titleResourceKey);

      if (this.getWidgetSettings().get('UnavailableBehavior') !== constants["a" /* default */].UnavailableBehaviors.HideWidget) {
        this.stopAvailabilityPolling();
      }
    }
  }, {
    key: "startChatAutomatically",
    value: function startChatAutomatically() {
      var _this2 = this;

      var d = jquery_default.a.Deferred();
      var mockData = {
        visitorName: 'Visitor'
      };
      var widgetSettings = this.getWidgetSettings();
      this.getDataController().checkChatAvailable().done(function (response) {
        _this2.getChatModel().set('operatorsAvailable', response.available);

        if (response.available) {
          _this2.getDataController().startChat(mockData).done(function (chatConnectionInfo) {
            utils["a" /* default */].GaEvent(widgetSettings, 'GaTrackingChat', 'GAChatEvent');

            _this2.getWidgetView().$el.find('.purechat-init-form').find('.general-error').text('').purechatDisplay('none');

            _this2.status.chatInfo = chatConnectionInfo;
            _this2.status.initialData = mockData;

            _this2.getChatModel().set('visitorName', mockData.visitorName);

            _this2.getChatModel().set('visitorEmail', mockData.visitorEmail);

            _this2.getChatModel().set('visitorQuestion', mockData.visitorQuestion);

            _this2.getChatModel().set('roomId', chatConnectionInfo.get('roomId'));

            _this2.getChatModel().set('userId', chatConnectionInfo.get('userId'));

            _this2.getChatModel().set('authToken', chatConnectionInfo.get('authToken'));

            _this2.getChatModel().set('chatId', chatConnectionInfo.get('chatId'));

            _this2.getChatModel().set('state', constants["a" /* default */].WidgetStates.Chatting);

            _this2.getDataController().connectionInfo.persistLocalStorage();

            d.resolve();
          }).fail(function () {
            var widgetView = _this2.getWidgetView();

            widgetView.$el.find('.purechat-init-form').find('.general-error').text('Unable to start chat. Please try again').purechatDisplay('block');
            d.reject();
          }).always(function () {
            _this2.submittingChat = false;
          });
        } else {
          _this2.getChatModel().set('state', constants["a" /* default */].WidgetStates.Unavailable);

          d.resolve();
        }
      });
      return d.promise();
    }
  }, {
    key: "destroy",
    value: function destroy() {
      var chatModel = this.getViewController().getChatModel();
      this.stopListening(chatModel);

      PCStateInactive_get(PCStateInactive_getPrototypeOf(PCStateInactive.prototype), "destroy", this).call(this);
    }
  }, {
    key: "name",
    get: function get() {
      return 'inactive';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        shouldBeInRoom: false,
        UiVisiblity: {}
      };
    }
  }]);

  return PCStateInactive;
}(states_PCWidgetState);

/* harmony default export */ var states_PCStateInactive = (PCStateInactive_PCStateInactive);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateInitializing.js
function PCStateInitializing_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateInitializing_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateInitializing_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateInitializing_typeof(obj); }

function PCStateInitializing_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateInitializing_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateInitializing_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateInitializing_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateInitializing_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateInitializing_possibleConstructorReturn(self, call) { if (call && (PCStateInitializing_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateInitializing_assertThisInitialized(self); }

function PCStateInitializing_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function PCStateInitializing_getPrototypeOf(o) { PCStateInitializing_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateInitializing_getPrototypeOf(o); }

function PCStateInitializing_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateInitializing_setPrototypeOf(subClass, superClass); }

function PCStateInitializing_setPrototypeOf(o, p) { PCStateInitializing_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateInitializing_setPrototypeOf(o, p); }




var PCStateInitializing_PCStateInitializing =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateInitializing_inherits(PCStateInitializing, _PCWidgetState);

  function PCStateInitializing() {
    PCStateInitializing_classCallCheck(this, PCStateInitializing);

    return PCStateInitializing_possibleConstructorReturn(this, PCStateInitializing_getPrototypeOf(PCStateInitializing).apply(this, arguments));
  }

  PCStateInitializing_createClass(PCStateInitializing, [{
    key: "onEnter",
    value: function onEnter() {
      var _this = this;

      states_PCWidgetState.prototype.onEnter.apply(this, arguments);
      this.getWidgetView().setExpandedTitle(this.getResource('title_initial_open'), 'title_initial_open');
      var re = new RegExp("^https?://".concat(document.location.hostname), 'i');

      if (!document.referrer.match(re)) {
        localStorage.acquisitionSource = document.referrer;
      }

      var inRoom = this.getDataController().checkInRoom();
      if (inRoom && this.chatModel.get('isPoppedOut')) this.getDataController().connectionInfo.loadChatServerUrl();
      this.syncWithContact().done(function () {
        _this.getChatModel().set('state', inRoom ? constants["a" /* default */].WidgetStates.Activating : constants["a" /* default */].WidgetStates.Inactive);
      });
    }
  }, {
    key: "name",
    get: function get() {
      return 'initializing';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        UiVisiblity: {}
      };
    }
  }]);

  return PCStateInitializing;
}(states_PCWidgetState);

/* harmony default export */ var states_PCStateInitializing = (PCStateInitializing_PCStateInitializing);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateUnavailable.js
function PCStateUnavailable_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateUnavailable_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateUnavailable_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateUnavailable_typeof(obj); }

function PCStateUnavailable_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateUnavailable_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateUnavailable_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateUnavailable_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateUnavailable_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateUnavailable_possibleConstructorReturn(self, call) { if (call && (PCStateUnavailable_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateUnavailable_assertThisInitialized(self); }

function PCStateUnavailable_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function PCStateUnavailable_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { PCStateUnavailable_get = Reflect.get; } else { PCStateUnavailable_get = function _get(target, property, receiver) { var base = PCStateUnavailable_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return PCStateUnavailable_get(target, property, receiver || target); }

function PCStateUnavailable_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = PCStateUnavailable_getPrototypeOf(object); if (object === null) break; } return object; }

function PCStateUnavailable_getPrototypeOf(o) { PCStateUnavailable_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateUnavailable_getPrototypeOf(o); }

function PCStateUnavailable_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateUnavailable_setPrototypeOf(subClass, superClass); }

function PCStateUnavailable_setPrototypeOf(o, p) { PCStateUnavailable_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateUnavailable_setPrototypeOf(o, p); }








/*
The state when there are no operators available
*/

var PCStateUnavailable_PCStateUnavailable =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateUnavailable_inherits(PCStateUnavailable, _PCWidgetState);

  function PCStateUnavailable() {
    PCStateUnavailable_classCallCheck(this, PCStateUnavailable);

    return PCStateUnavailable_possibleConstructorReturn(this, PCStateUnavailable_getPrototypeOf(PCStateUnavailable).apply(this, arguments));
  }

  PCStateUnavailable_createClass(PCStateUnavailable, [{
    key: "getRequiredSetting",
    value: function getRequiredSetting(setting) {
      var value = this.getWidgetSettings().get(setting);
      return value === undefined ? true : Boolean(value);
    }
  }, {
    key: "onEnter",
    value: function onEnter() {
      var _this = this;

      states_PCWidgetState.prototype.onEnter.apply(this, arguments);
      var behavior = this.settings.get('IPIsBanned') ? constants["a" /* default */].UnavailableBehaviors.ShowMessage : this.options.get('UnavailableBehavior');
      var settings = this.getWidgetSettings();
      var titleResourceKey = this.getInitialTitleResourceKey();
      this.getWidgetView().$el.find('.purechat-start-chat-button-container button').html('Start Chat');

      if (behavior === 0) {
        this.getWidgetView().onShow();
      } else if (behavior === 1) {
        this.getWidgetView().onShow();

        if (this.widgetView.model.get('expanded')) {
          this.getWidgetView().setTitle(this.getResource('title_noOperators'), 'title_noOperators');
        } else {
          this.getWidgetView().setTitle(this.getResource(titleResourceKey), titleResourceKey);
        }

        jquery_default()(this.getWidgetView().getRegion('content').el).html("<div data-resourcekey=\"error_noOperators\" class=\"purechat-closedmessage-container purechat-no-operators\">".concat(this.getResource('error_noOperators'), "</div>"));
      } else {
        this.getWidgetView().onShow();

        if (this.widgetView.model.get('expanded')) {
          this.getWidgetView().setExpandedTitle(this.getResource('title_emailForm'), 'title_emailForm');
        } else {
          this.getWidgetView().setTitle(this.getResource(titleResourceKey), titleResourceKey);
        } // need to update to pass these in as options.


        var model = new no_conflict["a" /* Backbone */].Model({
          AskForFirstName: this.settings.get('AskForFirstName'),
          AskForLastName: this.settings.get('AskForLastName'),
          AskForEmail: true,
          AskForCompany: this.settings.get('AskForCompany'),
          AskForQuestion: true,
          AskForPhoneNumber: this.settings.get('AskForPhoneNumber'),
          EmailForm: true,
          EmailFormAskForFirstName: this.settings.get('EmailFormAskForFirstName'),
          EmailFormAskForLastName: this.settings.get('EmailFormAskForLastName'),
          EmailFormAskForCompany: this.settings.get('EmailFormAskForCompany'),
          EmailFormAskForPhoneNumber: this.settings.get('EmailFormAskForPhoneNumber'),
          InitialVisitorFirstName: this.getViewController().getChatModel().get('visitorFirstName') || '',
          InitialVisitorLastName: this.getViewController().getChatModel().get('visitorLastName') || '',
          InitialVisitorEmail: this.getViewController().getChatModel().get('visitorEmail') || '',
          InitialVisitorCompany: this.getViewController().getChatModel().get('visitorCompany') || '',
          InitialVisitorQuestion: this.getViewController().getChatModel().get('visitorQuestion') || '',
          InitialVisitorPhoneNumber: this.getViewController().getChatModel().get('visitorPhoneNumber') || '',
          RequireFirstName: this.getRequiredSetting('RequireFirstName'),
          RequireLastName: this.getRequiredSetting('RequireLastName'),
          RequireCompany: this.getRequiredSetting('RequireCompany'),
          RequirePhoneNumber: this.getRequiredSetting('RequirePhoneNumber'),
          RequireEmail: this.getRequiredSetting('RequireEmail'),
          RequireQuestion: this.getRequiredSetting('RequireQuestion')
        });
        model.on('formSubmit', function (data) {
          var form = jquery_default()(_this.getWidgetView().el).find('.purechat-form.purechat-email-form');
          app.events.trigger('widget:spinner:show');

          _this.getDataController().submitEmailForm(data).done(function (result) {
            if (result.success) {
              var emailSent = new email_sent_view({
                rm: _this.getResources(),
                model: model
              });

              _this.getWidgetView().showChildView('content', emailSent);

              _this.getWidgetView().ui.restartButton.purechatDisplay('inline-block');

              _this.getWidgetView().$el.find('.purechat-btn-restart').on('click.RestartChat', function (e) {
                return _this.restartChat.call(_this, e);
              });

              _this.getViewController().trigger('email:send', data);
            } else {
              form.find('.purechat-email-error').purechatDisplay('block');
            }
          }).fail(function () {
            form.find('.purechat-email-error').purechatDisplay('block');
          }).always(function () {
            app.events.trigger('widget:spinner:hide');
          });
        });
        this.listenTo(this.getViewController().getChatModel(), 'change', function (cModel) {
          model.set({
            InitialVisitorName: cModel.get('visitorName') || '',
            InitialVisitorFirstName: cModel.get('visitorFirstName') || '',
            InitialVisitorLastName: cModel.get('visitorLastName') || '',
            InitialVisitorEmail: cModel.get('visitorEmail') || '',
            InitialVisitorCompany: cModel.get('visitorCompany') || '',
            InitialVisitorQuestion: cModel.get('visitorQuestion') || '',
            InitialVisitorPhoneNumber: cModel.get('visitorPhoneNumber') || ''
          });
        });
        var emailForm = new start_chat_form_view({
          viewController: this.getViewController(),
          rm: this.getResources(),
          model: model,
          settings: this.options,
          FormType: 'email'
        });
        this.getWidgetView().showChildView('content', emailForm);
      }

      this.listenTo(this.getChatModel(), 'change:operatorsAvailable', function (model, available) {
        if (!available) return;

        _this.getChatModel().set('state', constants["a" /* default */].WidgetStates.Inactive);
      }); // only poll availability if it is expanded or set to hide widget on unavailable.

      var isHideWidget = settings.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget && settings.anyButtonEnabled();

      if (this.widgetView.model.get('expanded') && !isHideWidget || isHideWidget && this.getChatModel().get('operatorsAvailable') || this.options.get('enableAvailabilityPolling')) {
        if (!window._pcWidgetInitializer.disableAvailabilityPings) {
          this.startAvailabilityPolling();
        }
      }
    }
  }, {
    key: "onExpanded",
    value: function onExpanded() {
      var inRoom = this.getDataController().checkInRoom();

      if (inRoom) {
        this.getChatModel().set('state', constants["a" /* default */].WidgetStates.Activating);
      } else {
        var behavior = this.settings.get('IPIsBanned') ? constants["a" /* default */].UnavailableBehaviors.ShowMessage : this.options.get('UnavailableBehavior');

        if (behavior === 1) {
          this.getWidgetView().setTitle(this.getResource('title_noOperators'), 'title_noOperators');
        } else {
          this.getWidgetView().setExpandedTitle(this.getResource('title_emailForm'), 'title_emailForm');
        }

        if (!window._pcWidgetInitializer.disableAvailabilityPings) {
          this.startAvailabilityPolling();
        }
      }
    }
  }, {
    key: "onCollapsed",
    value: function onCollapsed() {
      var settings = this.getWidgetSettings();
      var titleResourceKey = this.getInitialTitleResourceKey();
      this.getWidgetView().setTitle(this.getResource(titleResourceKey));
      var unavailableBehavior = settings.get('UnavailableBehavior');

      if (unavailableBehavior !== constants["a" /* default */].UnavailableBehaviors.HideWidget || unavailableBehavior === constants["a" /* default */].UnavailableBehaviors.HideWidget && !settings.anyButtonEnabled()) {
        this.stopAvailabilityPolling();
      }
    }
  }, {
    key: "restartChat",
    value: function restartChat(e) {
      var _this2 = this;

      var sender = jquery_default()(e.currentTarget);
      sender.off('click.RestartChat');
      e.stopPropagation();
      this.getDataController().restartChat().done(function () {
        _this2.getChatModel().restartChat();

        _this2.getViewController().resetVisitorQuestion();

        _this2.getViewController().trigger('widget:restart');
      }).fail(function () {
        throw new Error('Failed to send email. Please try again!');
      });
    }
  }, {
    key: "destroy",
    value: function destroy() {
      this.stopListening(this.getChatModel());

      PCStateUnavailable_get(PCStateUnavailable_getPrototypeOf(PCStateUnavailable.prototype), "destroy", this).call(this);
    }
  }, {
    key: "name",
    get: function get() {
      return 'unavailable';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        shouldBeInRoom: false
      };
    }
  }]);

  return PCStateUnavailable;
}(states_PCWidgetState);

/* harmony default export */ var states_PCStateUnavailable = (PCStateUnavailable_PCStateUnavailable);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/UnsupportedBrowser.html
var UnsupportedBrowser = __webpack_require__(662);
var UnsupportedBrowser_default = /*#__PURE__*/__webpack_require__.n(UnsupportedBrowser);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/unsupported_browser.view.js


var UnsupportedBrowserView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: UnsupportedBrowser_default.a,
  className: 'purechat-unsupported-browser',
  onRender: function onRender() {}
});
/* harmony default export */ var unsupported_browser_view = (UnsupportedBrowserView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCStateUnsupported.js
function PCStateUnsupported_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { PCStateUnsupported_typeof = function _typeof(obj) { return typeof obj; }; } else { PCStateUnsupported_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return PCStateUnsupported_typeof(obj); }

function PCStateUnsupported_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function PCStateUnsupported_possibleConstructorReturn(self, call) { if (call && (PCStateUnsupported_typeof(call) === "object" || typeof call === "function")) { return call; } return PCStateUnsupported_assertThisInitialized(self); }

function PCStateUnsupported_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function PCStateUnsupported_getPrototypeOf(o) { PCStateUnsupported_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return PCStateUnsupported_getPrototypeOf(o); }

function PCStateUnsupported_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function PCStateUnsupported_createClass(Constructor, protoProps, staticProps) { if (protoProps) PCStateUnsupported_defineProperties(Constructor.prototype, protoProps); if (staticProps) PCStateUnsupported_defineProperties(Constructor, staticProps); return Constructor; }

function PCStateUnsupported_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) PCStateUnsupported_setPrototypeOf(subClass, superClass); }

function PCStateUnsupported_setPrototypeOf(o, p) { PCStateUnsupported_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return PCStateUnsupported_setPrototypeOf(o, p); }



/*
	This state is used exclusively for displaying a sad message to the user that he / she is using a crappy old browser
*/

var PCStateUnsupported_PCStateUnsupported =
/*#__PURE__*/
function (_PCWidgetState) {
  PCStateUnsupported_inherits(PCStateUnsupported, _PCWidgetState);

  PCStateUnsupported_createClass(PCStateUnsupported, [{
    key: "name",
    get: function get() {
      return 'unsupported';
    }
  }, {
    key: "stateSettings",
    get: function get() {
      return {
        UiVisiblity: {}
      };
    }
  }]);

  function PCStateUnsupported(options) {
    PCStateUnsupported_classCallCheck(this, PCStateUnsupported);

    return PCStateUnsupported_possibleConstructorReturn(this, PCStateUnsupported_getPrototypeOf(PCStateUnsupported).call(this, options));
  }

  PCStateUnsupported_createClass(PCStateUnsupported, [{
    key: "onEnter",
    value: function onEnter() {
      states_PCWidgetState.prototype.onEnter.apply(this, arguments);
      this.getWidgetView().showChildView('content', new unsupported_browser_view());
    }
  }]);

  return PCStateUnsupported;
}(states_PCWidgetState);

/* harmony default export */ var states_PCStateUnsupported = (PCStateUnsupported_PCStateUnsupported);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/states/PCWidgetStates.js








/* harmony default export */ var PCWidgetStates = ({
  PCStateActivating: states_PCStateActivating,
  PCStateChatting: states_PCStateChatting,
  PCStateClosed: states_PCStateClosed,
  PCStateEmailForm: states_PCStateEmailForm,
  PCStateInactive: states_PCStateInactive,
  PCStateInitializing: states_PCStateInitializing,
  PCStateUnavailable: states_PCStateUnavailable,
  PCStateUnsupported: states_PCStateUnsupported
});
// CONCATENATED MODULE: ./Scripts/widgets/legacy/visitor_tracker.js
function visitor_tracker_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function visitor_tracker_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { visitor_tracker_ownKeys(source, true).forEach(function (key) { visitor_tracker_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { visitor_tracker_ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function visitor_tracker_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function visitor_tracker_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function visitor_tracker_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function visitor_tracker_createClass(Constructor, protoProps, staticProps) { if (protoProps) visitor_tracker_defineProperties(Constructor.prototype, protoProps); if (staticProps) visitor_tracker_defineProperties(Constructor, staticProps); return Constructor; }

 // eslint-disable-next-line no-magic-numbers

var INACTIVITY_TIMEOUT = 1000 * 60 * 5; // 5 minutes

var visitor_tracker_TrackerEvent =
/*#__PURE__*/
function () {
  function TrackerEvent(eventName) {
    var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : jquery_default.a.noop;

    visitor_tracker_classCallCheck(this, TrackerEvent);

    this.eventName = eventName;
    this.callback = callback || jquery_default.a.noop;
  }

  visitor_tracker_createClass(TrackerEvent, [{
    key: "applyCallback",
    value: function applyCallback(args) {
      this.callback.apply(window.vtftw, [args]);
    }
  }]);

  return TrackerEvent;
}();

var cleanNulls = function cleanNulls(value) {
  if (value === 'null') return undefined;
  if (value === null) return undefined;
  return value;
};

var createPushStateEvent = function createPushStateEvent(type) {
  var original = window.history[type];
  var currentUrl = window.location.href;
  return function () {
    var _arguments = arguments;
    var returnValue = original.apply(this, arguments); // eslint-disable-line no-invalid-this
    // Emit our custom event on the next tick

    setTimeout(function () {
      // Check to see if the url changed, if not, then don't fire the event
      if (currentUrl === window.location.href) return;
      currentUrl = window.location.href;
      var eventName = "purechat:".concat(type);
      var event;

      if (typeof Event === 'function') {
        event = new Event(eventName);
      } else {
        event = document.createEvent('Event');
        event.initEvent(eventName, true, true);
      }

      event.arguments = _arguments;
      window.dispatchEvent(event);
    }, 0);
    return returnValue;
  };
};

var storageProxy = {
  get: function get(name) {
    return cleanNulls(window.localStorage.getItem(name));
  },
  set: function set(name, value) {
    window.localStorage.setItem(name, value);
  },
  remove: function remove(name) {
    window.localStorage.removeItem(name);
  }
};

var visitor_tracker_VisitorTracker =
/*#__PURE__*/
function () {
  function VisitorTracker(config, accountId) {
    visitor_tracker_classCallCheck(this, VisitorTracker);

    this.config = visitor_tracker_objectSpread({}, config);
    this.accountId = accountId;
    this.additionalInfo = {};
    this.pingCount = 0;
    this.pingDelay = this.config.pingInterval;
    this.pid = null;
    this.pingInterval = null;
    this.inactivityTimeout = null;
    this.userActive = true;
    this.userAlwaysActive = false;
    this.firstLoad = true;
    this.events = [];
    this.initialized = false; // Wrap window events to handle widget being on sigle-page app. Since `pushState` and
    // `replaceState` don't fire window events, we create a wrapper to emit one ourselves
    // when that changes. We prefix it with `purechat:` just to avoid collision.

    var updatePageIdFn = this.updatePageId.bind(this);
    window.history.pushState = createPushStateEvent('pushState');
    window.history.replaceState = createPushStateEvent('replaceState');
    window.addEventListener('purechat:pushState', updatePageIdFn);
    window.addEventListener('purechat:replaceState', updatePageIdFn);
    window.addEventListener('hashchange', updatePageIdFn);
    var resetTimerFn = this.resetTimer.bind(this);
    document.addEventListener('keypress', resetTimerFn);
    document.addEventListener('mousemove', resetTimerFn); // Also attach listeners to the widget itself since the widget will swallow up these events
    // so they won't get triggered on the document.

    if (config.widgetElement) {
      config.widgetElement.addEventListener('keypress', resetTimerFn);
      config.widgetElement.addEventListener('mousemove', resetTimerFn);
    } // Call reset timer to setup the first inactivity timer


    this.resetTimer();
  }

  visitor_tracker_createClass(VisitorTracker, [{
    key: "init",
    value: function init() {
      this.pid = new Date().getTime();
      this.activateUser();
      this.initialized = true;
    } // Properties

  }, {
    key: "doPing",
    // Public Functions
    value: function doPing() {
      var _this = this;

      if (!this.userActive) return;
      var i = null;
      var s = null;
      var vc = storageProxy.get('vc');
      var vn = storageProxy.get('vn');

      try {
        i = storageProxy.get('i');

        if (this.isActiveSession) {
          s = storageProxy.get(this.sessionItemName);
        } else {
          // Not active, just reset the session
          storageProxy.remove(this.sessionItemName);
        }
      } catch (e) {
        /* Do Nothing */
      }

      var params = {
        i: i,
        s: s,
        f: this.firstLoad.toString(),
        c: this.pingCount,
        pid: this.pid,
        sid: this.accountId,
        url: document.location.href,
        ref: document.referrer || 'Direct',
        ai: JSON.stringify(this.additionalInfo),
        nv: true
      };

      if (vc) {
        params.vc = vc;
      }

      if (vn) {
        params.vn = vn;
      } // Do not turn this into the promise version of the request. Since the dashboard
      // is currently stuck on version 2.2.4 of jQuery because of the old ass version of
      // Marionette and Backbone we are using. So switching it causes the hosted widget
      // tracking not to work.


      jquery_default.a.ajax({
        url: this.config.pingQueueUrl,
        method: 'POST',
        contentType: 'application/json; charset=utf-8',
        data: JSON.stringify(params),
        xhrFields: {
          withCredentials: true
        },
        success: function success(response) {
          _this.firstLoad = false; // No way to track the user so stop trying

          if (!response.i) return;
          _this.pingCount++;
          _this.pingDelay = _this.config.pingInterval;
          _this.pingInterval = setTimeout(_this.doPing.bind(_this), _this.pingDelay);
          (response.e || []).forEach(function (event) {
            return _this.trigger(event.eventName, event);
          });

          try {
            storageProxy.set('i', response.i);
            storageProxy.set(_this.lastCheckinItemName, Date.now());
            if (response.s) storageProxy.set(_this.sessionItemName, response.s);
            if (response.vc) storageProxy.set('vc', response.vc);
            if (response.vn) storageProxy.set('vn', response.vn);
            return true;
          } catch (e) {
            return false;
          }
        },
        error: function error() {
          // eslint-disable-next-line no-magic-numbers
          _this.pingDelay = _this.pingDelay * 2; // Exponentialy backoff on error.

          _this.pingInterval = setTimeout(_this.doPing.bind(_this), _this.pingDelay);
        }
      });
    }
  }, {
    key: "updatePageId",
    value: function updatePageId() {
      this.pid = new Date().getTime();
    }
  }, {
    key: "activateUser",
    value: function activateUser() {
      this.userActive = true;

      if (!this.pingInterval) {
        this.pingDelay = this.config.pingInterval;
        this.pingInterval = setTimeout(this.doPing.bind(this), 0);
      }
    }
  }, {
    key: "inactivateUser",
    value: function inactivateUser() {
      this.userActive = false;

      if (this.pingInterval) {
        clearTimeout(this.pingInterval);
        this.pingInterval = null;
      }
    }
  }, {
    key: "resetTimer",
    value: function resetTimer() {
      this.activateUser();

      if (this.inactivityTimeout) {
        clearTimeout(this.inactivityTimeout);
        this.inactivityTimeout = null;
      }

      if (!this.userAlwaysActive) {
        this.inactivityTimeout = setTimeout(this.inactivateUser.bind(this), INACTIVITY_TIMEOUT);
      }
    }
  }, {
    key: "setUserAlwaysActive",
    value: function setUserAlwaysActive() {
      this.userAlwaysActive = true;
      this.resetTimer();
    }
  }, {
    key: "unsetUserAlwaysActive",
    value: function unsetUserAlwaysActive() {
      this.userAlwaysActive = false;
      this.resetTimer();
    }
  }, {
    key: "setAdditionalInfo",
    value: function setAdditionalInfo() {
      var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      this.additionalInfo = visitor_tracker_objectSpread({}, this.additionalInfo, {}, args);
    } // Event Public Functions

  }, {
    key: "trigger",
    value: function trigger(eventName, args) {
      this.events.filter(function (event) {
        return event.eventName === eventName;
      }).forEach(function (event) {
        return event.applyCallback(args);
      });
    }
  }, {
    key: "on",
    value: function on(eventName) {
      var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : jquery_default.a.noop;
      this.events.push(new visitor_tracker_TrackerEvent(eventName, callback));
    }
  }, {
    key: "off",
    value: function off(eventName) {
      this.events = this.events.filter(function (event) {
        return event.eventName !== eventName;
      });
    }
  }, {
    key: "sessionItemName",
    get: function get() {
      return "s_".concat(this.accountId);
    }
  }, {
    key: "lastCheckinItemName",
    get: function get() {
      return "lastCheckin_".concat(this.accountId);
    }
  }, {
    key: "isActiveSession",
    get: function get() {
      var now = Date.now();
      var lastCheckin = storageProxy.get(this.lastCheckinItemName);
      return lastCheckin && now - lastCheckin >= this.config.sessionTimeout ? false : true;
    }
  }]);

  return VisitorTracker;
}();

/* harmony default export */ var visitor_tracker = (visitor_tracker_VisitorTracker);
// EXTERNAL MODULE: ../node_modules/style-loader?{attrs:{id: "pcwidget-styles"}}!../node_modules/css-loader?localIdentName=[name]__[local]___[hash:base64:5]!../node_modules/stylus-loader!./Content/widget/doop.styl
var doop = __webpack_require__(663);
var doop_default = /*#__PURE__*/__webpack_require__.n(doop);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/controllers/purechat.js
function purechat_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { purechat_typeof = function _typeof(obj) { return typeof obj; }; } else { purechat_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return purechat_typeof(obj); }

function purechat_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function purechat_possibleConstructorReturn(self, call) { if (call && (purechat_typeof(call) === "object" || typeof call === "function")) { return call; } return purechat_assertThisInitialized(self); }

function purechat_getPrototypeOf(o) { purechat_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return purechat_getPrototypeOf(o); }

function purechat_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function purechat_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function purechat_createClass(Constructor, protoProps, staticProps) { if (protoProps) purechat_defineProperties(Constructor.prototype, protoProps); if (staticProps) purechat_defineProperties(Constructor, staticProps); return Constructor; }

function purechat_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) purechat_setPrototypeOf(subClass, superClass); }

function purechat_setPrototypeOf(o, p) { purechat_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return purechat_setPrototypeOf(o, p); }

/* global VERSION_NUM */
















 // Stylesheet will get deleted in widget layout if demo or operator


var purechat_IMMEDIATELY = 0;
var purechat_JUST_A_SEC = 1000;
var PIXEL_MOVEMENT_THRESHOLD = 2;
var TEN_SECONDS = 10000;
var FORTY_FIVE_SECONDS = 45000;

var purechat_PureChatController =
/*#__PURE__*/
function (_ApiController) {
  purechat_inherits(PureChatController, _ApiController);

  purechat_createClass(PureChatController, [{
    key: "setChatModel",
    // --- GETTERS/SETTERS
    value: function setChatModel(model) {
      this.chatModel = model;
    }
  }, {
    key: "getChatModel",
    value: function getChatModel() {
      return this.chatModel;
    }
  }, {
    key: "setDataController",
    value: function setDataController(dc) {
      this.dc = dc;
    }
  }, {
    key: "getDataController",
    value: function getDataController() {
      return this.dc;
    } // --- INITIALIZE

  }]);

  function PureChatController(options) {
    var _this;

    purechat_classCallCheck(this, PureChatController);

    _this = purechat_possibleConstructorReturn(this, purechat_getPrototypeOf(PureChatController).call(this, options)); //There was a problem with people having their loader script being cached and this value isn't being set
    //so we are going to default it to a prod url for now to get it to work for them.

    if (!options.get('apiCdnServerUrl')) options.set('apiCdnServerUrl', 'https://cdnva2.purechat.com/api');
    app.pureServerUrl = options.get('pureServerUrl');
    var chatModel = new chat_model({
      isWidget: options.get('isWidget'),
      position: options.get('position'),
      pureServerUrl: options.get('pureServerUrl'),
      cdnServerUrl: options.get('cdnServerUrl') || options.get('pureServerUrl'),
      apiCdnServerUrl: options.get('apiCdnServerUrl'),
      chatServerUrl: options.get('chatServerUrl'),
      widgetType: constants["a" /* default */].WidgetType.Tab,
      isOperator: options.get('isOperator'),
      isPoppedOut: options.get('poppedOut'),
      State: constants["a" /* default */].WidgetStates.Inactive,
      messages: new messages_collection(),
      operators: new operators_collection(),
      origin: options.get('origin') || window.location.href,
      userId: options.get('userId'),
      expanded: options.get('expanded')
    });

    _this.setChatModel(chatModel);

    _this.registerPublicApiEvents(); // Set some default settings for the chat box when it's in the preview


    if (options.get('isDemo')) {
      chatModel.set('operatorsAvailable', true);
      chatModel.set('visitorName', options.get('visitorName'));
    }

    var isMobile = _this.options.isMobileRequest() && !_this.options.isDesktopDimension();
    var isHiddenOnMobile = _this.options.get('MobileDisplayType') === constants["a" /* default */].MobileDisplayTypes.Hidden;

    if (isMobile && isHiddenOnMobile) {
      options.set('ChatBoxEnabled', false);

      _this.trigger('widget:ready');
    }

    if (!options.browserIsUnsupported() && (options.get('ChatBoxEnabled') || options.get('isDemo'))) {
      _this.setupDataController().done(_this.controllerReady.bind(purechat_assertThisInitialized(_this))).fail(function () {
        return _this.trigger('widget:fail');
      }); // Wire up some other events


      _this.on('all', function () {
        if (this.state) this.state.triggerMethod.apply(this.state, arguments);
      }.bind(purechat_assertThisInitialized(_this)));

      _this.on('chat:start', function () {
        return _this.disableVisitorTrackingInactivity();
      });

      _this.on('chat:end', function () {
        return _this.enableVisitorTrackingInactivity();
      });
    } else if (options.get('VisitorTrackingEnabled')) {
      _this.setupPageActivityTest();

      _this.startVisitorTracking();
    }

    return _this;
  } // --- METHODS


  purechat_createClass(PureChatController, [{
    key: "setupDataController",
    value: function setupDataController() {
      var settingsDeferred = this.options.get('dataController').loadWidgetSettings();
      this.setDataController(this.options.get('dataController'));
      return settingsDeferred;
    }
  }, {
    key: "controllerReady",
    value: function controllerReady() {
      var _this2 = this;

      var widgetSettings = this.options.get('dataController').widgetSettings.widgetConfig;
      var mergedWidgetSettings = jquery_default.a.extend({}, widgetSettings, this.options.toJSON());
      this.options.set(mergedWidgetSettings); // If the path is excluded via settings, we still want to start visitor tracking for them.
      // Also make sure to trigger the `widget:ready` event so other events get triggered.

      if (this.isExcludedPath()) {
        this.options.set('ChatBoxEnabled', false);
        this.startVisitorTracking();
        this.trigger('widget:ready');
        return false;
      }

      this.setupPageActivityTest();
      this.rm = this.options;
      var otherWidgetSettings = this.getDataController().widgetSettings;
      var mergedOtherWidgetSettings = jquery_default.a.extend({}, otherWidgetSettings, this.options.toJSON());
      this.options.set(mergedOtherWidgetSettings);
      var dataController = this.getDataController();
      var isMobile = this.options.isMobileRequest() && this.options.isAllowedOnMobile() && !this.options.isDesktopDimension();

      var doneFunc = function doneFunc(response) {
        _this2.chatModel.set('operatorsAvailable', response.available);

        var titleResourceKey = isMobile ? response.available ? 'mobile_title_initial' : 'mobile_title_unavailable_initial' : response.available ? 'title_initial' : 'title_unavailable_initial';
        jquery_default()('.purechat-button-expand').find('.purechat-button-text').text(_this2.options.getResource(titleResourceKey), titleResourceKey);

        _this2.chatModel.on('change:operatorsAvailable', _this2.operatorsAvailableChanged.bind(_this2));

        var expandButtons = jquery_default()('.purechat-button-expand');
        expandButtons.filter(':not(.purechat)').click(function (e) {
          if (!jquery_default()(e.target).hasClass('pc-icon-caret-down') && !jquery_default()(e.target).hasClass('purechat-super-minimize-link-button') && (dataController.options.ForcePopout && !_this2.chatModel.get('isPoppedOut') || dataController.options.usePrototypeFallback)) {
            _this2.popoutChatOnExpand(dataController, dataController.options, _this2.chatModel, _this2.state);
          } else {
            _this2.widgetLayout.triggerMethod('expand', e, {
              collapse: jquery_default()(e.target).hasClass('purechat-btn-collapse') || jquery_default()(e.target).hasClass('pc-icon-minus'),
              superMinimize: jquery_default()(e.target).hasClass('pc-icon-caret-down') || jquery_default()(e.target).hasClass('pc-icon-caret-up') || jquery_default()(e.target).hasClass('purechat-super-minimize-link-button')
            });
          }
        });
        if (!dataController.connectionInfo.isInChat()) dataController.connectionInfo.loadFromLocalStorage();

        _this2.chatModel.set('userId', dataController.connectionInfo.get('userId'));

        _this2.widgetLayout = new widget_layout_view({
          viewController: _this2,
          rm: _this2.rm,
          model: _this2.chatModel,
          widgetSettings: _this2.options,
          cssModules: doop_default.a
        });

        _this2.widgetLayout.render();

        if (!dataController.connectionInfo.get('chatActiveInOtherWindow') && dataController.connectionInfo.get('disabled') && dataController.connectionInfo.get('roomId')) {
          _this2.widgetLayout.$el.purechatDisplay('none');
        } else if (dataController.connectionInfo.get('chatActiveInOtherWindow') && !_this2.chatModel.get('expanded')) {
          _this2.widgetLayout.triggerMethod('collapse');
        }

        if (_this2.options.get('isOperator')) {
          _this2.stylesLoaded();
        } else {
          var type = _this2.getStyleType();

          var useMinimal = type === constants["a" /* default */].StyleTypes.Minimal || type === constants["a" /* default */].StyleTypes.Mobile;

          _this2.widgetLayout.$el.addClass(constants["a" /* default */].StyleTypesMappings[type]);

          utils["a" /* default */].setCssVars('pcwidget-styles', _this2.options.get('Color'), useMinimal); // Necessary so that all the events in the preview can be wired up
          // before kicking off the state change stuff.

          setTimeout(function () {
            return _this2.stylesLoaded();
          }, 0);
        }
      };

      if (this.chatModel.get('isOperator')) {
        doneFunc({
          available: true
        });
      } else {
        dataController.checkChatAvailable().done(doneFunc);
      }
    }
  }, {
    key: "stylesLoaded",
    value: function stylesLoaded() {
      var _this3 = this;

      var renderInto = no_conflict["c" /* _ */].isString(this.options.get('renderInto')) ? jquery_default()(this.options.get('renderInto')) : this.options.get('renderInto');
      renderInto.append(this.widgetLayout.$el);
      renderInto.on('selectionShow', function () {
        return _this3.onSelectionShow();
      });
      this.bindGobalCommand(this.widgetLayout.$el);
      this.options.get('dataController').options.chatModel = this.getChatModel();
      this.listenTo(this.chatModel, 'change:state', this.stateChange);
      this.chatModel.set('state', this.options.get('initialState') || constants["a" /* default */].WidgetStates.Initializing);
      this.listenTo(this.widgetLayout.$el, 'change:state', this.stateChange);
      this.widgetLayout.$el.purechatDisplay();
      this.widgetLayout.triggerMethod('afterInsertion');
      this.trigger('widget:ready'); // We fire this manually the first time because the public api isn't bound until now
      // and we missed the change event on the model.

      this.triggerWidgetAvailableChange(this.chatModel.get('operatorsAvailable'));

      if (!this.chatModel.get('expanded') && this.options.useMobile() && !this.options.isDesktopDimension()) {
        setTimeout(function () {
          return _this3.widgetLayout.collapseMobile();
        }, purechat_JUST_A_SEC);
      }

      this.timeBasedTrigger = new time_based(this);
      this.urlBaseTrigger = new url_based(this);
      this.startVisitorTracking();
    }
  }, {
    key: "triggerWidgetAvailableChange",
    value: function triggerWidgetAvailableChange(available) {
      this.chatModel.trigger(available ? 'widget:available' : 'widget:unavailable');
    }
  }, {
    key: "operatorsAvailableChanged",
    value: function operatorsAvailableChanged(model, available) {
      var _this4 = this;

      var expandButtons = jquery_default()('.purechat-button-expand');

      if (available) {
        expandButtons.addClass('purechat-button-available');
        expandButtons.removeClass('purechat-button-unavailable');
        expandButtons.removeClass('purechat-button-hidden');
        expandButtons.removeAttr('disabled');
      } else {
        if (this.options.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget && !this.options.anyButtonEnabled()) {
          expandButtons.removeClass('purechat-button-available');
          expandButtons.addClass('purechat-button-unavailable');
          expandButtons.attr('disabled', 'disabled');
        }

        expandButtons.each(function (i, element) {
          var next = jquery_default()(element);
          var hideString = next.attr('HideUnavailable');
          var hide = !hideString ? _this4.options.get('UnavailableBehavior') === constants["a" /* default */].UnavailableBehaviors.HideWidget && !_this4.options.anyButtonEnabled() : hideString === 'true';
          if (hide) next.addClass('purechat-button-hidden');
        });
      }

      this.triggerWidgetAvailableChange(available);
    } // --- OTHER STUFF

  }, {
    key: "popoutChatOnExpand",
    value: function popoutChatOnExpand(dataController, settings, chatModel, state, goToMobile) {
      chatModel.set('poppedOut', true);
      state.disable();
      dataController.connectionInfo.persistLocalStorage();
      var params = Object(shared_url["a" /* objectToQueryString */])({
        widgetId: settings.widgetId,
        userId: dataController.connectionInfo.get('userId'),
        displayName: dataController.connectionInfo.get('visitorName'),
        authToken: dataController.connectionInfo.get('authToken'),
        roomId: dataController.connectionInfo.get('roomId'),
        chatId: dataController.connectionInfo.get('chatId'),
        roomType: dataController.connectionInfo.get('roomType'),
        origin: encodeURIComponent(chatModel ? chatModel.get('origin') : ''),
        contactId: window.localStorage.getItem('i')
      });
      var url = "".concat(config_production_default.a.dashboardRootUrl, "/visitorwidget/chatwindow?").concat(params);

      if (!goToMobile) {
        window.openedWindow = window.open(url, 'purechatwindow', 'menubar=no, location=no, resizable=yes, scrollbars=no, status=no, width=480, height=640');
      } else {
        window.openedWindow = window.open(url, '_blank');
      }

      this.trigger('widget:poppedOut');
    }
  }, {
    key: "resetVisitorQuestion",
    value: function resetVisitorQuestion() {
      this.getChatModel().set('visitorQuestion', null);
    }
  }, {
    key: "triggerResizedEvent",
    value: function triggerResizedEvent() {
      var _this5 = this;

      if (this.resizeTrigger) clearTimeout(this.resizeTrigger);
      this.resizeTrigger = setTimeout(function () {
        _this5.resizeTrigger = null;
        if (!_this5.widgetLayout || !_this5.widgetLayout.$el) return;

        var height = _this5.widgetLayout.$el.height();

        var width = _this5.widgetLayout.$el.width(); //this is legacy for wix.  Should go away shortly.


        _this5.widgetLayout.trigger('resized', {
          height: height,
          width: width
        });

        _this5.widgetLayout.trigger('widget:resized', {
          height: height,
          width: width
        });

        if (_this5.resizeTrigger2) clearTimeout(_this5.resizeTrigger2);
        _this5.resizeTrigger2 = setTimeout(function () {
          _this5.resizeTrigger2 = null; //this is legacy for wix.  Should go away shortly.

          _this5.widgetLayout.trigger('resized', {
            height: height,
            width: width
          });

          _this5.widgetLayout.trigger('widget:resized', {
            height: height,
            width: width
          });
        }, purechat_JUST_A_SEC);
      }, purechat_IMMEDIATELY);
    }
  }, {
    key: "unbindAppLevelCommands",
    value: function unbindAppLevelCommands() {
      app.events.off('roomHostChanged');
    }
  }, {
    key: "bindAppLevelCommands",
    value: function bindAppLevelCommands() {
      var _this6 = this;

      try {
        this.unbindAppLevelCommands();
      } catch (ex) {
        /* Do Nothing */
      }

      app.events.on('roomHostChanged', function (args) {
        // Since the chat server client doesn't have access to the publicAPI (at least, not according to my knowledge) we're just piping in one event to another
        if (_this6.options.get('MobileDisplayType') === constants["a" /* default */].MobileDisplayTypes.MobileOptimized && _this6.options.get('RequestFromMobileDevice') || !_this6.options.get('RequestFromMobileDevice')) {
          _this6.getPublicApi().trigger('room:hostChanged', args);
        }
      });
    }
  }, {
    key: "getStyleType",
    value: function getStyleType() {
      var isDesktop = this.options.isDesktopDimension();
      var requestFromMobile = this.options.isMobileRequest();
      var allowOnMobile = this.options.isAllowedOnMobile();
      if (requestFromMobile && allowOnMobile && !isDesktop) return constants["a" /* default */].StyleTypes.Mobile;

      switch (this.options.get('StyleName').toLowerCase()) {
        case 'classic':
          return constants["a" /* default */].StyleTypes.Classic;

        case 'minimal':
        default:
          return constants["a" /* default */].StyleTypes.Minimal;
      }
    }
  }, {
    key: "getStyleURL",
    value: function getStyleURL() {
      var type = this.getStyleType();
      var assetsUrl = "".concat(this.options.get('cdnServerUrl'), "/assets");
      var sheetName = constants["a" /* default */].StyleTypesMappings[type];
      var sheetUrl = "".concat(assetsUrl, "/").concat(sheetName, ".").concat(110140, ".js");
      return sheetUrl;
    }
  }, {
    key: "bindVisitorTrackingEvents",
    value: function bindVisitorTrackingEvents() {
      var _this7 = this;

      if (this.vtftw) {
        this.vtftw.on('purechat:startChat', function (args) {
          _this7.onFormSubmitted({
            operatorJoinIds: args.eventArgs.operatorJoinIds || [],
            initiator: 1,
            startedByOperator: true
          });
        });
      }
    }
  }, {
    key: "unbindVisitorTrackingEvents",
    value: function unbindVisitorTrackingEvents() {
      if (this.vtftw) this.vtftw.off('purechat:startChat');
    }
  }, {
    key: "isBanned",
    value: function isBanned() {
      var banned = this.options.get('IPIsBanned');
      if (!banned) return false;

      try {
        return JSON.parse(banned.toString().toLowerCase());
      } catch (e) {
        return false;
      }
    }
  }, {
    key: "startVisitorTracking",
    value: function startVisitorTracking() {
      if (!this.getChatModel().get('isOperator') && this.options.get('VisitorTrackingEnabled') && !this.options.get('isDemo')) {
        var feature = no_conflict["c" /* _ */].find(this.options.get('Features'), function (f) {
          return f.Status !== constants["a" /* default */].FeatureStatus.Off && f.Feature === constants["a" /* default */].Features.VisitorTracking;
        }); // This is checking to make sure we're not tracking the in-dash beta widget


        if (feature && (!this.vtftw || !this.vtftw.initialized)) {
          var additionalInfo = {
            widgetId: this.options.get('overrideWidgetId') || this.options.get('Id'),
            widgetName: this.options.get('Name')
          };

          if (this.isBanned()) {
            additionalInfo.isBanned = true;
          }

          if (!config_production_default.a.widgetElement && this.options.get('ChatBoxEnabled')) config_production_default.a.widgetElement = this.widgetLayout.el; // Uncomment this to track people by their widget ID

          this.vtftw = new visitor_tracker(config_production_default.a, this.options.get('AccountId'));
          this.vtftw.setAdditionalInfo(additionalInfo);
          this.vtftw.init();
          this.bindVisitorTrackingEvents();
        }
      }
    }
  }, {
    key: "disableVisitorTrackingInactivity",
    value: function disableVisitorTrackingInactivity() {
      if (this.vtftw) this.vtftw.setUserAlwaysActive();
    }
  }, {
    key: "enableVisitorTrackingInactivity",
    value: function enableVisitorTrackingInactivity() {
      if (this.vtftw) this.vtftw.unsetUserAlwaysActive();
    }
  }, {
    key: "coalesceStartChatData",
    value: function coalesceStartChatData(data) {
      var chatModel = this.getChatModel();

      if (!chatModel.get('visitorFirstName') || data.visitorFirstName && chatModel.get('visitorFirstName') !== data.visitorFirstName) {
        chatModel.set('visitorFirstName', data.visitorFirstName);
      }

      if (!chatModel.get('visitorLastName') || data.visitorLastName && chatModel.get('visitorLastName') !== data.visitorLastName) {
        chatModel.set('visitorLastName', data.visitorLastName);
      }

      if (!chatModel.get('visitorName') || data.visitorName && chatModel.get('visitorName') !== data.visitorName) {
        chatModel.set('visitorName', data.visitorName);
      }

      if (!chatModel.get('visitorEmail') || data.visitorEmail && chatModel.get('visitorEmail') !== data.visitorEmail) {
        chatModel.set('visitorEmail', data.visitorEmail);
      }

      if (!chatModel.get('visitorQuestion') || data.visitorQuestion && chatModel.get('visitorQuestion') !== data.visitorQuestion) {
        chatModel.set('visitorQuestion', data.visitorQuestion);
      }

      if (!chatModel.get('visitorCompany') || data.visitorCompany && chatModel.get('visitorCompany') !== data.visitorCompany) {
        chatModel.set('visitorCompany', data.visitorCompany);
      }

      if (!chatModel.get('visitorPhoneNumber') || data.visitorPhoneNumber && chatModel.get('visitorPhoneNumber') !== data.visitorPhoneNumber) {
        chatModel.set('visitorPhoneNumber', data.visitorPhoneNumber);
      }

      return jquery_default.a.extend(data, chatModel.attributes);
    }
  }, {
    key: "onFormSubmitted",
    value: function onFormSubmitted(data) {
      var _this8 = this;

      var dataController = this.getDataController();
      var inRoom = dataController.checkInRoom();
      var form = this.widgetLayout.$el.find('.purechat-form.purechat-init-form');
      var chatModel = this.getChatModel();
      if (form && form.length > 0) app.events.trigger('widget:spinner:show');
      if (this.state.submittingChat) return;

      if (inRoom) {
        app.events.trigger('widget:spinner:hide');
        chatModel.set('state', constants["a" /* default */].WidgetStates.Activating);
        return;
      }

      logger["a" /* default */].log(logger["a" /* default */].LEVELS.DEBUG, 'Starting chat on DEBUG widget', '', false, '', '');
      dataController.checkChatAvailable().done(function (response) {
        if (!data.startedByOperator && !response.available) {
          app.events.trigger('widget:spinner:hide');
          chatModel.set('state', constants["a" /* default */].WidgetStates.Unavailable);
          return;
        }

        _this8.submittingChat = true;
        data.origin = chatModel.get('origin');
        dataController.startChat(_this8.coalesceStartChatData(data)).done(function (chatConnectionInfo) {
          utils["a" /* default */].GaEvent(_this8.options, 'GaTrackingChat', 'GAChatEvent');

          _this8.widgetLayout.$('.purechat-init-form .general-error').text('').purechatDisplay('none');

          _this8.state.status.chatInfo = chatConnectionInfo;
          _this8.state.status.initialData = data;
          chatModel.set({
            visitorFirstName: data.visitorFirstName,
            visitorLastName: data.visitorLastName,
            visitorName: data.visitorName,
            visitorEmail: data.visitorEmail,
            visitorQuestion: data.visitorQuestion,
            visitorPhoneNumber: data.visitorPhoneNumber,
            visitorCompany: data.visitorCompany,
            roomId: chatConnectionInfo.get('roomId'),
            userId: chatConnectionInfo.get('userId'),
            authToken: chatConnectionInfo.get('authToken'),
            chatId: chatConnectionInfo.get('chatId'),
            state: constants["a" /* default */].WidgetStates.Chatting
          });
          dataController.connectionInfo.persistLocalStorage();
        }).fail(function () {
          _this8.widgetLayout.$el.find('.purechat-init-form .general-error').text('Unable to start chat. Please try again').purechatDisplay('block');
        }).always(function () {
          _this8.state.submittingChat = false;
          app.events.trigger('widget:spinner:hide');
        });
      });
    }
  }, {
    key: "setupPageActivityTest",
    value: function setupPageActivityTest() {
      var _this9 = this;

      var tid = null;
      var lastX = -9999;
      var lastY = -9999;
      this.pageActivity = false; // See if there has been a mouse move in the last X seconds
      // and update the pageActivity cache.

      jquery_default()(document).on('mousemove.setupPageActivityTest', no_conflict["c" /* _ */].throttle(function (e) {
        if (tid) clearTimeout(tid); // Get deltas of mouse movement, then check to see if it's moved more
        // than the defined threshold.

        var xDelta = Math.abs(lastX - e.clientX);
        var yDelta = Math.abs(lastY - e.clientY);
        if (xDelta <= PIXEL_MOVEMENT_THRESHOLD && yDelta <= PIXEL_MOVEMENT_THRESHOLD) return;
        lastX = e.clientX;
        lastY = e.clientY;
        _this9.pageActivity = true; // Wait 45 seconds before setting the flag back to false. This means that
        // no activity has happened on the page in that time period.

        tid = setTimeout(function () {
          _this9.pageActivity = false;
        }, FORTY_FIVE_SECONDS);
      }, TEN_SECONDS));
    }
  }, {
    key: "onSelectionShow",
    value: function onSelectionShow() {
      if (this.state && this.state.onSelectionShow) this.state.onSelectionShow();
    }
  }, {
    key: "stateChange",
    value: function stateChange(model, newState) {
      var state = new PCWidgetStates[newState](this.options);
      this.setState(state);
    }
  }, {
    key: "setState",
    value: function setState(newState) {
      var oldState = this.state;
      var status = {};

      if (this.state) {
        status = this.state.status;
        if (this.state.onExit) this.state.onExit();
        this.state.destroy();
      }

      this.state = newState;
      this.state.status = status;
      this.state.setChatModel(this.getChatModel());
      this.state.setWidgetView(this.widgetLayout);
      this.state.setWidgetSettings(this.options);
      this.state.setResources(this.rm);
      this.state.setDataController(this.getDataController());
      this.state.setViewController(this);
      this.trigger('state:changed', {
        oldState: oldState,
        newState: newState
      });
      if (this.state.onEnter) this.state.onEnter();
      this.triggerResizedEvent();
    }
  }, {
    key: "bindGobalCommand",
    value: function bindGobalCommand($el) {
      var _this10 = this;

      $el.on('click.delegateEvents', '[data-command]', function (e) {
        e.preventDefault();
        var sender = jquery_default()(e.currentTarget);
        var command = sender.data('command');
        var commandParams = sender.data('command-params');

        _this10.trigger(command, commandParams);
      });
    }
  }, {
    key: "undelegateEvents",
    value: function undelegateEvents() {
      this.$el.off('.delegateEvents' + this.cid);
      return this;
    }
  }, {
    key: "onClose",
    value: function onClose() {}
  }, {
    key: "roomHostChanged",
    value: function roomHostChanged(args) {
      var chatModel = this.getChatModel();

      no_conflict["c" /* _ */].keys(args).forEach(function (key) {
        return chatModel.set(key, args[key], {
          silent: true
        });
      });

      chatModel.trigger('roomHostChanged');
    }
  }, {
    key: "isExcludedPath",
    value: function isExcludedPath() {
      var currentPath = window.location.href;
      var excludedPaths = this.options.get('ExcludedPaths') || [];
      return excludedPaths.some(function (path) {
        var regex = new RegExp(path, 'gi');
        return regex.test(currentPath);
      });
    }
  }]);

  return PureChatController;
}(api);

/* harmony default export */ var purechat = (purechat_PureChatController);
// EXTERNAL MODULE: ../node_modules/marked/lib/marked.js
var marked = __webpack_require__(303);
var marked_default = /*#__PURE__*/__webpack_require__.n(marked);

// EXTERNAL MODULE: ../node_modules/ua-parser-js/src/ua-parser.js
var ua_parser = __webpack_require__(219);
var ua_parser_default = /*#__PURE__*/__webpack_require__.n(ua_parser);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/animals/Baby-Chicks.png
var Baby_Chicks = __webpack_require__(664);
var Baby_Chicks_default = /*#__PURE__*/__webpack_require__.n(Baby_Chicks);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/animals/Baby-Otter.png
var Baby_Otter = __webpack_require__(665);
var Baby_Otter_default = /*#__PURE__*/__webpack_require__.n(Baby_Otter);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/animals/Baby-Panda.png
var Baby_Panda = __webpack_require__(666);
var Baby_Panda_default = /*#__PURE__*/__webpack_require__.n(Baby_Panda);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/animals/Bunny.png
var Bunny = __webpack_require__(667);
var Bunny_default = /*#__PURE__*/__webpack_require__.n(Bunny);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/animals/Kitten.png
var Kitten = __webpack_require__(668);
var Kitten_default = /*#__PURE__*/__webpack_require__.n(Kitten);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/animals/Puppy.png
var Puppy = __webpack_require__(669);
var Puppy_default = /*#__PURE__*/__webpack_require__.n(Puppy);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Black-LiveChat-Bubble.png
var Black_LiveChat_Bubble = __webpack_require__(670);
var Black_LiveChat_Bubble_default = /*#__PURE__*/__webpack_require__.n(Black_LiveChat_Bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Blue-LiveChat-Bubble.png
var Blue_LiveChat_Bubble = __webpack_require__(671);
var Blue_LiveChat_Bubble_default = /*#__PURE__*/__webpack_require__.n(Blue_LiveChat_Bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/chat-01.png
var chat_01 = __webpack_require__(672);
var chat_01_default = /*#__PURE__*/__webpack_require__.n(chat_01);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/chinese.png
var chinese = __webpack_require__(673);
var chinese_default = /*#__PURE__*/__webpack_require__.n(chinese);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Contact-01.png
var Contact_01 = __webpack_require__(674);
var Contact_01_default = /*#__PURE__*/__webpack_require__.n(Contact_01);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/email.png
var clipart_email = __webpack_require__(675);
var email_default = /*#__PURE__*/__webpack_require__.n(clipart_email);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Female-Hello.png
var Female_Hello = __webpack_require__(676);
var Female_Hello_default = /*#__PURE__*/__webpack_require__.n(Female_Hello);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Female-Support2.png
var Female_Support2 = __webpack_require__(677);
var Female_Support2_default = /*#__PURE__*/__webpack_require__.n(Female_Support2);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Female-Support.png
var Female_Support = __webpack_require__(678);
var Female_Support_default = /*#__PURE__*/__webpack_require__.n(Female_Support);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Female-ThumbsUp.png
var Female_ThumbsUp = __webpack_require__(679);
var Female_ThumbsUp_default = /*#__PURE__*/__webpack_require__.n(Female_ThumbsUp);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/french.png
var french = __webpack_require__(680);
var french_default = /*#__PURE__*/__webpack_require__.n(french);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/german.png
var german = __webpack_require__(681);
var german_default = /*#__PURE__*/__webpack_require__.n(german);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Global-01.png
var Global_01 = __webpack_require__(682);
var Global_01_default = /*#__PURE__*/__webpack_require__.n(Global_01);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/hello.png
var hello = __webpack_require__(683);
var hello_default = /*#__PURE__*/__webpack_require__.n(hello);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Info-01.png
var Info_01 = __webpack_require__(684);
var Info_01_default = /*#__PURE__*/__webpack_require__.n(Info_01);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/italian.png
var italian = __webpack_require__(685);
var italian_default = /*#__PURE__*/__webpack_require__.n(italian);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/japanese.png
var japanese = __webpack_require__(686);
var japanese_default = /*#__PURE__*/__webpack_require__.n(japanese);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Male-Hello.png
var Male_Hello = __webpack_require__(687);
var Male_Hello_default = /*#__PURE__*/__webpack_require__.n(Male_Hello);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Male-Support2.png
var Male_Support2 = __webpack_require__(688);
var Male_Support2_default = /*#__PURE__*/__webpack_require__.n(Male_Support2);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Male-Support.png
var Male_Support = __webpack_require__(689);
var Male_Support_default = /*#__PURE__*/__webpack_require__.n(Male_Support);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Male-ThumbsUp.png
var Male_ThumbsUp = __webpack_require__(690);
var Male_ThumbsUp_default = /*#__PURE__*/__webpack_require__.n(Male_ThumbsUp);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/PC-Bubble.png
var PC_Bubble = __webpack_require__(691);
var PC_Bubble_default = /*#__PURE__*/__webpack_require__.n(PC_Bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/portugese.png
var portugese = __webpack_require__(692);
var portugese_default = /*#__PURE__*/__webpack_require__.n(portugese);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/Red-LiveChat-Bubble.png
var Red_LiveChat_Bubble = __webpack_require__(693);
var Red_LiveChat_Bubble_default = /*#__PURE__*/__webpack_require__.n(Red_LiveChat_Bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/romanian.png
var romanian = __webpack_require__(694);
var romanian_default = /*#__PURE__*/__webpack_require__.n(romanian);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/russian.png
var russian = __webpack_require__(695);
var russian_default = /*#__PURE__*/__webpack_require__.n(russian);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/snowman.png
var snowman = __webpack_require__(696);
var snowman_default = /*#__PURE__*/__webpack_require__.n(snowman);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/spanish.png
var spanish = __webpack_require__(697);
var spanish_default = /*#__PURE__*/__webpack_require__.n(spanish);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/clipart/White-LiveChat-Bubble.png
var White_LiveChat_Bubble = __webpack_require__(698);
var White_LiveChat_Bubble_default = /*#__PURE__*/__webpack_require__.n(White_LiveChat_Bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/black-chat-bubble.png
var black_chat_bubble = __webpack_require__(699);
var black_chat_bubble_default = /*#__PURE__*/__webpack_require__.n(black_chat_bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/black-circle-hi.png
var black_circle_hi = __webpack_require__(700);
var black_circle_hi_default = /*#__PURE__*/__webpack_require__.n(black_circle_hi);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/black-decorative-pointer.png
var black_decorative_pointer = __webpack_require__(701);
var black_decorative_pointer_default = /*#__PURE__*/__webpack_require__.n(black_decorative_pointer);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/black-pointer.png
var black_pointer = __webpack_require__(702);
var black_pointer_default = /*#__PURE__*/__webpack_require__.n(black_pointer);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/blue-chat.png
var blue_chat = __webpack_require__(703);
var blue_chat_default = /*#__PURE__*/__webpack_require__.n(blue_chat);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/blue-circle-hi.png
var blue_circle_hi = __webpack_require__(704);
var blue_circle_hi_default = /*#__PURE__*/__webpack_require__.n(blue_circle_hi);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/blue-decorative-pointer.png
var blue_decorative_pointer = __webpack_require__(705);
var blue_decorative_pointer_default = /*#__PURE__*/__webpack_require__.n(blue_decorative_pointer);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/blue-pin.png
var blue_pin = __webpack_require__(706);
var blue_pin_default = /*#__PURE__*/__webpack_require__.n(blue_pin);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/bubbles-black.png
var bubbles_black = __webpack_require__(707);
var bubbles_black_default = /*#__PURE__*/__webpack_require__.n(bubbles_black);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/bubbles-blue.png
var bubbles_blue = __webpack_require__(708);
var bubbles_blue_default = /*#__PURE__*/__webpack_require__.n(bubbles_blue);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/bubbles-teal.png
var bubbles_teal = __webpack_require__(709);
var bubbles_teal_default = /*#__PURE__*/__webpack_require__.n(bubbles_teal);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/bubbles-white.png
var bubbles_white = __webpack_require__(710);
var bubbles_white_default = /*#__PURE__*/__webpack_require__.n(bubbles_white);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/bubble-white.png
var bubble_white = __webpack_require__(711);
var bubble_white_default = /*#__PURE__*/__webpack_require__.n(bubble_white);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/chat-with-us-tab.png
var chat_with_us_tab = __webpack_require__(712);
var chat_with_us_tab_default = /*#__PURE__*/__webpack_require__.n(chat_with_us_tab);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/green-pin.png
var green_pin = __webpack_require__(713);
var green_pin_default = /*#__PURE__*/__webpack_require__.n(green_pin);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/green-tab.png
var green_tab = __webpack_require__(714);
var green_tab_default = /*#__PURE__*/__webpack_require__.n(green_tab);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/navy-chat.png
var navy_chat = __webpack_require__(715);
var navy_chat_default = /*#__PURE__*/__webpack_require__.n(navy_chat);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/red-chat-bubble.png
var red_chat_bubble = __webpack_require__(716);
var red_chat_bubble_default = /*#__PURE__*/__webpack_require__.n(red_chat_bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/red-circle-hi.png
var red_circle_hi = __webpack_require__(717);
var red_circle_hi_default = /*#__PURE__*/__webpack_require__.n(red_circle_hi);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/red-decorative-pointer.png
var red_decorative_pointer = __webpack_require__(718);
var red_decorative_pointer_default = /*#__PURE__*/__webpack_require__.n(red_decorative_pointer);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/red-pin.png
var red_pin = __webpack_require__(719);
var red_pin_default = /*#__PURE__*/__webpack_require__.n(red_pin);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/teal-chat-bubble.png
var teal_chat_bubble = __webpack_require__(720);
var teal_chat_bubble_default = /*#__PURE__*/__webpack_require__.n(teal_chat_bubble);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/white-pointer.png
var white_pointer = __webpack_require__(721);
var white_pointer_default = /*#__PURE__*/__webpack_require__.n(white_pointer);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/bubbles/yellow-tab.png
var yellow_tab = __webpack_require__(722);
var yellow_tab_default = /*#__PURE__*/__webpack_require__.n(yellow_tab);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/people/operator-person-1.png
var operator_person_1 = __webpack_require__(723);
var operator_person_1_default = /*#__PURE__*/__webpack_require__.n(operator_person_1);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/people/operator-person-2.png
var operator_person_2 = __webpack_require__(724);
var operator_person_2_default = /*#__PURE__*/__webpack_require__.n(operator_person_2);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/people/operator-tab.png
var operator_tab = __webpack_require__(725);
var operator_tab_default = /*#__PURE__*/__webpack_require__.n(operator_tab);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/people/support-circle-grey.png
var support_circle_grey = __webpack_require__(726);
var support_circle_grey_default = /*#__PURE__*/__webpack_require__.n(support_circle_grey);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/flat/people/support-circle-white.png
var support_circle_white = __webpack_require__(727);
var support_circle_white_default = /*#__PURE__*/__webpack_require__.n(support_circle_white);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/people/CS-F-01.png
var CS_F_01 = __webpack_require__(728);
var CS_F_01_default = /*#__PURE__*/__webpack_require__.n(CS_F_01);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/people/CS-G-01.png
var CS_G_01 = __webpack_require__(729);
var CS_G_01_default = /*#__PURE__*/__webpack_require__.n(CS_G_01);

// EXTERNAL MODULE: ./Content/images/StockWidgetImages/people/CS-M-01.png
var CS_M_01 = __webpack_require__(730);
var CS_M_01_default = /*#__PURE__*/__webpack_require__.n(CS_M_01);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/stock_images.js
// In order to serve up hashed stock images, they need to be imported and mapped
// to paths in the database. Whenever a new stock image is added, it should be added
// here, and then the non-hashed path can be used in the database.



































































var imageMap = {
  'animals/baby-chicks.png': Baby_Chicks_default.a,
  'animals/baby-otter.png': Baby_Otter_default.a,
  'animals/baby-panda.png': Baby_Panda_default.a,
  'animals/bunny.png': Bunny_default.a,
  'animals/kitten.png': Kitten_default.a,
  'animals/puppy.png': Puppy_default.a,
  'clipart/black-livechat-bubble.png': Black_LiveChat_Bubble_default.a,
  'clipart/blue-livechat-bubble.png': Blue_LiveChat_Bubble_default.a,
  'clipart/chat-01.png': chat_01_default.a,
  'clipart/chinese.png': chinese_default.a,
  'clipart/contact-01.png': Contact_01_default.a,
  'clipart/email.png': email_default.a,
  'clipart/female-hello.png': Female_Hello_default.a,
  'clipart/female-support2.png': Female_Support2_default.a,
  'clipart/female-support.png': Female_Support_default.a,
  'clipart/female-thumbsup.png': Female_ThumbsUp_default.a,
  'clipart/french.png': french_default.a,
  'clipart/german.png': german_default.a,
  'clipart/global-01.png': Global_01_default.a,
  'clipart/hello.png': hello_default.a,
  'clipart/info-01.png': Info_01_default.a,
  'clipart/italian.png': italian_default.a,
  'clipart/japanese.png': japanese_default.a,
  'clipart/male-hello.png': Male_Hello_default.a,
  'clipart/male-support2.png': Male_Support2_default.a,
  'clipart/male-support.png': Male_Support_default.a,
  'clipart/male-thumbsup.png': Male_ThumbsUp_default.a,
  'clipart/pc-bubble.png': PC_Bubble_default.a,
  'clipart/portugese.png': portugese_default.a,
  'clipart/red-livechat-bubble.png': Red_LiveChat_Bubble_default.a,
  'clipart/romanian.png': romanian_default.a,
  'clipart/russian.png': russian_default.a,
  'clipart/snowman.png': snowman_default.a,
  'clipart/spanish.png': spanish_default.a,
  'clipart/white-livechat-bubble.png': White_LiveChat_Bubble_default.a,
  'flat/bubbles/black-chat-bubble.png': black_chat_bubble_default.a,
  'flat/bubbles/black-circle-hi.png': black_circle_hi_default.a,
  'flat/bubbles/black-decorative-pointer.png': black_decorative_pointer_default.a,
  'flat/bubbles/black-pointer.png': black_pointer_default.a,
  'flat/bubbles/blue-chat.png': blue_chat_default.a,
  'flat/bubbles/blue-circle-hi.png': blue_circle_hi_default.a,
  'flat/bubbles/blue-decorative-pointer.png': blue_decorative_pointer_default.a,
  'flat/bubbles/blue-pin.png': blue_pin_default.a,
  'flat/bubbles/bubbles-black.png': bubbles_black_default.a,
  'flat/bubbles/bubbles-blue.png': bubbles_blue_default.a,
  'flat/bubbles/bubbles-teal.png': bubbles_teal_default.a,
  'flat/bubbles/bubbles-white.png': bubbles_white_default.a,
  'flat/bubbles/bubble-white.png': bubble_white_default.a,
  'flat/bubbles/chat-with-us-tab.png': chat_with_us_tab_default.a,
  'flat/bubbles/green-pin.png': green_pin_default.a,
  'flat/bubbles/green-tab.png': green_tab_default.a,
  'flat/bubbles/navy-chat.png': navy_chat_default.a,
  'flat/bubbles/red-chat-bubble.png': red_chat_bubble_default.a,
  'flat/bubbles/red-circle-hi.png': red_circle_hi_default.a,
  'flat/bubbles/red-decorative-pointer.png': red_decorative_pointer_default.a,
  'flat/bubbles/red-pin.png': red_pin_default.a,
  'flat/bubbles/teal-chat-bubble.png': teal_chat_bubble_default.a,
  'flat/bubbles/white-pointer.png': white_pointer_default.a,
  'flat/bubbles/yellow-tab.png': yellow_tab_default.a,
  'flat/people/operator-person-1.png': operator_person_1_default.a,
  'flat/people/operator-person-2.png': operator_person_2_default.a,
  'flat/people/operator-tab.png': operator_tab_default.a,
  'flat/people/support-circle-grey.png': support_circle_grey_default.a,
  'flat/people/support-circle-white.png': support_circle_white_default.a,
  'people/cs-f-01.png': CS_F_01_default.a,
  'people/cs-g-01.png': CS_G_01_default.a,
  'people/cs-m-01.png': CS_M_01_default.a
};

function resolveAssetFromPath(path, fallbackPath) {
  var imageMapPath = path.toLowerCase().replace('/content/images/stockwidgetimages/', '');
  return imageMap[imageMapPath] || '' + fallbackPath + path;
}

/* harmony default export */ var stock_images = ({
  resolveAssetFromPath: resolveAssetFromPath
});
// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/widget_settings.model.js







var MAC_OS = 2;
var LINUX_OS = 3;
var ANDROID_OS = 4;
var IOS_OS = 5;

var getOsType = function getOsType() {
  var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

  switch (name.toLowerCase()) {
    case 'windows':
      return 1;

    case 'mac os':
      return MAC_OS;

    case 'ubuntu':
      return LINUX_OS;

    case 'android':
      return ANDROID_OS;

    case 'ios':
      return IOS_OS;

    default:
      return 0;
  }
}; // Create a custom marked rendered for markdown processing. By default
// links are not created with a `target="_blank"` so the links will
// open in the same window. This will add it to external links to
// fix that.


var widget_settings_model_createRenderer = function createRenderer() {
  var renderer = new marked_default.a.Renderer();

  renderer.link = function (href, title, text) {
    var external = /^https?:\/\/.+$/.test(href);
    var newWindow = external || title === 'newWindow';
    var out = "<a href=\"".concat(href, "\"");
    if (newWindow) out += ' target="_blank"';
    if (title && title !== 'newWindow') out += " title=\"".concat(title, "\"");
    return "".concat(out, ">").concat(text, "</a>");
  };

  return renderer;
};

var WidgetSettings = no_conflict["a" /* Backbone */].RelationalModel.extend({
  initialize: function initialize() {
    var parser = new ua_parser_default.a();
    var browser = parser.getBrowser();
    var os = parser.getOS();
    var device = parser.getDevice();
    this.set('BrowserDetails', {
      Browser: browser.name,
      Version: parseInt(browser.major, 10),
      OS: os.name,
      OsType: getOsType(os.name)
    });

    if (!this.get('isDemo')) {
      this.set('RequestFromMobileDevice', device.type === 'mobile');
    }
  },
  getResource: function getResource(key, data) {
    var resources = this.get('StringResources');
    if (!resources) return key;
    marked_default.a.setOptions({
      renderer: widget_settings_model_createRenderer()
    });
    var isMarkdownField = constants["a" /* default */].MarkdownFields.indexOf(key) > -1;
    if (!data) return isMarkdownField ? marked_default()(resources[key]) : resources[key]; // Make sure format is a string, it might be an integer/float and we don't want
    // it to blow up completely.

    var format = "".concat(resources[key] || ''); // Prevent using variable that input fields

    if (!data.displayName) format = format.replace('{displayName}', '');
    if (!data.chatUserNames) format = format.replace('{chatUserNames}', '');
    if (!this.compiledResources) this.compiledResources = {};

    if (!this.compiledResources[format]) {
      var formatted = isMarkdownField ? no_conflict["c" /* _ */].template(marked_default()(no_conflict["c" /* _ */].escape(format)), null, {
        interpolate: /\{(.+?)\}/g
      }) : no_conflict["c" /* _ */].template(format, null, {
        interpolate: /\{(.+?)\}/g
      });
      this.compiledResources[format] = formatted;
    }

    return this.compiledResources[format](data);
  },
  _isDesktopDimension: null,
  isDesktopDimension: function isDesktopDimension() {
    // Cache the resolution so the widget behavior stays the same after loading
    if (!this._isDesktopDimension) {
      var winHeight = jquery_default()(window).height();
      var winWidth = jquery_default()(window).width();
      var desktopHeightThreshold = 625;
      var desktopWidthThreshold = 625;
      this._isDesktopDimension = this.get('isDemo') ? !this.isMobileRequest() : winHeight >= desktopHeightThreshold && winWidth >= desktopWidthThreshold;
    }

    return this._isDesktopDimension;
  },
  isMobileRequest: function isMobileRequest() {
    return this.get('RequestFromMobileDevice');
  },
  isAllowedOnMobile: function isAllowedOnMobile() {
    return this.get('MobileDisplayType') !== constants["a" /* default */].MobileDisplayTypes.SameAsDesktop || !!this.get('Demo');
  },
  useMobile: function useMobile() {
    return this.isMobileRequest() && this.isAllowedOnMobile();
  },
  showImage: function showImage() {
    return this.get('CollapsedStyle') === constants["a" /* default */].WidgetType.Image || this.get('CollapsedStyle') === constants["a" /* default */].WidgetType.ImageTab;
  },
  anyButtonEnabled: function anyButtonEnabled() {
    return this.get('ShowEmailButton') || this.get('ShowPhoneButton') || this.get('ShowTwitterButton') || this.get('ShowAddressButton');
  },
  poweredByUrl: function poweredByUrl() {
    var params = {
      c: this.get('Company') || '',
      utm_source: window.location.hostname,
      utm_medium: 'widget',
      utm_campaign: 'poweredby'
    };
    var queryString = Object.keys(params).map(function (key) {
      return "".concat(key, "=").concat(encodeURIComponent(params[key]));
    }).join('&');
    return "https://purechat.com/powered-by-purechat?".concat(queryString);
  },
  absoluteCollapsedImageUrl: function absoluteCollapsedImageUrl(available) {
    if (this.get('CollapsedStyle') === constants["a" /* default */].WidgetType.Button) return '';
    return available ? this.absoluteUrl(this.get('AvailableCollapsedWidgetImageUrl')) : this.absoluteUrl(this.get('UnavailableCollapsedWidgetImageUrl'));
  },
  mobileAbsoluteCollapsedImageUrl: function mobileAbsoluteCollapsedImageUrl(available) {
    if (this.get('CollapsedStyle') === constants["a" /* default */].WidgetType.Button) return '';
    return available ? this.absoluteUrl(this.get('MobileAvailableCollapsedWidgetImageUrl')) : this.absoluteUrl(this.get('MobileUnavailableCollapsedWidgetImageUrl'));
  },
  absoluteUrl: function absoluteUrl(path) {
    var trimmedPath = (path || '').toLowerCase().trim();
    var tildeInFront = trimmedPath.indexOf('~') === 0;
    var slashInFront = trimmedPath.indexOf('/') === 0; // If the only thing in the path is the tilde

    if (trimmedPath.length === 1 && tildeInFront) return null;

    if (tildeInFront || trimmedPath.indexOf('files/download') > -1) {
      return this.get('apiCdnServerUrl') + (tildeInFront ? trimmedPath.substring(1) : trimmedPath);
    }

    if (slashInFront) {
      return stock_images.resolveAssetFromPath(trimmedPath, this.get('cdnServerUrl'));
    }

    return trimmedPath;
  },
  formatDateTime: function formatDateTime(dateString) {
    var d = new Date(dateString);
    var formattedDate = d.getMonth() + 1 + '/' + d.getDate() + '/' + d.getFullYear();
    formattedDate += ' ' + (d.getHours() % 12 == 0 ? '12' : d.getHours() % 12) + ':' + (d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes()) + (d.getHours() >= 12 ? 'PM' : 'AM');
    return formattedDate;
  },
  browserIsUnsupported: function browserIsUnsupported() {
    var unsupported = false;
    var browserDetails = this.get('BrowserDetails');
    if (!browserDetails) return unsupported;
    browserDetails.Version = parseFloat(browserDetails.Version);

    switch (browserDetails.Browser.toLowerCase().replace(/s+/g, '')) {
      case 'internetexplorer':
      case 'ie':
        if (browserDetails.Version <= 10) {
          unsupported = true;
        }

        break;

      case 'safari':
        if (browserDetails.Version < 5) {
          unsupported = true;
        }

        break;

      case 'opera':
        if (browserDetails.Version < 12) {
          unsupported = true;
        }

    }

    return unsupported;
  },
  isFileTransferEnabled: function isFileTransferEnabled() {
    var room = this.get('room');
    return room && room.roomType !== constants["a" /* default */].RoomType.Visitor ? false : this.get('FileTransferEnabled');
  }
});
/* harmony default export */ var widget_settings_model = (WidgetSettings);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/controllers/notifications.js
function notifications_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function notifications_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function notifications_createClass(Constructor, protoProps, staticProps) { if (protoProps) notifications_defineProperties(Constructor.prototype, protoProps); if (staticProps) notifications_defineProperties(Constructor, staticProps); return Constructor; }



var notifications_NotificationsController =
/*#__PURE__*/
function () {
  function NotificationsController(_ref) {
    var _this = this;

    var settings = _ref.settings;

    notifications_classCallCheck(this, NotificationsController);

    this.notificationSoundTimeout = null;
    this.soundIsPlaying = false;
    this._soundsFolder = '/content/audio/';
    this._localStorageKey = '_purechatVisitorWidgetPlaySound';
    this.settings = settings;
    var storageItem = window.localStorage.getItem(this._localStorageKey);
    window.localStorage[this._localStorageKey] = typeof storageItem !== 'undefined' && storageItem !== null ? storageItem.toString().toLowerCase() === 'true' : true;
    app.events.on('notifications:newMessage', function () {
      return _this.newMessage();
    });
  }

  notifications_createClass(NotificationsController, [{
    key: "newMessage",
    value: function newMessage() {
      if (!this.settings.get('RequestFromMobileDevice') && !this.settings.get('isInEditorMode')) {
        var serverUrl = this.settings.get('pureServerUrl') || 'https://app.purechat.com';
        var playSound = localStorage._purechatVisitorWidgetPlaySound.toString().toLowerCase() === 'true';

        if (!this.settings.get('isOperator') && playSound && typeof Audio !== 'undefined' && !this.soundIsPlaying) {
          var audioTest = new Audio();
          var supportsWave = audioTest.canPlayType('audio/wav') || audioTest.canPlayType('audio/wave');

          if (supportsWave) {
            this._playWave(serverUrl);
          } else {
            this._playMp3(serverUrl);
          }
        }
      }
    }
  }, {
    key: "_playSound",
    value: function _playSound(url) {
      var _this2 = this;

      var audio = new Audio(url);

      audio.onended = function () {
        _this2.soundIsPlaying = false;
        audio = null;
      };

      this.soundIsPlaying = true;
      audio.play();
    }
  }, {
    key: "_playWave",
    value: function _playWave(serverUrl) {
      this._playSound(serverUrl + this._soundsFolder + 'Correct-short.wav');
    }
  }, {
    key: "_playMp3",
    value: function _playMp3(serverUrl) {
      this._playSound(serverUrl + this._soundsFolder + 'Correct-short.mp3');
    }
  }]);

  return NotificationsController;
}();

/* harmony default export */ var notifications = (notifications_NotificationsController);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/widget_initializer.js
function widget_initializer_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function widget_initializer_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { widget_initializer_ownKeys(source, true).forEach(function (key) { widget_initializer_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { widget_initializer_ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function widget_initializer_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function widget_initializer_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function widget_initializer_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function widget_initializer_createClass(Constructor, protoProps, staticProps) { if (protoProps) widget_initializer_defineProperties(Constructor.prototype, protoProps); if (staticProps) widget_initializer_defineProperties(Constructor, staticProps); return Constructor; }










var DEFAULT_SETTINGS = {
  accountId: '',
  chatServerUrl: '',
  checkWidgetAvailableInterval: 20000,
  config: {},
  connectionSettings: {},
  dataController: null,
  insertElement: null,
  isOperator: false,
  isWidget: false,
  apiServerUrl: config_production_default.a.apiRootUrl,
  pureServerUrl: config_production_default.a.dashboardRootUrl,
  cdnServerUrl: config_production_default.a.cdnUrl,
  apiCdnServerUrl: config_production_default.a.apiCdnServerUrl,
  renderInto: 'body',
  userProperties: {
    userId: null,
    displayName: null,
    authToken: null,
    roomId: null,
    chatId: null
  },
  widgetId: ''
}; // This array is an array of widgets to turn on DEBUG logging for.

var WIDGETS_TO_DEBUG = ['29afb4fb-bb02-4683-87ab-61fe4df53428', '0a7b5ef9-ca8b-47cc-8564-7bcd7e7e641a' // Empire medical primary widget
];

var widget_initializer_WidgetInitializer =
/*#__PURE__*/
function () {
  function WidgetInitializer() {
    widget_initializer_classCallCheck(this, WidgetInitializer);

    this.settings = {};
  }

  widget_initializer_createClass(WidgetInitializer, [{
    key: "start",
    value: function start() {
      var _this = this;

      var initialSettings = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : jquery_default.a.noop;
      this.settings = widget_initializer_objectSpread({
        hasAllSettings: true
      }, DEFAULT_SETTINGS, {}, initialSettings);
      if (WIDGETS_TO_DEBUG.some(function (id) {
        return id === _this.settings.widgetId;
      })) logger["a" /* default */].setLogLevel(logger["a" /* default */].LEVELS.DEBUG);
      var serviceOptions = this.createServiceOptions();
      var serviceInstance = serviceOptions.test ? new test_data(serviceOptions) : new pc_data["a" /* default */](widget_initializer_objectSpread({}, this.settings, {}, serviceOptions));
      data_singleton["a" /* default */].setInstance(serviceInstance);
      var viewOptions = this.createViewOptions();
      this.purechat = new purechat(new widget_settings_model(viewOptions));
      this.notificationsController = new notifications({
        settings: this.purechat.options
      });
      callback(this.purechat);
    }
  }, {
    key: "createServiceOptions",
    value: function createServiceOptions() {
      return {
        test: false,
        widgetId: this.settings.widgetId || this.settings.c,
        connectionSettings: widget_initializer_objectSpread({}, this.settings),
        isWidget: this.settings.isWidget || this.settings.f,
        isOperator: this.settings.d === undefined ? false : this.settings.d,
        pureServerUrl: this.settings.pureServerUrl,
        apiServerUrl: this.settings.apiServerUrl,
        renderInto: jquery_default()('body')
      };
    }
  }, {
    key: "createViewOptions",
    value: function createViewOptions() {
      var usePrototypeFallback = false;

      if (typeof window.Prototype !== 'undefined') {
        try {
          var splitVersion = window.Prototype.Version.split(/\./g);

          if (splitVersion.length > 0) {
            // eslint-disable-next-line no-magic-numbers
            usePrototypeFallback = parseInt(splitVersion[0], 10) >= 2 ? false : parseInt(splitVersion[1], 10) >= 7 ? false : true;
          }

          if (usePrototypeFallback) {
            // eslint-disable-next-line no-console
            console.log('PureChat widgets are not compatible with Prototype.js versions < 1.7. Default widget behavior will popout into a new window');
          }
        } catch (ex) {
          console.log(ex); // eslint-disable-line no-console
        }
      }

      return widget_initializer_objectSpread({}, this.settings, {}, {
        test: false,
        pureServerUrl: this.settings.pureServerUrl,
        widgetId: this.settings.widgetId || this.settings.c,
        isWidget: this.settings.isWidget || this.settings.f,
        isOperator: this.settings.d === undefined ? false : this.settings.d,
        renderInto: jquery_default()('body'),
        dataController: data_singleton["a" /* default */].getInstance(),
        usePrototypeFallback: usePrototypeFallback
      });
    }
  }, {
    key: "loadWidgetSettings",
    value: function loadWidgetSettings(versionNumber) {
      var widgetId = this.settings.overrideWidgetId || this.settings.widgetId;
      var url = "".concat(config_production_default.a.apiCdnServerUrl, "/api/visitorwidget/widget/").concat(widgetId, "/").concat(versionNumber);
      return jquery_default.a.ajax({
        url: url,
        jsonpCallback: '_WidgetJPCB_WidgetSettings',
        dataType: 'jsonp',
        cache: true
      });
    }
  }, {
    key: "disableAvailabilityPings",
    get: function get() {
      return this.settings.DisableAvailabilityPings || this.settings.IPIsBanned;
    }
  }]);

  return WidgetInitializer;
}();


// EXTERNAL MODULE: ./Scripts/widgets/legacy/services/dashboard_data.js
var dashboard_data = __webpack_require__(612);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/services/demo_data.js
function demo_data_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { demo_data_typeof = function _typeof(obj) { return typeof obj; }; } else { demo_data_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return demo_data_typeof(obj); }

function demo_data_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function demo_data_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function demo_data_createClass(Constructor, protoProps, staticProps) { if (protoProps) demo_data_defineProperties(Constructor.prototype, protoProps); if (staticProps) demo_data_defineProperties(Constructor, staticProps); return Constructor; }

function demo_data_possibleConstructorReturn(self, call) { if (call && (demo_data_typeof(call) === "object" || typeof call === "function")) { return call; } return demo_data_assertThisInitialized(self); }

function demo_data_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function demo_data_getPrototypeOf(o) { demo_data_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return demo_data_getPrototypeOf(o); }

function demo_data_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) demo_data_setPrototypeOf(subClass, superClass); }

function demo_data_setPrototypeOf(o, p) { demo_data_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return demo_data_setPrototypeOf(o, p); }





var demo_data_DemoDataController =
/*#__PURE__*/
function (_TestDataController) {
  demo_data_inherits(DemoDataController, _TestDataController);

  function DemoDataController() {
    demo_data_classCallCheck(this, DemoDataController);

    return demo_data_possibleConstructorReturn(this, demo_data_getPrototypeOf(DemoDataController).apply(this, arguments));
  }

  demo_data_createClass(DemoDataController, [{
    key: "getWidgetSettings",
    value: function getWidgetSettings() {
      var d = jquery_default.a.Deferred();

      if (window.parent && window.parent.currentWidgetSettings) {
        d.resolve(window.parent.currentWidgetSettings.attributes);
      } else {
        jquery_default.a.ajax({
          url: "".concat(this.getOption('apiServerUrl'), "/api/VisitorWidget/Widget/").concat(this.getOption('widgetId')).concat(window.location.search),
          dataType: 'jsonp',
          timeout: 20000,
          success: function success(response) {
            // we got the widget info ok - render the widget and advance to the next state
            response.UserWidgetSettings = new no_conflict["a" /* Backbone */].Model(response.UserWidgetSettings);
            var widgetSettings = {
              success: true,
              version: response.Version,
              accountId: response.AccountId,
              color: response.Color,
              position: response.Position,
              widgetType: response.WidgetType,
              widgetConfig: response,
              resources: response.StringResources,
              googleAnalytics: response.GoogleAnalytics,
              chatServerUrl: response.ChatServerUrl,
              ShowMinimizeWidgetButton: response.ShowMinimizeWidgetButton,
              userWidgetConfig: response.UserWidgetSettings
            };
            d.resolve(widgetSettings);
          },
          error: function error() {
            d.reject();
          }
        });
      }

      return d.promise();
    }
  }, {
    key: "isDemo",
    value: function isDemo() {
      return this.getOption('isDemo');
    }
  }, {
    key: "setDemoUnavailable",
    value: function setDemoUnavailable() {
      return this.getOption('setOperatorsUnavailable');
    }
  }]);

  return DemoDataController;
}(test_data);

/* harmony default export */ var demo_data = (demo_data_DemoDataController);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/controllers/dashboard_chat.js
function dashboard_chat_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { dashboard_chat_typeof = function _typeof(obj) { return typeof obj; }; } else { dashboard_chat_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return dashboard_chat_typeof(obj); }

function dashboard_chat_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function dashboard_chat_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function dashboard_chat_createClass(Constructor, protoProps, staticProps) { if (protoProps) dashboard_chat_defineProperties(Constructor.prototype, protoProps); if (staticProps) dashboard_chat_defineProperties(Constructor, staticProps); return Constructor; }

function dashboard_chat_possibleConstructorReturn(self, call) { if (call && (dashboard_chat_typeof(call) === "object" || typeof call === "function")) { return call; } return dashboard_chat_assertThisInitialized(self); }

function dashboard_chat_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function dashboard_chat_getPrototypeOf(o) { dashboard_chat_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return dashboard_chat_getPrototypeOf(o); }

function dashboard_chat_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) dashboard_chat_setPrototypeOf(subClass, superClass); }

function dashboard_chat_setPrototypeOf(o, p) { dashboard_chat_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return dashboard_chat_setPrototypeOf(o, p); }



var DashboardChatController =
/*#__PURE__*/
function (_PureChatController) {
  dashboard_chat_inherits(DashboardChatController, _PureChatController);

  function DashboardChatController(options) {
    dashboard_chat_classCallCheck(this, DashboardChatController);

    return dashboard_chat_possibleConstructorReturn(this, dashboard_chat_getPrototypeOf(DashboardChatController).call(this, options));
  }

  dashboard_chat_createClass(DashboardChatController, [{
    key: "scrolledToBottom",
    value: function scrolledToBottom() {
      var room = this.rm.get('room').id;
      if (window.PureChatEvents) window.PureChatEvents.trigger('dashboard:chats:scroll-bottom', room);
    }
  }]);

  return DashboardChatController;
}(purechat);

/* harmony default export */ var dashboard_chat = (DashboardChatController);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/main-dashboard.js





 // Dependenciese for public API









 // Puts the instance on the window so that the loader can be notified when
// everything fully loads.

var initializer = new widget_initializer_WidgetInitializer();
window._pcWidgetInitializer = initializer; // Provide a "Public API" to the Dashboard, editor, pop out widget

var main_dashboard_purechatApp = Object.create(app);
main_dashboard_purechatApp.Services = {
  DataServiceSingleton: data_singleton["a" /* default */],
  DemoDataService: demo_data,
  DashboardDataService: dashboard_data["a" /* default */],
  PCDataService: pc_data["a" /* default */]
};
main_dashboard_purechatApp.Controllers = {
  DashboardChatController: dashboard_chat,
  PureChatController: purechat
};
main_dashboard_purechatApp.Notifications = {
  Controller: notifications
};
main_dashboard_purechatApp.Models = {
  WidgetSettings: widget_settings_model
};
main_dashboard_purechatApp.Constants = constants["a" /* default */];
main_dashboard_purechatApp.$ = jquery_default.a;
window.purechatApp = main_dashboard_purechatApp;
// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/Errors.js
var Errors = __webpack_require__(60);

// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/HttpClient.js
var HttpClient = __webpack_require__(125);

// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/NodeHttpClient.js
var NodeHttpClient = __webpack_require__(641);

// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/ILogger.js
var ILogger = __webpack_require__(7);

// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var __extends = (undefined && undefined.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();



var XhrHttpClient_XhrHttpClient = /** @class */ (function (_super) {
    __extends(XhrHttpClient, _super);
    function XhrHttpClient(logger) {
        var _this = _super.call(this) || this;
        _this.logger = logger;
        return _this;
    }
    /** @inheritDoc */
    XhrHttpClient.prototype.send = function (request) {
        var _this = this;
        // Check that abort was not signaled before calling send
        if (request.abortSignal && request.abortSignal.aborted) {
            return Promise.reject(new Errors["a" /* AbortError */]());
        }
        if (!request.method) {
            return Promise.reject(new Error("No method defined."));
        }
        if (!request.url) {
            return Promise.reject(new Error("No url defined."));
        }
        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.open(request.method, request.url, true);
            xhr.withCredentials = true;
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            // Explicitly setting the Content-Type header for React Native on Android platform.
            xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
            var headers = request.headers;
            if (headers) {
                Object.keys(headers)
                    .forEach(function (header) {
                    xhr.setRequestHeader(header, headers[header]);
                });
            }
            if (request.responseType) {
                xhr.responseType = request.responseType;
            }
            if (request.abortSignal) {
                request.abortSignal.onabort = function () {
                    xhr.abort();
                    reject(new Errors["a" /* AbortError */]());
                };
            }
            if (request.timeout) {
                xhr.timeout = request.timeout;
            }
            xhr.onload = function () {
                if (request.abortSignal) {
                    request.abortSignal.onabort = null;
                }
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve(new HttpClient["b" /* HttpResponse */](xhr.status, xhr.statusText, xhr.response || xhr.responseText));
                }
                else {
                    reject(new Errors["b" /* HttpError */](xhr.statusText, xhr.status));
                }
            };
            xhr.onerror = function () {
                _this.logger.log(ILogger["a" /* LogLevel */].Warning, "Error from HTTP request. " + xhr.status + ": " + xhr.statusText + ".");
                reject(new Errors["b" /* HttpError */](xhr.statusText, xhr.status));
            };
            xhr.ontimeout = function () {
                _this.logger.log(ILogger["a" /* LogLevel */].Warning, "Timeout from HTTP request.");
                reject(new Errors["c" /* TimeoutError */]());
            };
            xhr.send(request.content || "");
        });
    };
    return XhrHttpClient;
}(HttpClient["a" /* HttpClient */]));

//# sourceMappingURL=XhrHttpClient.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var DefaultHttpClient_extends = (undefined && undefined.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();




/** Default implementation of {@link @microsoft/signalr.HttpClient}. */
var DefaultHttpClient_DefaultHttpClient = /** @class */ (function (_super) {
    DefaultHttpClient_extends(DefaultHttpClient, _super);
    /** Creates a new instance of the {@link @microsoft/signalr.DefaultHttpClient}, using the provided {@link @microsoft/signalr.ILogger} to log messages. */
    function DefaultHttpClient(logger) {
        var _this = _super.call(this) || this;
        if (typeof XMLHttpRequest !== "undefined") {
            _this.httpClient = new XhrHttpClient_XhrHttpClient(logger);
        }
        else {
            _this.httpClient = new NodeHttpClient["a" /* NodeHttpClient */](logger);
        }
        return _this;
    }
    /** @inheritDoc */
    DefaultHttpClient.prototype.send = function (request) {
        // Check that abort was not signaled before calling send
        if (request.abortSignal && request.abortSignal.aborted) {
            return Promise.reject(new Errors["a" /* AbortError */]());
        }
        if (!request.method) {
            return Promise.reject(new Error("No method defined."));
        }
        if (!request.url) {
            return Promise.reject(new Error("No url defined."));
        }
        return this.httpClient.send(request);
    };
    DefaultHttpClient.prototype.getCookieString = function (url) {
        return this.httpClient.getCookieString(url);
    };
    return DefaultHttpClient;
}(HttpClient["a" /* HttpClient */]));

//# sourceMappingURL=DefaultHttpClient.js.map
// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js
var HandshakeProtocol = __webpack_require__(642);

// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
/** Defines the type of a Hub Message. */
var MessageType;
(function (MessageType) {
    /** Indicates the message is an Invocation message and implements the {@link @microsoft/signalr.InvocationMessage} interface. */
    MessageType[MessageType["Invocation"] = 1] = "Invocation";
    /** Indicates the message is a StreamItem message and implements the {@link @microsoft/signalr.StreamItemMessage} interface. */
    MessageType[MessageType["StreamItem"] = 2] = "StreamItem";
    /** Indicates the message is a Completion message and implements the {@link @microsoft/signalr.CompletionMessage} interface. */
    MessageType[MessageType["Completion"] = 3] = "Completion";
    /** Indicates the message is a Stream Invocation message and implements the {@link @microsoft/signalr.StreamInvocationMessage} interface. */
    MessageType[MessageType["StreamInvocation"] = 4] = "StreamInvocation";
    /** Indicates the message is a Cancel Invocation message and implements the {@link @microsoft/signalr.CancelInvocationMessage} interface. */
    MessageType[MessageType["CancelInvocation"] = 5] = "CancelInvocation";
    /** Indicates the message is a Ping message and implements the {@link @microsoft/signalr.PingMessage} interface. */
    MessageType[MessageType["Ping"] = 6] = "Ping";
    /** Indicates the message is a Close message and implements the {@link @microsoft/signalr.CloseMessage} interface. */
    MessageType[MessageType["Close"] = 7] = "Close";
})(MessageType || (MessageType = {}));
//# sourceMappingURL=IHubProtocol.js.map
// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/Utils.js
var Utils = __webpack_require__(29);

// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/Subject.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

/** Stream implementation to stream items to the server. */
var Subject_Subject = /** @class */ (function () {
    function Subject() {
        this.observers = [];
    }
    Subject.prototype.next = function (item) {
        for (var _i = 0, _a = this.observers; _i < _a.length; _i++) {
            var observer = _a[_i];
            observer.next(item);
        }
    };
    Subject.prototype.error = function (err) {
        for (var _i = 0, _a = this.observers; _i < _a.length; _i++) {
            var observer = _a[_i];
            if (observer.error) {
                observer.error(err);
            }
        }
    };
    Subject.prototype.complete = function () {
        for (var _i = 0, _a = this.observers; _i < _a.length; _i++) {
            var observer = _a[_i];
            if (observer.complete) {
                observer.complete();
            }
        }
    };
    Subject.prototype.subscribe = function (observer) {
        this.observers.push(observer);
        return new Utils["d" /* SubjectSubscription */](this, observer);
    };
    return Subject;
}());

//# sourceMappingURL=Subject.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/HubConnection.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (undefined && undefined.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};





var DEFAULT_TIMEOUT_IN_MS = 30 * 1000;
var DEFAULT_PING_INTERVAL_IN_MS = 15 * 1000;
/** Describes the current state of the {@link HubConnection} to the server. */
var HubConnectionState;
(function (HubConnectionState) {
    /** The hub connection is disconnected. */
    HubConnectionState["Disconnected"] = "Disconnected";
    /** The hub connection is connecting. */
    HubConnectionState["Connecting"] = "Connecting";
    /** The hub connection is connected. */
    HubConnectionState["Connected"] = "Connected";
    /** The hub connection is disconnecting. */
    HubConnectionState["Disconnecting"] = "Disconnecting";
    /** The hub connection is reconnecting. */
    HubConnectionState["Reconnecting"] = "Reconnecting";
})(HubConnectionState || (HubConnectionState = {}));
/** Represents a connection to a SignalR Hub. */
var HubConnection_HubConnection = /** @class */ (function () {
    function HubConnection(connection, logger, protocol, reconnectPolicy) {
        var _this = this;
        Utils["a" /* Arg */].isRequired(connection, "connection");
        Utils["a" /* Arg */].isRequired(logger, "logger");
        Utils["a" /* Arg */].isRequired(protocol, "protocol");
        this.serverTimeoutInMilliseconds = DEFAULT_TIMEOUT_IN_MS;
        this.keepAliveIntervalInMilliseconds = DEFAULT_PING_INTERVAL_IN_MS;
        this.logger = logger;
        this.protocol = protocol;
        this.connection = connection;
        this.reconnectPolicy = reconnectPolicy;
        this.handshakeProtocol = new HandshakeProtocol["a" /* HandshakeProtocol */]();
        this.connection.onreceive = function (data) { return _this.processIncomingData(data); };
        this.connection.onclose = function (error) { return _this.connectionClosed(error); };
        this.callbacks = {};
        this.methods = {};
        this.closedCallbacks = [];
        this.reconnectingCallbacks = [];
        this.reconnectedCallbacks = [];
        this.invocationId = 0;
        this.receivedHandshakeResponse = false;
        this.connectionState = HubConnectionState.Disconnected;
        this.connectionStarted = false;
        this.cachedPingMessage = this.protocol.writeMessage({ type: MessageType.Ping });
    }
    /** @internal */
    // Using a public static factory method means we can have a private constructor and an _internal_
    // create method that can be used by HubConnectionBuilder. An "internal" constructor would just
    // be stripped away and the '.d.ts' file would have no constructor, which is interpreted as a
    // public parameter-less constructor.
    HubConnection.create = function (connection, logger, protocol, reconnectPolicy) {
        return new HubConnection(connection, logger, protocol, reconnectPolicy);
    };
    Object.defineProperty(HubConnection.prototype, "state", {
        /** Indicates the state of the {@link HubConnection} to the server. */
        get: function () {
            return this.connectionState;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(HubConnection.prototype, "connectionId", {
        /** Represents the connection id of the {@link HubConnection} on the server. The connection id will be null when the connection is either
         *  in the disconnected state or if the negotiation step was skipped.
         */
        get: function () {
            return this.connection ? (this.connection.connectionId || null) : null;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(HubConnection.prototype, "baseUrl", {
        /** Indicates the url of the {@link HubConnection} to the server. */
        get: function () {
            return this.connection.baseUrl || "";
        },
        /**
         * Sets a new url for the HubConnection. Note that the url can only be changed when the connection is in either the Disconnected or
         * Reconnecting states.
         * @param {string} url The url to connect to.
         */
        set: function (url) {
            if (this.connectionState !== HubConnectionState.Disconnected && this.connectionState !== HubConnectionState.Reconnecting) {
                throw new Error("The HubConnection must be in the Disconnected or Reconnecting state to change the url.");
            }
            if (!url) {
                throw new Error("The HubConnection url must be a valid url.");
            }
            this.connection.baseUrl = url;
        },
        enumerable: true,
        configurable: true
    });
    /** Starts the connection.
     *
     * @returns {Promise<void>} A Promise that resolves when the connection has been successfully established, or rejects with an error.
     */
    HubConnection.prototype.start = function () {
        this.startPromise = this.startWithStateTransitions();
        return this.startPromise;
    };
    HubConnection.prototype.startWithStateTransitions = function () {
        return __awaiter(this, void 0, void 0, function () {
            var e_1;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (this.connectionState !== HubConnectionState.Disconnected) {
                            return [2 /*return*/, Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."))];
                        }
                        this.connectionState = HubConnectionState.Connecting;
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Starting HubConnection.");
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 3, , 4]);
                        return [4 /*yield*/, this.startInternal()];
                    case 2:
                        _a.sent();
                        this.connectionState = HubConnectionState.Connected;
                        this.connectionStarted = true;
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "HubConnection connected successfully.");
                        return [3 /*break*/, 4];
                    case 3:
                        e_1 = _a.sent();
                        this.connectionState = HubConnectionState.Disconnected;
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "HubConnection failed to start successfully because of error '" + e_1 + "'.");
                        return [2 /*return*/, Promise.reject(e_1)];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    HubConnection.prototype.startInternal = function () {
        return __awaiter(this, void 0, void 0, function () {
            var handshakePromise, handshakeRequest, e_2;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        this.stopDuringStartError = undefined;
                        this.receivedHandshakeResponse = false;
                        handshakePromise = new Promise(function (resolve, reject) {
                            _this.handshakeResolver = resolve;
                            _this.handshakeRejecter = reject;
                        });
                        return [4 /*yield*/, this.connection.start(this.protocol.transferFormat)];
                    case 1:
                        _a.sent();
                        _a.label = 2;
                    case 2:
                        _a.trys.push([2, 5, , 7]);
                        handshakeRequest = {
                            protocol: this.protocol.name,
                            version: this.protocol.version,
                        };
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Sending handshake request.");
                        return [4 /*yield*/, this.sendMessage(this.handshakeProtocol.writeHandshakeRequest(handshakeRequest))];
                    case 3:
                        _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Information, "Using HubProtocol '" + this.protocol.name + "'.");
                        // defensively cleanup timeout in case we receive a message from the server before we finish start
                        this.cleanupTimeout();
                        this.resetTimeoutPeriod();
                        this.resetKeepAliveInterval();
                        return [4 /*yield*/, handshakePromise];
                    case 4:
                        _a.sent();
                        // It's important to check the stopDuringStartError instead of just relying on the handshakePromise
                        // being rejected on close, because this continuation can run after both the handshake completed successfully
                        // and the connection was closed.
                        if (this.stopDuringStartError) {
                            // It's important to throw instead of returning a rejected promise, because we don't want to allow any state
                            // transitions to occur between now and the calling code observing the exceptions. Returning a rejected promise
                            // will cause the calling continuation to get scheduled to run later.
                            throw this.stopDuringStartError;
                        }
                        return [3 /*break*/, 7];
                    case 5:
                        e_2 = _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Hub handshake failed with error '" + e_2 + "' during start(). Stopping HubConnection.");
                        this.cleanupTimeout();
                        this.cleanupPingTimer();
                        // HttpConnection.stop() should not complete until after the onclose callback is invoked.
                        // This will transition the HubConnection to the disconnected state before HttpConnection.stop() completes.
                        return [4 /*yield*/, this.connection.stop(e_2)];
                    case 6:
                        // HttpConnection.stop() should not complete until after the onclose callback is invoked.
                        // This will transition the HubConnection to the disconnected state before HttpConnection.stop() completes.
                        _a.sent();
                        throw e_2;
                    case 7: return [2 /*return*/];
                }
            });
        });
    };
    /** Stops the connection.
     *
     * @returns {Promise<void>} A Promise that resolves when the connection has been successfully terminated, or rejects with an error.
     */
    HubConnection.prototype.stop = function () {
        return __awaiter(this, void 0, void 0, function () {
            var startPromise, e_3;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        startPromise = this.startPromise;
                        this.stopPromise = this.stopInternal();
                        return [4 /*yield*/, this.stopPromise];
                    case 1:
                        _a.sent();
                        _a.label = 2;
                    case 2:
                        _a.trys.push([2, 4, , 5]);
                        // Awaiting undefined continues immediately
                        return [4 /*yield*/, startPromise];
                    case 3:
                        // Awaiting undefined continues immediately
                        _a.sent();
                        return [3 /*break*/, 5];
                    case 4:
                        e_3 = _a.sent();
                        return [3 /*break*/, 5];
                    case 5: return [2 /*return*/];
                }
            });
        });
    };
    HubConnection.prototype.stopInternal = function (error) {
        if (this.connectionState === HubConnectionState.Disconnected) {
            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Call to HubConnection.stop(" + error + ") ignored because it is already in the disconnected state.");
            return Promise.resolve();
        }
        if (this.connectionState === HubConnectionState.Disconnecting) {
            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Call to HttpConnection.stop(" + error + ") ignored because the connection is already in the disconnecting state.");
            return this.stopPromise;
        }
        this.connectionState = HubConnectionState.Disconnecting;
        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Stopping HubConnection.");
        if (this.reconnectDelayHandle) {
            // We're in a reconnect delay which means the underlying connection is currently already stopped.
            // Just clear the handle to stop the reconnect loop (which no one is waiting on thankfully) and
            // fire the onclose callbacks.
            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Connection stopped during reconnect delay. Done reconnecting.");
            clearTimeout(this.reconnectDelayHandle);
            this.reconnectDelayHandle = undefined;
            this.completeClose();
            return Promise.resolve();
        }
        this.cleanupTimeout();
        this.cleanupPingTimer();
        this.stopDuringStartError = error || new Error("The connection was stopped before the hub handshake could complete.");
        // HttpConnection.stop() should not complete until after either HttpConnection.start() fails
        // or the onclose callback is invoked. The onclose callback will transition the HubConnection
        // to the disconnected state if need be before HttpConnection.stop() completes.
        return this.connection.stop(error);
    };
    /** Invokes a streaming hub method on the server using the specified name and arguments.
     *
     * @typeparam T The type of the items returned by the server.
     * @param {string} methodName The name of the server method to invoke.
     * @param {any[]} args The arguments used to invoke the server method.
     * @returns {IStreamResult<T>} An object that yields results from the server as they are received.
     */
    HubConnection.prototype.stream = function (methodName) {
        var _this = this;
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        var _a = this.replaceStreamingParams(args), streams = _a[0], streamIds = _a[1];
        var invocationDescriptor = this.createStreamInvocation(methodName, args, streamIds);
        var promiseQueue;
        var subject = new Subject_Subject();
        subject.cancelCallback = function () {
            var cancelInvocation = _this.createCancelInvocation(invocationDescriptor.invocationId);
            delete _this.callbacks[invocationDescriptor.invocationId];
            return promiseQueue.then(function () {
                return _this.sendWithProtocol(cancelInvocation);
            });
        };
        this.callbacks[invocationDescriptor.invocationId] = function (invocationEvent, error) {
            if (error) {
                subject.error(error);
                return;
            }
            else if (invocationEvent) {
                // invocationEvent will not be null when an error is not passed to the callback
                if (invocationEvent.type === MessageType.Completion) {
                    if (invocationEvent.error) {
                        subject.error(new Error(invocationEvent.error));
                    }
                    else {
                        subject.complete();
                    }
                }
                else {
                    subject.next((invocationEvent.item));
                }
            }
        };
        promiseQueue = this.sendWithProtocol(invocationDescriptor)
            .catch(function (e) {
            subject.error(e);
            delete _this.callbacks[invocationDescriptor.invocationId];
        });
        this.launchStreams(streams, promiseQueue);
        return subject;
    };
    HubConnection.prototype.sendMessage = function (message) {
        this.resetKeepAliveInterval();
        return this.connection.send(message);
    };
    /**
     * Sends a js object to the server.
     * @param message The js object to serialize and send.
     */
    HubConnection.prototype.sendWithProtocol = function (message) {
        return this.sendMessage(this.protocol.writeMessage(message));
    };
    /** Invokes a hub method on the server using the specified name and arguments. Does not wait for a response from the receiver.
     *
     * The Promise returned by this method resolves when the client has sent the invocation to the server. The server may still
     * be processing the invocation.
     *
     * @param {string} methodName The name of the server method to invoke.
     * @param {any[]} args The arguments used to invoke the server method.
     * @returns {Promise<void>} A Promise that resolves when the invocation has been successfully sent, or rejects with an error.
     */
    HubConnection.prototype.send = function (methodName) {
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        var _a = this.replaceStreamingParams(args), streams = _a[0], streamIds = _a[1];
        var sendPromise = this.sendWithProtocol(this.createInvocation(methodName, args, true, streamIds));
        this.launchStreams(streams, sendPromise);
        return sendPromise;
    };
    /** Invokes a hub method on the server using the specified name and arguments.
     *
     * The Promise returned by this method resolves when the server indicates it has finished invoking the method. When the promise
     * resolves, the server has finished invoking the method. If the server method returns a result, it is produced as the result of
     * resolving the Promise.
     *
     * @typeparam T The expected return type.
     * @param {string} methodName The name of the server method to invoke.
     * @param {any[]} args The arguments used to invoke the server method.
     * @returns {Promise<T>} A Promise that resolves with the result of the server method (if any), or rejects with an error.
     */
    HubConnection.prototype.invoke = function (methodName) {
        var _this = this;
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        var _a = this.replaceStreamingParams(args), streams = _a[0], streamIds = _a[1];
        var invocationDescriptor = this.createInvocation(methodName, args, false, streamIds);
        var p = new Promise(function (resolve, reject) {
            // invocationId will always have a value for a non-blocking invocation
            _this.callbacks[invocationDescriptor.invocationId] = function (invocationEvent, error) {
                if (error) {
                    reject(error);
                    return;
                }
                else if (invocationEvent) {
                    // invocationEvent will not be null when an error is not passed to the callback
                    if (invocationEvent.type === MessageType.Completion) {
                        if (invocationEvent.error) {
                            reject(new Error(invocationEvent.error));
                        }
                        else {
                            resolve(invocationEvent.result);
                        }
                    }
                    else {
                        reject(new Error("Unexpected message type: " + invocationEvent.type));
                    }
                }
            };
            var promiseQueue = _this.sendWithProtocol(invocationDescriptor)
                .catch(function (e) {
                reject(e);
                // invocationId will always have a value for a non-blocking invocation
                delete _this.callbacks[invocationDescriptor.invocationId];
            });
            _this.launchStreams(streams, promiseQueue);
        });
        return p;
    };
    /** Registers a handler that will be invoked when the hub method with the specified method name is invoked.
     *
     * @param {string} methodName The name of the hub method to define.
     * @param {Function} newMethod The handler that will be raised when the hub method is invoked.
     */
    HubConnection.prototype.on = function (methodName, newMethod) {
        if (!methodName || !newMethod) {
            return;
        }
        methodName = methodName.toLowerCase();
        if (!this.methods[methodName]) {
            this.methods[methodName] = [];
        }
        // Preventing adding the same handler multiple times.
        if (this.methods[methodName].indexOf(newMethod) !== -1) {
            return;
        }
        this.methods[methodName].push(newMethod);
    };
    HubConnection.prototype.off = function (methodName, method) {
        if (!methodName) {
            return;
        }
        methodName = methodName.toLowerCase();
        var handlers = this.methods[methodName];
        if (!handlers) {
            return;
        }
        if (method) {
            var removeIdx = handlers.indexOf(method);
            if (removeIdx !== -1) {
                handlers.splice(removeIdx, 1);
                if (handlers.length === 0) {
                    delete this.methods[methodName];
                }
            }
        }
        else {
            delete this.methods[methodName];
        }
    };
    /** Registers a handler that will be invoked when the connection is closed.
     *
     * @param {Function} callback The handler that will be invoked when the connection is closed. Optionally receives a single argument containing the error that caused the connection to close (if any).
     */
    HubConnection.prototype.onclose = function (callback) {
        if (callback) {
            this.closedCallbacks.push(callback);
        }
    };
    /** Registers a handler that will be invoked when the connection starts reconnecting.
     *
     * @param {Function} callback The handler that will be invoked when the connection starts reconnecting. Optionally receives a single argument containing the error that caused the connection to start reconnecting (if any).
     */
    HubConnection.prototype.onreconnecting = function (callback) {
        if (callback) {
            this.reconnectingCallbacks.push(callback);
        }
    };
    /** Registers a handler that will be invoked when the connection successfully reconnects.
     *
     * @param {Function} callback The handler that will be invoked when the connection successfully reconnects.
     */
    HubConnection.prototype.onreconnected = function (callback) {
        if (callback) {
            this.reconnectedCallbacks.push(callback);
        }
    };
    HubConnection.prototype.processIncomingData = function (data) {
        this.cleanupTimeout();
        if (!this.receivedHandshakeResponse) {
            data = this.processHandshakeResponse(data);
            this.receivedHandshakeResponse = true;
        }
        // Data may have all been read when processing handshake response
        if (data) {
            // Parse the messages
            var messages = this.protocol.parseMessages(data, this.logger);
            for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) {
                var message = messages_1[_i];
                switch (message.type) {
                    case MessageType.Invocation:
                        this.invokeClientMethod(message);
                        break;
                    case MessageType.StreamItem:
                    case MessageType.Completion:
                        var callback = this.callbacks[message.invocationId];
                        if (callback) {
                            if (message.type === MessageType.Completion) {
                                delete this.callbacks[message.invocationId];
                            }
                            callback(message);
                        }
                        break;
                    case MessageType.Ping:
                        // Don't care about pings
                        break;
                    case MessageType.Close:
                        this.logger.log(ILogger["a" /* LogLevel */].Information, "Close message received from server.");
                        // We don't want to wait on the stop itself.
                        this.stopPromise = this.stopInternal(message.error ? new Error("Server returned an error on close: " + message.error) : undefined);
                        break;
                    default:
                        this.logger.log(ILogger["a" /* LogLevel */].Warning, "Invalid message type: " + message.type + ".");
                        break;
                }
            }
        }
        this.resetTimeoutPeriod();
    };
    HubConnection.prototype.processHandshakeResponse = function (data) {
        var _a;
        var responseMessage;
        var remainingData;
        try {
            _a = this.handshakeProtocol.parseHandshakeResponse(data), remainingData = _a[0], responseMessage = _a[1];
        }
        catch (e) {
            var message = "Error parsing handshake response: " + e;
            this.logger.log(ILogger["a" /* LogLevel */].Error, message);
            var error = new Error(message);
            this.handshakeRejecter(error);
            throw error;
        }
        if (responseMessage.error) {
            var message = "Server returned handshake error: " + responseMessage.error;
            this.logger.log(ILogger["a" /* LogLevel */].Error, message);
            var error = new Error(message);
            this.handshakeRejecter(error);
            throw error;
        }
        else {
            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Server handshake complete.");
        }
        this.handshakeResolver();
        return remainingData;
    };
    HubConnection.prototype.resetKeepAliveInterval = function () {
        var _this = this;
        this.cleanupPingTimer();
        this.pingServerHandle = setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!(this.connectionState === HubConnectionState.Connected)) return [3 /*break*/, 4];
                        _b.label = 1;
                    case 1:
                        _b.trys.push([1, 3, , 4]);
                        return [4 /*yield*/, this.sendMessage(this.cachedPingMessage)];
                    case 2:
                        _b.sent();
                        return [3 /*break*/, 4];
                    case 3:
                        _a = _b.sent();
                        // We don't care about the error. It should be seen elsewhere in the client.
                        // The connection is probably in a bad or closed state now, cleanup the timer so it stops triggering
                        this.cleanupPingTimer();
                        return [3 /*break*/, 4];
                    case 4: return [2 /*return*/];
                }
            });
        }); }, this.keepAliveIntervalInMilliseconds);
    };
    HubConnection.prototype.resetTimeoutPeriod = function () {
        var _this = this;
        if (!this.connection.features || !this.connection.features.inherentKeepAlive) {
            // Set the timeout timer
            this.timeoutHandle = setTimeout(function () { return _this.serverTimeout(); }, this.serverTimeoutInMilliseconds);
        }
    };
    HubConnection.prototype.serverTimeout = function () {
        // The server hasn't talked to us in a while. It doesn't like us anymore ... :(
        // Terminate the connection, but we don't need to wait on the promise. This could trigger reconnecting.
        // tslint:disable-next-line:no-floating-promises
        this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."));
    };
    HubConnection.prototype.invokeClientMethod = function (invocationMessage) {
        var _this = this;
        var methods = this.methods[invocationMessage.target.toLowerCase()];
        if (methods) {
            try {
                methods.forEach(function (m) { return m.apply(_this, invocationMessage.arguments); });
            }
            catch (e) {
                this.logger.log(ILogger["a" /* LogLevel */].Error, "A callback for the method " + invocationMessage.target.toLowerCase() + " threw error '" + e + "'.");
            }
            if (invocationMessage.invocationId) {
                // This is not supported in v1. So we return an error to avoid blocking the server waiting for the response.
                var message = "Server requested a response, which is not supported in this version of the client.";
                this.logger.log(ILogger["a" /* LogLevel */].Error, message);
                // We don't want to wait on the stop itself.
                this.stopPromise = this.stopInternal(new Error(message));
            }
        }
        else {
            this.logger.log(ILogger["a" /* LogLevel */].Warning, "No client method with the name '" + invocationMessage.target + "' found.");
        }
    };
    HubConnection.prototype.connectionClosed = function (error) {
        this.logger.log(ILogger["a" /* LogLevel */].Debug, "HubConnection.connectionClosed(" + error + ") called while in state " + this.connectionState + ".");
        // Triggering this.handshakeRejecter is insufficient because it could already be resolved without the continuation having run yet.
        this.stopDuringStartError = this.stopDuringStartError || error || new Error("The underlying connection was closed before the hub handshake could complete.");
        // If the handshake is in progress, start will be waiting for the handshake promise, so we complete it.
        // If it has already completed, this should just noop.
        if (this.handshakeResolver) {
            this.handshakeResolver();
        }
        this.cancelCallbacksWithError(error || new Error("Invocation canceled due to the underlying connection being closed."));
        this.cleanupTimeout();
        this.cleanupPingTimer();
        if (this.connectionState === HubConnectionState.Disconnecting) {
            this.completeClose(error);
        }
        else if (this.connectionState === HubConnectionState.Connected && this.reconnectPolicy) {
            // tslint:disable-next-line:no-floating-promises
            this.reconnect(error);
        }
        else if (this.connectionState === HubConnectionState.Connected) {
            this.completeClose(error);
        }
        // If none of the above if conditions were true were called the HubConnection must be in either:
        // 1. The Connecting state in which case the handshakeResolver will complete it and stopDuringStartError will fail it.
        // 2. The Reconnecting state in which case the handshakeResolver will complete it and stopDuringStartError will fail the current reconnect attempt
        //    and potentially continue the reconnect() loop.
        // 3. The Disconnected state in which case we're already done.
    };
    HubConnection.prototype.completeClose = function (error) {
        var _this = this;
        if (this.connectionStarted) {
            this.connectionState = HubConnectionState.Disconnected;
            this.connectionStarted = false;
            try {
                this.closedCallbacks.forEach(function (c) { return c.apply(_this, [error]); });
            }
            catch (e) {
                this.logger.log(ILogger["a" /* LogLevel */].Error, "An onclose callback called with error '" + error + "' threw error '" + e + "'.");
            }
        }
    };
    HubConnection.prototype.reconnect = function (error) {
        return __awaiter(this, void 0, void 0, function () {
            var reconnectStartTime, previousReconnectAttempts, retryError, nextRetryDelay, e_4;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        reconnectStartTime = Date.now();
                        previousReconnectAttempts = 0;
                        retryError = error !== undefined ? error : new Error("Attempting to reconnect due to a unknown error.");
                        nextRetryDelay = this.getNextRetryDelay(previousReconnectAttempts++, 0, retryError);
                        if (nextRetryDelay === null) {
                            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt.");
                            this.completeClose(error);
                            return [2 /*return*/];
                        }
                        this.connectionState = HubConnectionState.Reconnecting;
                        if (error) {
                            this.logger.log(ILogger["a" /* LogLevel */].Information, "Connection reconnecting because of error '" + error + "'.");
                        }
                        else {
                            this.logger.log(ILogger["a" /* LogLevel */].Information, "Connection reconnecting.");
                        }
                        if (this.onreconnecting) {
                            try {
                                this.reconnectingCallbacks.forEach(function (c) { return c.apply(_this, [error]); });
                            }
                            catch (e) {
                                this.logger.log(ILogger["a" /* LogLevel */].Error, "An onreconnecting callback called with error '" + error + "' threw error '" + e + "'.");
                            }
                            // Exit early if an onreconnecting callback called connection.stop().
                            if (this.connectionState !== HubConnectionState.Reconnecting) {
                                this.logger.log(ILogger["a" /* LogLevel */].Debug, "Connection left the reconnecting state in onreconnecting callback. Done reconnecting.");
                                return [2 /*return*/];
                            }
                        }
                        _a.label = 1;
                    case 1:
                        if (!(nextRetryDelay !== null)) return [3 /*break*/, 7];
                        this.logger.log(ILogger["a" /* LogLevel */].Information, "Reconnect attempt number " + previousReconnectAttempts + " will start in " + nextRetryDelay + " ms.");
                        return [4 /*yield*/, new Promise(function (resolve) {
                                _this.reconnectDelayHandle = setTimeout(resolve, nextRetryDelay);
                            })];
                    case 2:
                        _a.sent();
                        this.reconnectDelayHandle = undefined;
                        if (this.connectionState !== HubConnectionState.Reconnecting) {
                            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Connection left the reconnecting state during reconnect delay. Done reconnecting.");
                            return [2 /*return*/];
                        }
                        _a.label = 3;
                    case 3:
                        _a.trys.push([3, 5, , 6]);
                        return [4 /*yield*/, this.startInternal()];
                    case 4:
                        _a.sent();
                        this.connectionState = HubConnectionState.Connected;
                        this.logger.log(ILogger["a" /* LogLevel */].Information, "HubConnection reconnected successfully.");
                        if (this.onreconnected) {
                            try {
                                this.reconnectedCallbacks.forEach(function (c) { return c.apply(_this, [_this.connection.connectionId]); });
                            }
                            catch (e) {
                                this.logger.log(ILogger["a" /* LogLevel */].Error, "An onreconnected callback called with connectionId '" + this.connection.connectionId + "; threw error '" + e + "'.");
                            }
                        }
                        return [2 /*return*/];
                    case 5:
                        e_4 = _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Information, "Reconnect attempt failed because of error '" + e_4 + "'.");
                        if (this.connectionState !== HubConnectionState.Reconnecting) {
                            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Connection left the reconnecting state during reconnect attempt. Done reconnecting.");
                            return [2 /*return*/];
                        }
                        retryError = e_4 instanceof Error ? e_4 : new Error(e_4.toString());
                        nextRetryDelay = this.getNextRetryDelay(previousReconnectAttempts++, Date.now() - reconnectStartTime, retryError);
                        return [3 /*break*/, 6];
                    case 6: return [3 /*break*/, 1];
                    case 7:
                        this.logger.log(ILogger["a" /* LogLevel */].Information, "Reconnect retries have been exhausted after " + (Date.now() - reconnectStartTime) + " ms and " + previousReconnectAttempts + " failed attempts. Connection disconnecting.");
                        this.completeClose();
                        return [2 /*return*/];
                }
            });
        });
    };
    HubConnection.prototype.getNextRetryDelay = function (previousRetryCount, elapsedMilliseconds, retryReason) {
        try {
            return this.reconnectPolicy.nextRetryDelayInMilliseconds({
                elapsedMilliseconds: elapsedMilliseconds,
                previousRetryCount: previousRetryCount,
                retryReason: retryReason,
            });
        }
        catch (e) {
            this.logger.log(ILogger["a" /* LogLevel */].Error, "IRetryPolicy.nextRetryDelayInMilliseconds(" + previousRetryCount + ", " + elapsedMilliseconds + ") threw error '" + e + "'.");
            return null;
        }
    };
    HubConnection.prototype.cancelCallbacksWithError = function (error) {
        var callbacks = this.callbacks;
        this.callbacks = {};
        Object.keys(callbacks)
            .forEach(function (key) {
            var callback = callbacks[key];
            callback(null, error);
        });
    };
    HubConnection.prototype.cleanupPingTimer = function () {
        if (this.pingServerHandle) {
            clearTimeout(this.pingServerHandle);
        }
    };
    HubConnection.prototype.cleanupTimeout = function () {
        if (this.timeoutHandle) {
            clearTimeout(this.timeoutHandle);
        }
    };
    HubConnection.prototype.createInvocation = function (methodName, args, nonblocking, streamIds) {
        if (nonblocking) {
            return {
                arguments: args,
                streamIds: streamIds,
                target: methodName,
                type: MessageType.Invocation,
            };
        }
        else {
            var invocationId = this.invocationId;
            this.invocationId++;
            return {
                arguments: args,
                invocationId: invocationId.toString(),
                streamIds: streamIds,
                target: methodName,
                type: MessageType.Invocation,
            };
        }
    };
    HubConnection.prototype.launchStreams = function (streams, promiseQueue) {
        var _this = this;
        if (streams.length === 0) {
            return;
        }
        // Synchronize stream data so they arrive in-order on the server
        if (!promiseQueue) {
            promiseQueue = Promise.resolve();
        }
        var _loop_1 = function (streamId) {
            streams[streamId].subscribe({
                complete: function () {
                    promiseQueue = promiseQueue.then(function () { return _this.sendWithProtocol(_this.createCompletionMessage(streamId)); });
                },
                error: function (err) {
                    var message;
                    if (err instanceof Error) {
                        message = err.message;
                    }
                    else if (err && err.toString) {
                        message = err.toString();
                    }
                    else {
                        message = "Unknown error";
                    }
                    promiseQueue = promiseQueue.then(function () { return _this.sendWithProtocol(_this.createCompletionMessage(streamId, message)); });
                },
                next: function (item) {
                    promiseQueue = promiseQueue.then(function () { return _this.sendWithProtocol(_this.createStreamItemMessage(streamId, item)); });
                },
            });
        };
        // We want to iterate over the keys, since the keys are the stream ids
        // tslint:disable-next-line:forin
        for (var streamId in streams) {
            _loop_1(streamId);
        }
    };
    HubConnection.prototype.replaceStreamingParams = function (args) {
        var streams = [];
        var streamIds = [];
        for (var i = 0; i < args.length; i++) {
            var argument = args[i];
            if (this.isObservable(argument)) {
                var streamId = this.invocationId;
                this.invocationId++;
                // Store the stream for later use
                streams[streamId] = argument;
                streamIds.push(streamId.toString());
                // remove stream from args
                args.splice(i, 1);
            }
        }
        return [streams, streamIds];
    };
    HubConnection.prototype.isObservable = function (arg) {
        // This allows other stream implementations to just work (like rxjs)
        return arg && arg.subscribe && typeof arg.subscribe === "function";
    };
    HubConnection.prototype.createStreamInvocation = function (methodName, args, streamIds) {
        var invocationId = this.invocationId;
        this.invocationId++;
        return {
            arguments: args,
            invocationId: invocationId.toString(),
            streamIds: streamIds,
            target: methodName,
            type: MessageType.StreamInvocation,
        };
    };
    HubConnection.prototype.createCancelInvocation = function (id) {
        return {
            invocationId: id,
            type: MessageType.CancelInvocation,
        };
    };
    HubConnection.prototype.createStreamItemMessage = function (id, item) {
        return {
            invocationId: id,
            item: item,
            type: MessageType.StreamItem,
        };
    };
    HubConnection.prototype.createCompletionMessage = function (id, error, result) {
        if (error) {
            return {
                error: error,
                invocationId: id,
                type: MessageType.Completion,
            };
        }
        return {
            invocationId: id,
            result: result,
            type: MessageType.Completion,
        };
    };
    return HubConnection;
}());

//# sourceMappingURL=HubConnection.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// 0, 2, 10, 30 second delays before reconnect attempts.
var DEFAULT_RETRY_DELAYS_IN_MILLISECONDS = [0, 2000, 10000, 30000, null];
/** @private */
var DefaultReconnectPolicy = /** @class */ (function () {
    function DefaultReconnectPolicy(retryDelays) {
        this.retryDelays = retryDelays !== undefined ? retryDelays.concat([null]) : DEFAULT_RETRY_DELAYS_IN_MILLISECONDS;
    }
    DefaultReconnectPolicy.prototype.nextRetryDelayInMilliseconds = function (retryContext) {
        return this.retryDelays[retryContext.previousRetryCount];
    };
    return DefaultReconnectPolicy;
}());

//# sourceMappingURL=DefaultReconnectPolicy.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/ITransport.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// This will be treated as a bit flag in the future, so we keep it using power-of-two values.
/** Specifies a specific HTTP transport type. */
var HttpTransportType;
(function (HttpTransportType) {
    /** Specifies no transport preference. */
    HttpTransportType[HttpTransportType["None"] = 0] = "None";
    /** Specifies the WebSockets transport. */
    HttpTransportType[HttpTransportType["WebSockets"] = 1] = "WebSockets";
    /** Specifies the Server-Sent Events transport. */
    HttpTransportType[HttpTransportType["ServerSentEvents"] = 2] = "ServerSentEvents";
    /** Specifies the Long Polling transport. */
    HttpTransportType[HttpTransportType["LongPolling"] = 4] = "LongPolling";
})(HttpTransportType || (HttpTransportType = {}));
/** Specifies the transfer format for a connection. */
var TransferFormat;
(function (TransferFormat) {
    /** Specifies that only text data will be transmitted over the connection. */
    TransferFormat[TransferFormat["Text"] = 1] = "Text";
    /** Specifies that binary data will be transmitted over the connection. */
    TransferFormat[TransferFormat["Binary"] = 2] = "Binary";
})(TransferFormat || (TransferFormat = {}));
//# sourceMappingURL=ITransport.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/AbortController.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Rough polyfill of https://developer.mozilla.org/en-US/docs/Web/API/AbortController
// We don't actually ever use the API being polyfilled, we always use the polyfill because
// it's a very new API right now.
// Not exported from index.
/** @private */
var AbortController = /** @class */ (function () {
    function AbortController() {
        this.isAborted = false;
        this.onabort = null;
    }
    AbortController.prototype.abort = function () {
        if (!this.isAborted) {
            this.isAborted = true;
            if (this.onabort) {
                this.onabort();
            }
        }
    };
    Object.defineProperty(AbortController.prototype, "signal", {
        get: function () {
            return this;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(AbortController.prototype, "aborted", {
        get: function () {
            return this.isAborted;
        },
        enumerable: true,
        configurable: true
    });
    return AbortController;
}());

//# sourceMappingURL=AbortController.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var LongPollingTransport_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var LongPollingTransport_generator = (undefined && undefined.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};





// Not exported from 'index', this type is internal.
/** @private */
var LongPollingTransport_LongPollingTransport = /** @class */ (function () {
    function LongPollingTransport(httpClient, accessTokenFactory, logger, logMessageContent) {
        this.httpClient = httpClient;
        this.accessTokenFactory = accessTokenFactory;
        this.logger = logger;
        this.pollAbort = new AbortController();
        this.logMessageContent = logMessageContent;
        this.running = false;
        this.onreceive = null;
        this.onclose = null;
    }
    Object.defineProperty(LongPollingTransport.prototype, "pollAborted", {
        // This is an internal type, not exported from 'index' so this is really just internal.
        get: function () {
            return this.pollAbort.aborted;
        },
        enumerable: true,
        configurable: true
    });
    LongPollingTransport.prototype.connect = function (url, transferFormat) {
        return LongPollingTransport_awaiter(this, void 0, void 0, function () {
            var pollOptions, token, pollUrl, response;
            return LongPollingTransport_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        Utils["a" /* Arg */].isRequired(url, "url");
                        Utils["a" /* Arg */].isRequired(transferFormat, "transferFormat");
                        Utils["a" /* Arg */].isIn(transferFormat, TransferFormat, "transferFormat");
                        this.url = url;
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) Connecting.");
                        // Allow binary format on Node and Browsers that support binary content (indicated by the presence of responseType property)
                        if (transferFormat === TransferFormat.Binary &&
                            (typeof XMLHttpRequest !== "undefined" && typeof new XMLHttpRequest().responseType !== "string")) {
                            throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported.");
                        }
                        pollOptions = {
                            abortSignal: this.pollAbort.signal,
                            headers: {},
                            timeout: 100000,
                        };
                        if (transferFormat === TransferFormat.Binary) {
                            pollOptions.responseType = "arraybuffer";
                        }
                        return [4 /*yield*/, this.getAccessToken()];
                    case 1:
                        token = _a.sent();
                        this.updateHeaderToken(pollOptions, token);
                        pollUrl = url + "&_=" + Date.now();
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) polling: " + pollUrl + ".");
                        return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)];
                    case 2:
                        response = _a.sent();
                        if (response.statusCode !== 200) {
                            this.logger.log(ILogger["a" /* LogLevel */].Error, "(LongPolling transport) Unexpected response code: " + response.statusCode + ".");
                            // Mark running as false so that the poll immediately ends and runs the close logic
                            this.closeError = new Errors["b" /* HttpError */](response.statusText || "", response.statusCode);
                            this.running = false;
                        }
                        else {
                            this.running = true;
                        }
                        this.receiving = this.poll(this.url, pollOptions);
                        return [2 /*return*/];
                }
            });
        });
    };
    LongPollingTransport.prototype.getAccessToken = function () {
        return LongPollingTransport_awaiter(this, void 0, void 0, function () {
            return LongPollingTransport_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!this.accessTokenFactory) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.accessTokenFactory()];
                    case 1: return [2 /*return*/, _a.sent()];
                    case 2: return [2 /*return*/, null];
                }
            });
        });
    };
    LongPollingTransport.prototype.updateHeaderToken = function (request, token) {
        if (!request.headers) {
            request.headers = {};
        }
        if (token) {
            // tslint:disable-next-line:no-string-literal
            request.headers["Authorization"] = "Bearer " + token;
            return;
        }
        // tslint:disable-next-line:no-string-literal
        if (request.headers["Authorization"]) {
            // tslint:disable-next-line:no-string-literal
            delete request.headers["Authorization"];
        }
    };
    LongPollingTransport.prototype.poll = function (url, pollOptions) {
        return LongPollingTransport_awaiter(this, void 0, void 0, function () {
            var token, pollUrl, response, e_1;
            return LongPollingTransport_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, , 8, 9]);
                        _a.label = 1;
                    case 1:
                        if (!this.running) return [3 /*break*/, 7];
                        return [4 /*yield*/, this.getAccessToken()];
                    case 2:
                        token = _a.sent();
                        this.updateHeaderToken(pollOptions, token);
                        _a.label = 3;
                    case 3:
                        _a.trys.push([3, 5, , 6]);
                        pollUrl = url + "&_=" + Date.now();
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) polling: " + pollUrl + ".");
                        return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)];
                    case 4:
                        response = _a.sent();
                        if (response.statusCode === 204) {
                            this.logger.log(ILogger["a" /* LogLevel */].Information, "(LongPolling transport) Poll terminated by server.");
                            this.running = false;
                        }
                        else if (response.statusCode !== 200) {
                            this.logger.log(ILogger["a" /* LogLevel */].Error, "(LongPolling transport) Unexpected response code: " + response.statusCode + ".");
                            // Unexpected status code
                            this.closeError = new Errors["b" /* HttpError */](response.statusText || "", response.statusCode);
                            this.running = false;
                        }
                        else {
                            // Process the response
                            if (response.content) {
                                this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) data received. " + Object(Utils["f" /* getDataDetail */])(response.content, this.logMessageContent) + ".");
                                if (this.onreceive) {
                                    this.onreceive(response.content);
                                }
                            }
                            else {
                                // This is another way timeout manifest.
                                this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) Poll timed out, reissuing.");
                            }
                        }
                        return [3 /*break*/, 6];
                    case 5:
                        e_1 = _a.sent();
                        if (!this.running) {
                            // Log but disregard errors that occur after stopping
                            this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) Poll errored after shutdown: " + e_1.message);
                        }
                        else {
                            if (e_1 instanceof Errors["c" /* TimeoutError */]) {
                                // Ignore timeouts and reissue the poll.
                                this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) Poll timed out, reissuing.");
                            }
                            else {
                                // Close the connection with the error as the result.
                                this.closeError = e_1;
                                this.running = false;
                            }
                        }
                        return [3 /*break*/, 6];
                    case 6: return [3 /*break*/, 1];
                    case 7: return [3 /*break*/, 9];
                    case 8:
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) Polling complete.");
                        // We will reach here with pollAborted==false when the server returned a response causing the transport to stop.
                        // If pollAborted==true then client initiated the stop and the stop method will raise the close event after DELETE is sent.
                        if (!this.pollAborted) {
                            this.raiseOnClose();
                        }
                        return [7 /*endfinally*/];
                    case 9: return [2 /*return*/];
                }
            });
        });
    };
    LongPollingTransport.prototype.send = function (data) {
        return LongPollingTransport_awaiter(this, void 0, void 0, function () {
            return LongPollingTransport_generator(this, function (_a) {
                if (!this.running) {
                    return [2 /*return*/, Promise.reject(new Error("Cannot send until the transport is connected"))];
                }
                return [2 /*return*/, Object(Utils["h" /* sendMessage */])(this.logger, "LongPolling", this.httpClient, this.url, this.accessTokenFactory, data, this.logMessageContent)];
            });
        });
    };
    LongPollingTransport.prototype.stop = function () {
        return LongPollingTransport_awaiter(this, void 0, void 0, function () {
            var deleteOptions, token;
            return LongPollingTransport_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) Stopping polling.");
                        // Tell receiving loop to stop, abort any current request, and then wait for it to finish
                        this.running = false;
                        this.pollAbort.abort();
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, , 5, 6]);
                        return [4 /*yield*/, this.receiving];
                    case 2:
                        _a.sent();
                        // Send DELETE to clean up long polling on the server
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) sending DELETE request to " + this.url + ".");
                        deleteOptions = {
                            headers: {},
                        };
                        return [4 /*yield*/, this.getAccessToken()];
                    case 3:
                        token = _a.sent();
                        this.updateHeaderToken(deleteOptions, token);
                        return [4 /*yield*/, this.httpClient.delete(this.url, deleteOptions)];
                    case 4:
                        _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) DELETE request sent.");
                        return [3 /*break*/, 6];
                    case 5:
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(LongPolling transport) Stop finished.");
                        // Raise close event here instead of in polling
                        // It needs to happen after the DELETE request is sent
                        this.raiseOnClose();
                        return [7 /*endfinally*/];
                    case 6: return [2 /*return*/];
                }
            });
        });
    };
    LongPollingTransport.prototype.raiseOnClose = function () {
        if (this.onclose) {
            var logMessage = "(LongPolling transport) Firing onclose event.";
            if (this.closeError) {
                logMessage += " Error: " + this.closeError;
            }
            this.logger.log(ILogger["a" /* LogLevel */].Trace, logMessage);
            this.onclose(this.closeError);
        }
    };
    return LongPollingTransport;
}());

//# sourceMappingURL=LongPollingTransport.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var ServerSentEventsTransport_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var ServerSentEventsTransport_generator = (undefined && undefined.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};



/** @private */
var ServerSentEventsTransport_ServerSentEventsTransport = /** @class */ (function () {
    function ServerSentEventsTransport(httpClient, accessTokenFactory, logger, logMessageContent, eventSourceConstructor) {
        this.httpClient = httpClient;
        this.accessTokenFactory = accessTokenFactory;
        this.logger = logger;
        this.logMessageContent = logMessageContent;
        this.eventSourceConstructor = eventSourceConstructor;
        this.onreceive = null;
        this.onclose = null;
    }
    ServerSentEventsTransport.prototype.connect = function (url, transferFormat) {
        return ServerSentEventsTransport_awaiter(this, void 0, void 0, function () {
            var token;
            var _this = this;
            return ServerSentEventsTransport_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        Utils["a" /* Arg */].isRequired(url, "url");
                        Utils["a" /* Arg */].isRequired(transferFormat, "transferFormat");
                        Utils["a" /* Arg */].isIn(transferFormat, TransferFormat, "transferFormat");
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(SSE transport) Connecting.");
                        // set url before accessTokenFactory because this.url is only for send and we set the auth header instead of the query string for send
                        this.url = url;
                        if (!this.accessTokenFactory) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.accessTokenFactory()];
                    case 1:
                        token = _a.sent();
                        if (token) {
                            url += (url.indexOf("?") < 0 ? "?" : "&") + ("access_token=" + encodeURIComponent(token));
                        }
                        _a.label = 2;
                    case 2: return [2 /*return*/, new Promise(function (resolve, reject) {
                            var opened = false;
                            if (transferFormat !== TransferFormat.Text) {
                                reject(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"));
                                return;
                            }
                            var eventSource;
                            if (Utils["c" /* Platform */].isBrowser || Utils["c" /* Platform */].isWebWorker) {
                                eventSource = new _this.eventSourceConstructor(url, { withCredentials: true });
                            }
                            else {
                                // Non-browser passes cookies via the dictionary
                                var cookies = _this.httpClient.getCookieString(url);
                                eventSource = new _this.eventSourceConstructor(url, { withCredentials: true, headers: { Cookie: cookies } });
                            }
                            try {
                                eventSource.onmessage = function (e) {
                                    if (_this.onreceive) {
                                        try {
                                            _this.logger.log(ILogger["a" /* LogLevel */].Trace, "(SSE transport) data received. " + Object(Utils["f" /* getDataDetail */])(e.data, _this.logMessageContent) + ".");
                                            _this.onreceive(e.data);
                                        }
                                        catch (error) {
                                            _this.close(error);
                                            return;
                                        }
                                    }
                                };
                                eventSource.onerror = function (e) {
                                    var error = new Error(e.data || "Error occurred");
                                    if (opened) {
                                        _this.close(error);
                                    }
                                    else {
                                        reject(error);
                                    }
                                };
                                eventSource.onopen = function () {
                                    _this.logger.log(ILogger["a" /* LogLevel */].Information, "SSE connected to " + _this.url);
                                    _this.eventSource = eventSource;
                                    opened = true;
                                    resolve();
                                };
                            }
                            catch (e) {
                                reject(e);
                                return;
                            }
                        })];
                }
            });
        });
    };
    ServerSentEventsTransport.prototype.send = function (data) {
        return ServerSentEventsTransport_awaiter(this, void 0, void 0, function () {
            return ServerSentEventsTransport_generator(this, function (_a) {
                if (!this.eventSource) {
                    return [2 /*return*/, Promise.reject(new Error("Cannot send until the transport is connected"))];
                }
                return [2 /*return*/, Object(Utils["h" /* sendMessage */])(this.logger, "SSE", this.httpClient, this.url, this.accessTokenFactory, data, this.logMessageContent)];
            });
        });
    };
    ServerSentEventsTransport.prototype.stop = function () {
        this.close();
        return Promise.resolve();
    };
    ServerSentEventsTransport.prototype.close = function (e) {
        if (this.eventSource) {
            this.eventSource.close();
            this.eventSource = undefined;
            if (this.onclose) {
                this.onclose(e);
            }
        }
    };
    return ServerSentEventsTransport;
}());

//# sourceMappingURL=ServerSentEventsTransport.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var WebSocketTransport_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var WebSocketTransport_generator = (undefined && undefined.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};



/** @private */
var WebSocketTransport_WebSocketTransport = /** @class */ (function () {
    function WebSocketTransport(httpClient, accessTokenFactory, logger, logMessageContent, webSocketConstructor) {
        this.logger = logger;
        this.accessTokenFactory = accessTokenFactory;
        this.logMessageContent = logMessageContent;
        this.webSocketConstructor = webSocketConstructor;
        this.httpClient = httpClient;
        this.onreceive = null;
        this.onclose = null;
    }
    WebSocketTransport.prototype.connect = function (url, transferFormat) {
        return WebSocketTransport_awaiter(this, void 0, void 0, function () {
            var token;
            var _this = this;
            return WebSocketTransport_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        Utils["a" /* Arg */].isRequired(url, "url");
                        Utils["a" /* Arg */].isRequired(transferFormat, "transferFormat");
                        Utils["a" /* Arg */].isIn(transferFormat, TransferFormat, "transferFormat");
                        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(WebSockets transport) Connecting.");
                        if (!this.accessTokenFactory) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.accessTokenFactory()];
                    case 1:
                        token = _a.sent();
                        if (token) {
                            url += (url.indexOf("?") < 0 ? "?" : "&") + ("access_token=" + encodeURIComponent(token));
                        }
                        _a.label = 2;
                    case 2: return [2 /*return*/, new Promise(function (resolve, reject) {
                            url = url.replace(/^http/, "ws");
                            var webSocket;
                            var cookies = _this.httpClient.getCookieString(url);
                            if (Utils["c" /* Platform */].isNode && cookies) {
                                // Only pass cookies when in non-browser environments
                                webSocket = new _this.webSocketConstructor(url, undefined, {
                                    headers: {
                                        Cookie: "" + cookies,
                                    },
                                });
                            }
                            if (!webSocket) {
                                // Chrome is not happy with passing 'undefined' as protocol
                                webSocket = new _this.webSocketConstructor(url);
                            }
                            if (transferFormat === TransferFormat.Binary) {
                                webSocket.binaryType = "arraybuffer";
                            }
                            // tslint:disable-next-line:variable-name
                            webSocket.onopen = function (_event) {
                                _this.logger.log(ILogger["a" /* LogLevel */].Information, "WebSocket connected to " + url + ".");
                                _this.webSocket = webSocket;
                                resolve();
                            };
                            webSocket.onerror = function (event) {
                                var error = null;
                                // ErrorEvent is a browser only type we need to check if the type exists before using it
                                if (typeof ErrorEvent !== "undefined" && event instanceof ErrorEvent) {
                                    error = event.error;
                                }
                                else {
                                    error = new Error("There was an error with the transport.");
                                }
                                reject(error);
                            };
                            webSocket.onmessage = function (message) {
                                _this.logger.log(ILogger["a" /* LogLevel */].Trace, "(WebSockets transport) data received. " + Object(Utils["f" /* getDataDetail */])(message.data, _this.logMessageContent) + ".");
                                if (_this.onreceive) {
                                    _this.onreceive(message.data);
                                }
                            };
                            webSocket.onclose = function (event) { return _this.close(event); };
                        })];
                }
            });
        });
    };
    WebSocketTransport.prototype.send = function (data) {
        if (this.webSocket && this.webSocket.readyState === this.webSocketConstructor.OPEN) {
            this.logger.log(ILogger["a" /* LogLevel */].Trace, "(WebSockets transport) sending data. " + Object(Utils["f" /* getDataDetail */])(data, this.logMessageContent) + ".");
            this.webSocket.send(data);
            return Promise.resolve();
        }
        return Promise.reject("WebSocket is not in the OPEN state");
    };
    WebSocketTransport.prototype.stop = function () {
        if (this.webSocket) {
            // Clear websocket handlers because we are considering the socket closed now
            this.webSocket.onclose = function () { };
            this.webSocket.onmessage = function () { };
            this.webSocket.onerror = function () { };
            this.webSocket.close();
            this.webSocket = undefined;
            // Manually invoke onclose callback inline so we know the HttpConnection was closed properly before returning
            // This also solves an issue where websocket.onclose could take 18+ seconds to trigger during network disconnects
            this.close(undefined);
        }
        return Promise.resolve();
    };
    WebSocketTransport.prototype.close = function (event) {
        // webSocket will be null if the transport did not start successfully
        this.logger.log(ILogger["a" /* LogLevel */].Trace, "(WebSockets transport) socket closed.");
        if (this.onclose) {
            if (event && (event.wasClean === false || event.code !== 1000)) {
                this.onclose(new Error("WebSocket closed with status code: " + event.code + " (" + event.reason + ")."));
            }
            else {
                this.onclose();
            }
        }
    };
    return WebSocketTransport;
}());

//# sourceMappingURL=WebSocketTransport.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/HttpConnection.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var HttpConnection_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var HttpConnection_generator = (undefined && undefined.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};







var MAX_REDIRECTS = 100;
var WebSocketModule = null;
var EventSourceModule = null;
if (Utils["c" /* Platform */].isNode && "function" !== "undefined") {
    // In order to ignore the dynamic require in webpack builds we need to do this magic
    // @ts-ignore: TS doesn't know about these names
    var requireFunc =  true ? require : undefined;
    WebSocketModule = requireFunc("ws");
    EventSourceModule = requireFunc("eventsource");
}
/** @private */
var HttpConnection_HttpConnection = /** @class */ (function () {
    function HttpConnection(url, options) {
        if (options === void 0) { options = {}; }
        this.features = {};
        Utils["a" /* Arg */].isRequired(url, "url");
        this.logger = Object(Utils["e" /* createLogger */])(options.logger);
        this.baseUrl = this.resolveUrl(url);
        options = options || {};
        options.logMessageContent = options.logMessageContent || false;
        if (!Utils["c" /* Platform */].isNode && typeof WebSocket !== "undefined" && !options.WebSocket) {
            options.WebSocket = WebSocket;
        }
        else if (Utils["c" /* Platform */].isNode && !options.WebSocket) {
            if (WebSocketModule) {
                options.WebSocket = WebSocketModule;
            }
        }
        if (!Utils["c" /* Platform */].isNode && typeof EventSource !== "undefined" && !options.EventSource) {
            options.EventSource = EventSource;
        }
        else if (Utils["c" /* Platform */].isNode && !options.EventSource) {
            if (typeof EventSourceModule !== "undefined") {
                options.EventSource = EventSourceModule;
            }
        }
        this.httpClient = options.httpClient || new DefaultHttpClient_DefaultHttpClient(this.logger);
        this.connectionState = "Disconnected" /* Disconnected */;
        this.connectionStarted = false;
        this.options = options;
        this.onreceive = null;
        this.onclose = null;
    }
    HttpConnection.prototype.start = function (transferFormat) {
        return HttpConnection_awaiter(this, void 0, void 0, function () {
            var message, message;
            return HttpConnection_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        transferFormat = transferFormat || TransferFormat.Binary;
                        Utils["a" /* Arg */].isIn(transferFormat, TransferFormat, "transferFormat");
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Starting connection with transfer format '" + TransferFormat[transferFormat] + "'.");
                        if (this.connectionState !== "Disconnected" /* Disconnected */) {
                            return [2 /*return*/, Promise.reject(new Error("Cannot start an HttpConnection that is not in the 'Disconnected' state."))];
                        }
                        this.connectionState = "Connecting " /* Connecting */;
                        this.startInternalPromise = this.startInternal(transferFormat);
                        return [4 /*yield*/, this.startInternalPromise];
                    case 1:
                        _a.sent();
                        if (!(this.connectionState === "Disconnecting" /* Disconnecting */)) return [3 /*break*/, 3];
                        message = "Failed to start the HttpConnection before stop() was called.";
                        this.logger.log(ILogger["a" /* LogLevel */].Error, message);
                        // We cannot await stopPromise inside startInternal since stopInternal awaits the startInternalPromise.
                        return [4 /*yield*/, this.stopPromise];
                    case 2:
                        // We cannot await stopPromise inside startInternal since stopInternal awaits the startInternalPromise.
                        _a.sent();
                        return [2 /*return*/, Promise.reject(new Error(message))];
                    case 3:
                        if (this.connectionState !== "Connected" /* Connected */) {
                            message = "HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!";
                            this.logger.log(ILogger["a" /* LogLevel */].Error, message);
                            return [2 /*return*/, Promise.reject(new Error(message))];
                        }
                        _a.label = 4;
                    case 4:
                        this.connectionStarted = true;
                        return [2 /*return*/];
                }
            });
        });
    };
    HttpConnection.prototype.send = function (data) {
        if (this.connectionState !== "Connected" /* Connected */) {
            return Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State."));
        }
        if (!this.sendQueue) {
            this.sendQueue = new TransportSendQueue(this.transport);
        }
        // Transport will not be null if state is connected
        return this.sendQueue.send(data);
    };
    HttpConnection.prototype.stop = function (error) {
        return HttpConnection_awaiter(this, void 0, void 0, function () {
            var _this = this;
            return HttpConnection_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (this.connectionState === "Disconnected" /* Disconnected */) {
                            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Call to HttpConnection.stop(" + error + ") ignored because the connection is already in the disconnected state.");
                            return [2 /*return*/, Promise.resolve()];
                        }
                        if (this.connectionState === "Disconnecting" /* Disconnecting */) {
                            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Call to HttpConnection.stop(" + error + ") ignored because the connection is already in the disconnecting state.");
                            return [2 /*return*/, this.stopPromise];
                        }
                        this.connectionState = "Disconnecting" /* Disconnecting */;
                        this.stopPromise = new Promise(function (resolve) {
                            // Don't complete stop() until stopConnection() completes.
                            _this.stopPromiseResolver = resolve;
                        });
                        // stopInternal should never throw so just observe it.
                        return [4 /*yield*/, this.stopInternal(error)];
                    case 1:
                        // stopInternal should never throw so just observe it.
                        _a.sent();
                        return [4 /*yield*/, this.stopPromise];
                    case 2:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    HttpConnection.prototype.stopInternal = function (error) {
        return HttpConnection_awaiter(this, void 0, void 0, function () {
            var e_1, e_2, e_3;
            return HttpConnection_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        // Set error as soon as possible otherwise there is a race between
                        // the transport closing and providing an error and the error from a close message
                        // We would prefer the close message error.
                        this.stopError = error;
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 3, , 4]);
                        return [4 /*yield*/, this.startInternalPromise];
                    case 2:
                        _a.sent();
                        return [3 /*break*/, 4];
                    case 3:
                        e_1 = _a.sent();
                        return [3 /*break*/, 4];
                    case 4:
                        if (!this.sendQueue) return [3 /*break*/, 9];
                        _a.label = 5;
                    case 5:
                        _a.trys.push([5, 7, , 8]);
                        return [4 /*yield*/, this.sendQueue.stop()];
                    case 6:
                        _a.sent();
                        return [3 /*break*/, 8];
                    case 7:
                        e_2 = _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Error, "TransportSendQueue.stop() threw error '" + e_2 + "'.");
                        return [3 /*break*/, 8];
                    case 8:
                        this.sendQueue = undefined;
                        _a.label = 9;
                    case 9:
                        if (!this.transport) return [3 /*break*/, 14];
                        _a.label = 10;
                    case 10:
                        _a.trys.push([10, 12, , 13]);
                        return [4 /*yield*/, this.transport.stop()];
                    case 11:
                        _a.sent();
                        return [3 /*break*/, 13];
                    case 12:
                        e_3 = _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Error, "HttpConnection.transport.stop() threw error '" + e_3 + "'.");
                        this.stopConnection();
                        return [3 /*break*/, 13];
                    case 13:
                        this.transport = undefined;
                        return [3 /*break*/, 15];
                    case 14:
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "HttpConnection.transport is undefined in HttpConnection.stop() because start() failed.");
                        this.stopConnection();
                        _a.label = 15;
                    case 15: return [2 /*return*/];
                }
            });
        });
    };
    HttpConnection.prototype.startInternal = function (transferFormat) {
        return HttpConnection_awaiter(this, void 0, void 0, function () {
            var url, negotiateResponse, redirects, _loop_1, this_1, e_4;
            return HttpConnection_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        url = this.baseUrl;
                        this.accessTokenFactory = this.options.accessTokenFactory;
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 12, , 13]);
                        if (!this.options.skipNegotiation) return [3 /*break*/, 5];
                        if (!(this.options.transport === HttpTransportType.WebSockets)) return [3 /*break*/, 3];
                        // No need to add a connection ID in this case
                        this.transport = this.constructTransport(HttpTransportType.WebSockets);
                        // We should just call connect directly in this case.
                        // No fallback or negotiate in this case.
                        return [4 /*yield*/, this.startTransport(url, transferFormat)];
                    case 2:
                        // We should just call connect directly in this case.
                        // No fallback or negotiate in this case.
                        _a.sent();
                        return [3 /*break*/, 4];
                    case 3: throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");
                    case 4: return [3 /*break*/, 11];
                    case 5:
                        negotiateResponse = null;
                        redirects = 0;
                        _loop_1 = function () {
                            var accessToken_1;
                            return HttpConnection_generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4 /*yield*/, this_1.getNegotiationResponse(url)];
                                    case 1:
                                        negotiateResponse = _a.sent();
                                        // the user tries to stop the connection when it is being started
                                        if (this_1.connectionState === "Disconnecting" /* Disconnecting */ || this_1.connectionState === "Disconnected" /* Disconnected */) {
                                            throw new Error("The connection was stopped during negotiation.");
                                        }
                                        if (negotiateResponse.error) {
                                            throw new Error(negotiateResponse.error);
                                        }
                                        if (negotiateResponse.ProtocolVersion) {
                                            throw new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");
                                        }
                                        if (negotiateResponse.url) {
                                            url = negotiateResponse.url;
                                        }
                                        if (negotiateResponse.accessToken) {
                                            accessToken_1 = negotiateResponse.accessToken;
                                            this_1.accessTokenFactory = function () { return accessToken_1; };
                                        }
                                        redirects++;
                                        return [2 /*return*/];
                                }
                            });
                        };
                        this_1 = this;
                        _a.label = 6;
                    case 6: return [5 /*yield**/, _loop_1()];
                    case 7:
                        _a.sent();
                        _a.label = 8;
                    case 8:
                        if (negotiateResponse.url && redirects < MAX_REDIRECTS) return [3 /*break*/, 6];
                        _a.label = 9;
                    case 9:
                        if (redirects === MAX_REDIRECTS && negotiateResponse.url) {
                            throw new Error("Negotiate redirection limit exceeded.");
                        }
                        this.connectionId = negotiateResponse.connectionId;
                        return [4 /*yield*/, this.createTransport(url, this.options.transport, negotiateResponse, transferFormat)];
                    case 10:
                        _a.sent();
                        _a.label = 11;
                    case 11:
                        if (this.transport instanceof LongPollingTransport_LongPollingTransport) {
                            this.features.inherentKeepAlive = true;
                        }
                        if (this.connectionState === "Connecting " /* Connecting */) {
                            // Ensure the connection transitions to the connected state prior to completing this.startInternalPromise.
                            // start() will handle the case when stop was called and startInternal exits still in the disconnecting state.
                            this.logger.log(ILogger["a" /* LogLevel */].Debug, "The HttpConnection connected successfully.");
                            this.connectionState = "Connected" /* Connected */;
                        }
                        return [3 /*break*/, 13];
                    case 12:
                        e_4 = _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Error, "Failed to start the connection: " + e_4);
                        this.connectionState = "Disconnected" /* Disconnected */;
                        this.transport = undefined;
                        return [2 /*return*/, Promise.reject(e_4)];
                    case 13: return [2 /*return*/];
                }
            });
        });
    };
    HttpConnection.prototype.getNegotiationResponse = function (url) {
        return HttpConnection_awaiter(this, void 0, void 0, function () {
            var _a, headers, token, negotiateUrl, response, e_5;
            return HttpConnection_generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!this.accessTokenFactory) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.accessTokenFactory()];
                    case 1:
                        token = _b.sent();
                        if (token) {
                            headers = (_a = {},
                                _a["Authorization"] = "Bearer " + token,
                                _a);
                        }
                        _b.label = 2;
                    case 2:
                        negotiateUrl = this.resolveNegotiateUrl(url);
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Sending negotiation request: " + negotiateUrl + ".");
                        _b.label = 3;
                    case 3:
                        _b.trys.push([3, 5, , 6]);
                        return [4 /*yield*/, this.httpClient.post(negotiateUrl, {
                                content: "",
                                headers: headers,
                            })];
                    case 4:
                        response = _b.sent();
                        if (response.statusCode !== 200) {
                            return [2 /*return*/, Promise.reject(new Error("Unexpected status code returned from negotiate " + response.statusCode))];
                        }
                        return [2 /*return*/, JSON.parse(response.content)];
                    case 5:
                        e_5 = _b.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Error, "Failed to complete negotiation with the server: " + e_5);
                        return [2 /*return*/, Promise.reject(e_5)];
                    case 6: return [2 /*return*/];
                }
            });
        });
    };
    HttpConnection.prototype.createConnectUrl = function (url, connectionId) {
        if (!connectionId) {
            return url;
        }
        return url + (url.indexOf("?") === -1 ? "?" : "&") + ("id=" + connectionId);
    };
    HttpConnection.prototype.createTransport = function (url, requestedTransport, negotiateResponse, requestedTransferFormat) {
        return HttpConnection_awaiter(this, void 0, void 0, function () {
            var connectUrl, transportExceptions, transports, _i, transports_1, endpoint, transportOrError, ex_1, ex_2, message;
            return HttpConnection_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        connectUrl = this.createConnectUrl(url, negotiateResponse.connectionId);
                        if (!this.isITransport(requestedTransport)) return [3 /*break*/, 2];
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Connection was provided an instance of ITransport, using that directly.");
                        this.transport = requestedTransport;
                        return [4 /*yield*/, this.startTransport(connectUrl, requestedTransferFormat)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                    case 2:
                        transportExceptions = [];
                        transports = negotiateResponse.availableTransports || [];
                        _i = 0, transports_1 = transports;
                        _a.label = 3;
                    case 3:
                        if (!(_i < transports_1.length)) return [3 /*break*/, 13];
                        endpoint = transports_1[_i];
                        transportOrError = this.resolveTransportOrError(endpoint, requestedTransport, requestedTransferFormat);
                        if (!(transportOrError instanceof Error)) return [3 /*break*/, 4];
                        // Store the error and continue, we don't want to cause a re-negotiate in these cases
                        transportExceptions.push(endpoint.transport + " failed: " + transportOrError);
                        return [3 /*break*/, 12];
                    case 4:
                        if (!this.isITransport(transportOrError)) return [3 /*break*/, 12];
                        this.transport = transportOrError;
                        if (!!negotiateResponse.connectionId) return [3 /*break*/, 9];
                        _a.label = 5;
                    case 5:
                        _a.trys.push([5, 7, , 8]);
                        return [4 /*yield*/, this.getNegotiationResponse(url)];
                    case 6:
                        negotiateResponse = _a.sent();
                        return [3 /*break*/, 8];
                    case 7:
                        ex_1 = _a.sent();
                        return [2 /*return*/, Promise.reject(ex_1)];
                    case 8:
                        connectUrl = this.createConnectUrl(url, negotiateResponse.connectionId);
                        _a.label = 9;
                    case 9:
                        _a.trys.push([9, 11, , 12]);
                        return [4 /*yield*/, this.startTransport(connectUrl, requestedTransferFormat)];
                    case 10:
                        _a.sent();
                        return [2 /*return*/];
                    case 11:
                        ex_2 = _a.sent();
                        this.logger.log(ILogger["a" /* LogLevel */].Error, "Failed to start the transport '" + endpoint.transport + "': " + ex_2);
                        negotiateResponse.connectionId = undefined;
                        transportExceptions.push(endpoint.transport + " failed: " + ex_2);
                        if (this.connectionState !== "Connecting " /* Connecting */) {
                            message = "Failed to select transport before stop() was called.";
                            this.logger.log(ILogger["a" /* LogLevel */].Debug, message);
                            return [2 /*return*/, Promise.reject(new Error(message))];
                        }
                        return [3 /*break*/, 12];
                    case 12:
                        _i++;
                        return [3 /*break*/, 3];
                    case 13:
                        if (transportExceptions.length > 0) {
                            return [2 /*return*/, Promise.reject(new Error("Unable to connect to the server with any of the available transports. " + transportExceptions.join(" ")))];
                        }
                        return [2 /*return*/, Promise.reject(new Error("None of the transports supported by the client are supported by the server."))];
                }
            });
        });
    };
    HttpConnection.prototype.constructTransport = function (transport) {
        switch (transport) {
            case HttpTransportType.WebSockets:
                if (!this.options.WebSocket) {
                    throw new Error("'WebSocket' is not supported in your environment.");
                }
                return new WebSocketTransport_WebSocketTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket);
            case HttpTransportType.ServerSentEvents:
                if (!this.options.EventSource) {
                    throw new Error("'EventSource' is not supported in your environment.");
                }
                return new ServerSentEventsTransport_ServerSentEventsTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.EventSource);
            case HttpTransportType.LongPolling:
                return new LongPollingTransport_LongPollingTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false);
            default:
                throw new Error("Unknown transport: " + transport + ".");
        }
    };
    HttpConnection.prototype.startTransport = function (url, transferFormat) {
        var _this = this;
        this.transport.onreceive = this.onreceive;
        this.transport.onclose = function (e) { return _this.stopConnection(e); };
        return this.transport.connect(url, transferFormat);
    };
    HttpConnection.prototype.resolveTransportOrError = function (endpoint, requestedTransport, requestedTransferFormat) {
        var transport = HttpTransportType[endpoint.transport];
        if (transport === null || transport === undefined) {
            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Skipping transport '" + endpoint.transport + "' because it is not supported by this client.");
            return new Error("Skipping transport '" + endpoint.transport + "' because it is not supported by this client.");
        }
        else {
            if (transportMatches(requestedTransport, transport)) {
                var transferFormats = endpoint.transferFormats.map(function (s) { return TransferFormat[s]; });
                if (transferFormats.indexOf(requestedTransferFormat) >= 0) {
                    if ((transport === HttpTransportType.WebSockets && !this.options.WebSocket) ||
                        (transport === HttpTransportType.ServerSentEvents && !this.options.EventSource)) {
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Skipping transport '" + HttpTransportType[transport] + "' because it is not supported in your environment.'");
                        return new Error("'" + HttpTransportType[transport] + "' is not supported in your environment.");
                    }
                    else {
                        this.logger.log(ILogger["a" /* LogLevel */].Debug, "Selecting transport '" + HttpTransportType[transport] + "'.");
                        try {
                            return this.constructTransport(transport);
                        }
                        catch (ex) {
                            return ex;
                        }
                    }
                }
                else {
                    this.logger.log(ILogger["a" /* LogLevel */].Debug, "Skipping transport '" + HttpTransportType[transport] + "' because it does not support the requested transfer format '" + TransferFormat[requestedTransferFormat] + "'.");
                    return new Error("'" + HttpTransportType[transport] + "' does not support " + TransferFormat[requestedTransferFormat] + ".");
                }
            }
            else {
                this.logger.log(ILogger["a" /* LogLevel */].Debug, "Skipping transport '" + HttpTransportType[transport] + "' because it was disabled by the client.");
                return new Error("'" + HttpTransportType[transport] + "' is disabled by the client.");
            }
        }
    };
    HttpConnection.prototype.isITransport = function (transport) {
        return transport && typeof (transport) === "object" && "connect" in transport;
    };
    HttpConnection.prototype.stopConnection = function (error) {
        this.logger.log(ILogger["a" /* LogLevel */].Debug, "HttpConnection.stopConnection(" + error + ") called while in state " + this.connectionState + ".");
        this.transport = undefined;
        // If we have a stopError, it takes precedence over the error from the transport
        error = this.stopError || error;
        this.stopError = undefined;
        if (this.connectionState === "Disconnected" /* Disconnected */) {
            this.logger.log(ILogger["a" /* LogLevel */].Debug, "Call to HttpConnection.stopConnection(" + error + ") was ignored because the connection is already in the disconnected state.");
            return;
        }
        if (this.connectionState === "Connecting " /* Connecting */) {
            this.logger.log(ILogger["a" /* LogLevel */].Warning, "Call to HttpConnection.stopConnection(" + error + ") was ignored because the connection hasn't yet left the in the connecting state.");
            return;
        }
        if (this.connectionState === "Disconnecting" /* Disconnecting */) {
            // A call to stop() induced this call to stopConnection and needs to be completed.
            // Any stop() awaiters will be scheduled to continue after the onclose callback fires.
            this.stopPromiseResolver();
        }
        if (error) {
            this.logger.log(ILogger["a" /* LogLevel */].Error, "Connection disconnected with error '" + error + "'.");
        }
        else {
            this.logger.log(ILogger["a" /* LogLevel */].Information, "Connection disconnected.");
        }
        this.connectionId = undefined;
        this.connectionState = "Disconnected" /* Disconnected */;
        if (this.onclose && this.connectionStarted) {
            this.connectionStarted = false;
            try {
                this.onclose(error);
            }
            catch (e) {
                this.logger.log(ILogger["a" /* LogLevel */].Error, "HttpConnection.onclose(" + error + ") threw error '" + e + "'.");
            }
        }
    };
    HttpConnection.prototype.resolveUrl = function (url) {
        // startsWith is not supported in IE
        if (url.lastIndexOf("https://", 0) === 0 || url.lastIndexOf("http://", 0) === 0) {
            return url;
        }
        if (!Utils["c" /* Platform */].isBrowser || !window.document) {
            throw new Error("Cannot resolve '" + url + "'.");
        }
        // Setting the url to the href propery of an anchor tag handles normalization
        // for us. There are 3 main cases.
        // 1. Relative  path normalization e.g "b" -> "http://localhost:5000/a/b"
        // 2. Absolute path normalization e.g "/a/b" -> "http://localhost:5000/a/b"
        // 3. Networkpath reference normalization e.g "//localhost:5000/a/b" -> "http://localhost:5000/a/b"
        var aTag = window.document.createElement("a");
        aTag.href = url;
        this.logger.log(ILogger["a" /* LogLevel */].Information, "Normalizing '" + url + "' to '" + aTag.href + "'.");
        return aTag.href;
    };
    HttpConnection.prototype.resolveNegotiateUrl = function (url) {
        var index = url.indexOf("?");
        var negotiateUrl = url.substring(0, index === -1 ? url.length : index);
        if (negotiateUrl[negotiateUrl.length - 1] !== "/") {
            negotiateUrl += "/";
        }
        negotiateUrl += "negotiate";
        negotiateUrl += index === -1 ? "" : url.substring(index);
        return negotiateUrl;
    };
    return HttpConnection;
}());

function transportMatches(requestedTransport, actualTransport) {
    return !requestedTransport || ((actualTransport & requestedTransport) !== 0);
}
var TransportSendQueue = /** @class */ (function () {
    function TransportSendQueue(transport) {
        this.transport = transport;
        this.buffer = [];
        this.executing = true;
        this.sendBufferedData = new PromiseSource();
        this.transportResult = new PromiseSource();
        this.sendLoopPromise = this.sendLoop();
    }
    TransportSendQueue.prototype.send = function (data) {
        this.bufferData(data);
        if (!this.transportResult) {
            this.transportResult = new PromiseSource();
        }
        return this.transportResult.promise;
    };
    TransportSendQueue.prototype.stop = function () {
        this.executing = false;
        this.sendBufferedData.resolve();
        return this.sendLoopPromise;
    };
    TransportSendQueue.prototype.bufferData = function (data) {
        if (this.buffer.length && typeof (this.buffer[0]) !== typeof (data)) {
            throw new Error("Expected data to be of type " + typeof (this.buffer) + " but was of type " + typeof (data));
        }
        this.buffer.push(data);
        this.sendBufferedData.resolve();
    };
    TransportSendQueue.prototype.sendLoop = function () {
        return HttpConnection_awaiter(this, void 0, void 0, function () {
            var transportResult, data, error_1;
            return HttpConnection_generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (false) {}
                        return [4 /*yield*/, this.sendBufferedData.promise];
                    case 1:
                        _a.sent();
                        if (!this.executing) {
                            if (this.transportResult) {
                                this.transportResult.reject("Connection stopped.");
                            }
                            return [3 /*break*/, 6];
                        }
                        this.sendBufferedData = new PromiseSource();
                        transportResult = this.transportResult;
                        this.transportResult = undefined;
                        data = typeof (this.buffer[0]) === "string" ?
                            this.buffer.join("") :
                            TransportSendQueue.concatBuffers(this.buffer);
                        this.buffer.length = 0;
                        _a.label = 2;
                    case 2:
                        _a.trys.push([2, 4, , 5]);
                        return [4 /*yield*/, this.transport.send(data)];
                    case 3:
                        _a.sent();
                        transportResult.resolve();
                        return [3 /*break*/, 5];
                    case 4:
                        error_1 = _a.sent();
                        transportResult.reject(error_1);
                        return [3 /*break*/, 5];
                    case 5: return [3 /*break*/, 0];
                    case 6: return [2 /*return*/];
                }
            });
        });
    };
    TransportSendQueue.concatBuffers = function (arrayBuffers) {
        var totalLength = arrayBuffers.map(function (b) { return b.byteLength; }).reduce(function (a, b) { return a + b; });
        var result = new Uint8Array(totalLength);
        var offset = 0;
        for (var _i = 0, arrayBuffers_1 = arrayBuffers; _i < arrayBuffers_1.length; _i++) {
            var item = arrayBuffers_1[_i];
            result.set(new Uint8Array(item), offset);
            offset += item.byteLength;
        }
        return result;
    };
    return TransportSendQueue;
}());

var PromiseSource = /** @class */ (function () {
    function PromiseSource() {
        var _this = this;
        this.promise = new Promise(function (resolve, reject) {
            var _a;
            return _a = [resolve, reject], _this.resolver = _a[0], _this.rejecter = _a[1], _a;
        });
    }
    PromiseSource.prototype.resolve = function () {
        this.resolver();
    };
    PromiseSource.prototype.reject = function (reason) {
        this.rejecter(reason);
    };
    return PromiseSource;
}());
//# sourceMappingURL=HttpConnection.js.map
// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/Loggers.js
var Loggers = __webpack_require__(156);

// EXTERNAL MODULE: ../node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js
var TextMessageFormat = __webpack_require__(160);

// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.





var JSON_HUB_PROTOCOL_NAME = "json";
/** Implements the JSON Hub Protocol. */
var JsonHubProtocol_JsonHubProtocol = /** @class */ (function () {
    function JsonHubProtocol() {
        /** @inheritDoc */
        this.name = JSON_HUB_PROTOCOL_NAME;
        /** @inheritDoc */
        this.version = 1;
        /** @inheritDoc */
        this.transferFormat = TransferFormat.Text;
    }
    /** Creates an array of {@link @microsoft/signalr.HubMessage} objects from the specified serialized representation.
     *
     * @param {string} input A string containing the serialized representation.
     * @param {ILogger} logger A logger that will be used to log messages that occur during parsing.
     */
    JsonHubProtocol.prototype.parseMessages = function (input, logger) {
        // The interface does allow "ArrayBuffer" to be passed in, but this implementation does not. So let's throw a useful error.
        if (typeof input !== "string") {
            throw new Error("Invalid input for JSON hub protocol. Expected a string.");
        }
        if (!input) {
            return [];
        }
        if (logger === null) {
            logger = Loggers["a" /* NullLogger */].instance;
        }
        // Parse the messages
        var messages = TextMessageFormat["a" /* TextMessageFormat */].parse(input);
        var hubMessages = [];
        for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) {
            var message = messages_1[_i];
            var parsedMessage = JSON.parse(message);
            if (typeof parsedMessage.type !== "number") {
                throw new Error("Invalid payload.");
            }
            switch (parsedMessage.type) {
                case MessageType.Invocation:
                    this.isInvocationMessage(parsedMessage);
                    break;
                case MessageType.StreamItem:
                    this.isStreamItemMessage(parsedMessage);
                    break;
                case MessageType.Completion:
                    this.isCompletionMessage(parsedMessage);
                    break;
                case MessageType.Ping:
                    // Single value, no need to validate
                    break;
                case MessageType.Close:
                    // All optional values, no need to validate
                    break;
                default:
                    // Future protocol changes can add message types, old clients can ignore them
                    logger.log(ILogger["a" /* LogLevel */].Information, "Unknown message type '" + parsedMessage.type + "' ignored.");
                    continue;
            }
            hubMessages.push(parsedMessage);
        }
        return hubMessages;
    };
    /** Writes the specified {@link @microsoft/signalr.HubMessage} to a string and returns it.
     *
     * @param {HubMessage} message The message to write.
     * @returns {string} A string containing the serialized representation of the message.
     */
    JsonHubProtocol.prototype.writeMessage = function (message) {
        return TextMessageFormat["a" /* TextMessageFormat */].write(JSON.stringify(message));
    };
    JsonHubProtocol.prototype.isInvocationMessage = function (message) {
        this.assertNotEmptyString(message.target, "Invalid payload for Invocation message.");
        if (message.invocationId !== undefined) {
            this.assertNotEmptyString(message.invocationId, "Invalid payload for Invocation message.");
        }
    };
    JsonHubProtocol.prototype.isStreamItemMessage = function (message) {
        this.assertNotEmptyString(message.invocationId, "Invalid payload for StreamItem message.");
        if (message.item === undefined) {
            throw new Error("Invalid payload for StreamItem message.");
        }
    };
    JsonHubProtocol.prototype.isCompletionMessage = function (message) {
        if (message.result && message.error) {
            throw new Error("Invalid payload for Completion message.");
        }
        if (!message.result && message.error) {
            this.assertNotEmptyString(message.error, "Invalid payload for Completion message.");
        }
        this.assertNotEmptyString(message.invocationId, "Invalid payload for Completion message.");
    };
    JsonHubProtocol.prototype.assertNotEmptyString = function (value, errorMessage) {
        if (typeof value !== "string" || value === "") {
            throw new Error(errorMessage);
        }
    };
    return JsonHubProtocol;
}());

//# sourceMappingURL=JsonHubProtocol.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
var __assign = (undefined && undefined.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};







// tslint:disable:object-literal-sort-keys
var LogLevelNameMapping = {
    trace: ILogger["a" /* LogLevel */].Trace,
    debug: ILogger["a" /* LogLevel */].Debug,
    info: ILogger["a" /* LogLevel */].Information,
    information: ILogger["a" /* LogLevel */].Information,
    warn: ILogger["a" /* LogLevel */].Warning,
    warning: ILogger["a" /* LogLevel */].Warning,
    error: ILogger["a" /* LogLevel */].Error,
    critical: ILogger["a" /* LogLevel */].Critical,
    none: ILogger["a" /* LogLevel */].None,
};
function parseLogLevel(name) {
    // Case-insensitive matching via lower-casing
    // Yes, I know case-folding is a complicated problem in Unicode, but we only support
    // the ASCII strings defined in LogLevelNameMapping anyway, so it's fine -anurse.
    var mapping = LogLevelNameMapping[name.toLowerCase()];
    if (typeof mapping !== "undefined") {
        return mapping;
    }
    else {
        throw new Error("Unknown log level: " + name);
    }
}
/** A builder for configuring {@link @microsoft/signalr.HubConnection} instances. */
var HubConnectionBuilder_HubConnectionBuilder = /** @class */ (function () {
    function HubConnectionBuilder() {
    }
    HubConnectionBuilder.prototype.configureLogging = function (logging) {
        Utils["a" /* Arg */].isRequired(logging, "logging");
        if (isLogger(logging)) {
            this.logger = logging;
        }
        else if (typeof logging === "string") {
            var logLevel = parseLogLevel(logging);
            this.logger = new Utils["b" /* ConsoleLogger */](logLevel);
        }
        else {
            this.logger = new Utils["b" /* ConsoleLogger */](logging);
        }
        return this;
    };
    HubConnectionBuilder.prototype.withUrl = function (url, transportTypeOrOptions) {
        Utils["a" /* Arg */].isRequired(url, "url");
        this.url = url;
        // Flow-typing knows where it's at. Since HttpTransportType is a number and IHttpConnectionOptions is guaranteed
        // to be an object, we know (as does TypeScript) this comparison is all we need to figure out which overload was called.
        if (typeof transportTypeOrOptions === "object") {
            this.httpConnectionOptions = __assign({}, this.httpConnectionOptions, transportTypeOrOptions);
        }
        else {
            this.httpConnectionOptions = __assign({}, this.httpConnectionOptions, { transport: transportTypeOrOptions });
        }
        return this;
    };
    /** Configures the {@link @microsoft/signalr.HubConnection} to use the specified Hub Protocol.
     *
     * @param {IHubProtocol} protocol The {@link @microsoft/signalr.IHubProtocol} implementation to use.
     */
    HubConnectionBuilder.prototype.withHubProtocol = function (protocol) {
        Utils["a" /* Arg */].isRequired(protocol, "protocol");
        this.protocol = protocol;
        return this;
    };
    HubConnectionBuilder.prototype.withAutomaticReconnect = function (retryDelaysOrReconnectPolicy) {
        if (this.reconnectPolicy) {
            throw new Error("A reconnectPolicy has already been set.");
        }
        if (!retryDelaysOrReconnectPolicy) {
            this.reconnectPolicy = new DefaultReconnectPolicy();
        }
        else if (Array.isArray(retryDelaysOrReconnectPolicy)) {
            this.reconnectPolicy = new DefaultReconnectPolicy(retryDelaysOrReconnectPolicy);
        }
        else {
            this.reconnectPolicy = retryDelaysOrReconnectPolicy;
        }
        return this;
    };
    /** Creates a {@link @microsoft/signalr.HubConnection} from the configuration options specified in this builder.
     *
     * @returns {HubConnection} The configured {@link @microsoft/signalr.HubConnection}.
     */
    HubConnectionBuilder.prototype.build = function () {
        // If httpConnectionOptions has a logger, use it. Otherwise, override it with the one
        // provided to configureLogger
        var httpConnectionOptions = this.httpConnectionOptions || {};
        // If it's 'null', the user **explicitly** asked for null, don't mess with it.
        if (httpConnectionOptions.logger === undefined) {
            // If our logger is undefined or null, that's OK, the HttpConnection constructor will handle it.
            httpConnectionOptions.logger = this.logger;
        }
        // Now create the connection
        if (!this.url) {
            throw new Error("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.");
        }
        var connection = new HttpConnection_HttpConnection(this.url, httpConnectionOptions);
        return HubConnection_HubConnection.create(connection, this.logger || Loggers["a" /* NullLogger */].instance, this.protocol || new JsonHubProtocol_JsonHubProtocol(), this.reconnectPolicy);
    };
    return HubConnectionBuilder;
}());

function isLogger(logger) {
    return logger.log !== undefined;
}
//# sourceMappingURL=HubConnectionBuilder.js.map
// CONCATENATED MODULE: ../node_modules/@microsoft/signalr/dist/esm/index.js
/* unused harmony export VERSION */
/* unused concated harmony import AbortError */
/* unused concated harmony import HttpError */
/* unused concated harmony import TimeoutError */
/* unused concated harmony import HttpClient */
/* unused concated harmony import HttpResponse */
/* unused concated harmony import DefaultHttpClient */
/* unused concated harmony import HubConnection */
/* concated harmony reexport HubConnectionState */__webpack_require__.d(__webpack_exports__, "b", function() { return HubConnectionState; });
/* concated harmony reexport HubConnectionBuilder */__webpack_require__.d(__webpack_exports__, "a", function() { return HubConnectionBuilder_HubConnectionBuilder; });
/* unused concated harmony import MessageType */
/* unused concated harmony import LogLevel */
/* unused concated harmony import HttpTransportType */
/* unused concated harmony import TransferFormat */
/* unused concated harmony import NullLogger */
/* unused concated harmony import JsonHubProtocol */
/* unused concated harmony import Subject */
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Version token that will be replaced by the prepack command
/** The version of the SignalR client. */
var VERSION = "3.0.0";











//# sourceMappingURL=index.js.map
// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/constants.js
var constants = __webpack_require__(4);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/models/message.model.js
var message_model = __webpack_require__(157);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/utils/index.js + 2 modules
var utils = __webpack_require__(15);

// EXTERNAL MODULE: ./Scripts/config/config.production.js
var config_production = __webpack_require__(11);
var config_production_default = /*#__PURE__*/__webpack_require__.n(config_production);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/link.model.js


var LinkModel = no_conflict["a" /* Backbone */].Model.extend({
  url: function url() {
    if (!this.get('link')) throw new Error('LinkModel.link is required');
    return "".concat(config_production_default.a.apiUrl, "/api/unfurl?url=").concat(encodeURIComponent(this.get('link')));
  }
});
/* harmony default export */ var link_model = (LinkModel);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/services/data_singleton.js
var data_singleton = __webpack_require__(116);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/MessageView.html
var MessageView = __webpack_require__(643);
var MessageView_default = /*#__PURE__*/__webpack_require__.n(MessageView);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/message.view.js






 // 2MB

var MAX_UNFURL_SIZE = 2 * Math.pow(10, 6); // eslint-disable-line no-magic-numbers

var message_view_MessageView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: MessageView_default.a,
  className: function className() {
    var dir = this.model.get('myMessage') ? 'purechat-message-right' : 'purechat-message-left';
    if (this.isOtherOperatorMessage()) dir += ' purechat-message-break';
    if (this.extendedClassName) dir += " ".concat(this.extendedClassName);
    if (this.hasMultipleOperators()) dir += ' purechat-message-multiple-operators';
    return "purechat-message-wrapper purechat-clearfix ".concat(dir, " purechat-animate purechat-animate-somewhat-fast purechat-animation-fadeInDownSmall");
  },
  ui: {
    timestamp: '.purechat-time'
  },
  events: {
    'click a.purechat-message-link': function clickAPurechatMessageLink(e) {
      e.preventDefault();
      var href = e.target.getAttribute('href');
      window.open(href);
      return false;
    }
  },
  templateHelpers: function templateHelpers() {
    var _this = this;

    return {
      prettyDate: this.prettyDate.bind(this),
      // https://www.youtube.com/watch?v=KiqkclCJsZs
      enhance: function enhance(message) {
        var messageFormatted = utils["a" /* default */].formatWhitespace(message);
        var messageLinkified = utils["a" /* default */].linkify(messageFormatted);
        return messageLinkified;
      },
      iconRootUrl: function iconRootUrl() {
        return utils["a" /* default */].iconRootUrl(_this.getOption('settings').get('isDemo'));
      },
      svgHrefAttr: function svgHrefAttr() {
        return utils["a" /* default */].svgHrefAttr();
      },
      isNote: function isNote() {
        return _this.model.get('type') === constants["a" /* default */].MessageTypes.Note;
      },
      isSeparator: function isSeparator() {
        return _this.model.get('type') === constants["a" /* default */].MessageTypes.Separator;
      },
      isMessage: function isMessage() {
        return _this.model.get('type') === constants["a" /* default */].MessageTypes.Message;
      },
      hasMultipleOperators: this.hasMultipleOperators.bind(this)
    };
  },
  onRender: function onRender() {
    this.$el.attr({
      'data-userid': this.model.get('userId')
    });
    var typeClass = this.model.getTypeString();
    this.$el.addClass(this.model.get('type') !== constants["a" /* default */].MessageTypes.Message ? "purechat-".concat(typeClass) : '');
    this.$el.addClass(this.model.get('isClosedChat') ? 'closed' : '');
  },
  isOtherOperatorMessage: function isOtherOperatorMessage() {
    var _this2 = this;

    if (this.model.get('type') === constants["a" /* default */].MessageTypes.Separator || this.model.get('type') === constants["a" /* default */].MessageTypes.Note) return true;
    var messages = this.getOption('messages');
    if (messages.length < 2) return true; // eslint-disable-line no-magic-numbers

    var index = no_conflict["c" /* _ */].findIndex(messages, function (m) {
      return m.id && m.id === _this2.model.get('id') || m.timeAdded === _this2.model.get('timeAdded');
    });

    var previousMessage = messages[index - 1];
    return !previousMessage || !this.model.get('myMessage') && this.model.get('userId') !== previousMessage.userId;
  },
  updateTimestamp: function updateTimestamp() {
    if (this.model.get('time') && this.ui.timestamp && !no_conflict["c" /* _ */].isString(this.ui.timestamp)) {
      this.ui.timestamp.text(this.prettyDate());
    }
  },
  isInViewport: function isInViewport(parentTop, parentBottom) {
    var myTop = this.$el.offset().top;
    var myBottom = myTop + this.$el.outerHeight();

    if (myTop >= parentTop && myTop <= parentBottom || myBottom >= parentTop && myBottom <= parentBottom) {
      return true;
    }

    return false;
  },
  unfurlLinks: function unfurlLinks(viewportTop, viewportBottom) {
    var _this3 = this;

    var isOperator = this.getOption('settings').get('isOperator');
    if (!isOperator && !this.getOption('settings').get('LinkSummariesEnabled')) return;
    if (isOperator && !this.getOption('rm').get('LinkSummariesEnabled')) return;
    if (this.model.get('unfurled') || this.model.get('type') !== constants["a" /* default */].MessageTypes.Message) return;

    if (viewportTop !== undefined && viewportBottom !== undefined) {
      if (!this.isInViewport(viewportTop, viewportBottom)) return;
    }

    var links = utils["a" /* default */].getLinks(this.model.get('message'));
    this.model.set('unfurled', true);
    if (links.length === 0) return;
    var models = links.map(function (link) {
      var url = link;

      if (link.indexOf('http') < 0) {
        url = "http://".concat(url);
      }

      return new link_model({
        link: url
      });
    });
    models.forEach(function (model) {
      model.fetch().then(function (res, status) {
        if (status === 'nocontent') return;
        if (model.get('size') > MAX_UNFURL_SIZE) return;

        var messageAttributes = no_conflict["c" /* _ */].extend(_this3.model.toJSON(), model.toJSON(), {
          parent: _this3.model,
          // Make the unfurl message 1 tick later than the parent message
          // so that it sorts with its parent correctly.
          date: new Date(_this3.model.get('date').getTime() + 1)
        });

        delete messageAttributes.id;
        var message = new message_model["a" /* default */](messageAttributes);

        _this3.model.collection.add(message);
      });
    });
  },
  prettyDate: function prettyDate() {
    var settings = this.getOption('settings');
    var showTime = settings.get('ShowFullMessageTimestamp');
    if (settings.get('isDemo')) return showTime ? utils["a" /* default */].toHourMinuteString(new Date(), false) : 'Just now';
    if (showTime || settings.get('isOperator')) return utils["a" /* default */].toHourMinuteString(this.model.get('date'), false);
    return utils["a" /* default */].prettyDate(this.model.get('date'));
  },
  hasMultipleOperators: function hasMultipleOperators() {
    if (this.getOption('settings').get('isOperator')) return false;
    if (this.model.get('type') !== constants["a" /* default */].MessageTypes.Message) return false;
    if (this.model.get('myMessage')) return false;
    var service = data_singleton["a" /* default */].getInstance();
    var chatModel = no_conflict["b" /* Marionette */].getOption(service, 'chatModel');
    return chatModel.get('operators').length > 1;
  }
});
/* harmony default export */ var message_view = (message_view_MessageView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/ClosedMessage.html
var ClosedMessage = __webpack_require__(644);
var ClosedMessage_default = /*#__PURE__*/__webpack_require__.n(ClosedMessage);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/closed_message.view.js




var ClosedMessageView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: ClosedMessage_default.a,
  className: 'purechat-message-note purechat-message-note-closed',
  attributes: {
    width: '100%'
  },
  ui: {
    ratingThanks: '.purechat-rating-thanks',
    displayContainer: '.purechat-message-display-container',
    ratingPrompt: '[data-resourcekey="closed_askForRating"]',
    thumbsUp: '.purechat-thumbs-up',
    thumbsDown: '.purechat-thumbs-down'
  },
  templateHelpers: function templateHelpers() {
    var settings = this.options.settings.toJSON();
    settings.showPoweredBy = !settings.isOperator && !settings.RemoveBranding;
    settings.poweredByUrl = this.options.settings.poweredByUrl();

    settings.ctaUrl = function () {
      var ctaUrl = this.getResource('button_cta_url');
      var httpRegex = new RegExp('(https|http)://');
      return ctaUrl.search(httpRegex) !== 0 ? 'http://' + ctaUrl : ctaUrl;
    };

    settings.iconRootUrl = function () {
      return utils["a" /* default */].iconRootUrl(settings.isDemo);
    };

    settings.svgHrefAttr = function () {
      return utils["a" /* default */].svgHrefAttr();
    };

    settings.apiUrl = config_production_default.a.apiUrl;
    return settings;
  },
  events: {
    'click @ui.thumbsUp': 'handleThumbsUp',
    'click @ui.thumbsDown': 'handleThumbsDown',
    'click .purechat-download-container a': 'handleDownload'
  },
  handleThumbsUp: function handleThumbsUp() {
    if (!this.options.settings.get('isInEditorMode')) {
      this.ui.thumbsUp.addClass('purechat-thumbs-selected');
      this.rateChat(true);
    }
  },
  handleThumbsDown: function handleThumbsDown() {
    if (!this.options.settings.get('isInEditorMode')) {
      this.ui.thumbsDown.addClass('purechat-thumbs-selected');
      this.rateChat(false);
    }
  },
  handleDownload: function handleDownload() {
    return !this.options.settings.get('isInEditorMode');
  },
  rateChat: function rateChat(up) {
    if (!this.rating) {
      this.rating = up ? 1 : 0;
      this.trigger('chat:rated', this.rating);
    }

    this.$el.find('.purechat-thumbs-selectable:not(.purechat-thumbs-selected)').remove();
    this.ui.ratingThanks.text(this.getResource('closed_ratingThanks'));
    this.ui.ratingThanks.attr('data-resourcekey', 'closed_ratingThanks');

    if (this.ui.ratingPrompt.length > 0) {
      this.ui.ratingPrompt.purechatDisplay('none');
    }
  }
});
/* harmony default export */ var closed_message_view = (ClosedMessageView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/empty.view.js


var EmptyView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: no_conflict["c" /* _ */].template(''),
  className: 'empty-item'
});
/* harmony default export */ var empty_view = (EmptyView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/unfurl_link.html
var unfurl_link = __webpack_require__(645);
var unfurl_link_default = /*#__PURE__*/__webpack_require__.n(unfurl_link);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/unfurl_link.view.js



var DEFAULT_CHAR_COUNT = 34;
var UnfurlLinkView = message_view.extend({
  template: unfurl_link_default.a,
  extendedClassName: 'purechat-unfurl-link',
  templateHelpers: function templateHelpers() {
    return no_conflict["c" /* _ */].extend({
      truncate: function truncate(txt) {
        var charCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_CHAR_COUNT;
        return txt.substring(0, charCount);
      }
    }, message_view.prototype.templateHelpers.apply(this, arguments));
  }
});
/* harmony default export */ var unfurl_link_view = (UnfurlLinkView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/unfurl_image.html
var unfurl_image = __webpack_require__(317);
var unfurl_image_default = /*#__PURE__*/__webpack_require__.n(unfurl_image);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/unfurl_image.view.js


var UnfurlImageView = message_view.extend({
  template: unfurl_image_default.a,
  extendedClassName: 'purechat-unfurl-image'
});
/* harmony default export */ var unfurl_image_view = (UnfurlImageView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/unfurl_giphy.view.js


var UnfurlGiphyView = message_view.extend({
  template: unfurl_image_default.a,
  extendedClassName: 'purechat-unfurl-giphy'
});
/* harmony default export */ var unfurl_giphy_view = (UnfurlGiphyView);
// EXTERNAL MODULE: ../node_modules/jquery/src/jquery.js
var jquery = __webpack_require__(0);
var jquery_default = /*#__PURE__*/__webpack_require__.n(jquery);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/unfurl_youtube.html
var unfurl_youtube = __webpack_require__(646);
var unfurl_youtube_default = /*#__PURE__*/__webpack_require__.n(unfurl_youtube);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/unfurl_youtube.view.js




var UnfurlYoutubeView = message_view.extend({
  template: unfurl_youtube_default.a,
  extendedClassName: 'purechat-unfurl-youtube',
  ui: no_conflict["c" /* _ */].extend({
    playButton: '.purechat-unfurl-play',
    image: '.purechat-unfurl-media'
  }, message_view.prototype.ui),
  events: no_conflict["c" /* _ */].extend({
    'click @ui.playButton': 'playVideo',
    'click @ui.image': 'playVideo'
  }, message_view.prototype.events),
  playVideo: function playVideo() {
    var iframe = jquery_default()('<iframe></iframe>').attr({
      src: this.model.get('media') + '?autoplay=1',
      width: '100%',
      class: 'purechat-unfurl-iframe',
      frameborder: '0',
      webkitallowfullscreen: 'webkitallowfullscreen',
      mozallowfullscreen: 'mozallowfullscreen',
      allowfullscreen: 'allowfullscreen'
    });
    this.ui.image.after(iframe).purechatDisplay('none');
    this.ui.playButton.purechatDisplay('none');
  }
});
/* harmony default export */ var unfurl_youtube_view = (UnfurlYoutubeView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/unfurl_twitter.html
var unfurl_twitter = __webpack_require__(647);
var unfurl_twitter_default = /*#__PURE__*/__webpack_require__.n(unfurl_twitter);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/unfurl_twitter.view.js


var UnfurlTwitterView = message_view.extend({
  template: unfurl_twitter_default.a,
  extendedClassName: 'purechat-unfurl-twitter'
});
/* harmony default export */ var unfurl_twitter_view = (UnfurlTwitterView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/image_preview.html
var image_preview = __webpack_require__(648);
var image_preview_default = /*#__PURE__*/__webpack_require__.n(image_preview);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/image_preview.view.js



var ESCAPE_KEY = 27;
var ImagePreviewView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: image_preview_default.a,
  id: 'PureChatWidgetImagePreview',
  templateHelpers: function templateHelpers() {
    return {
      imageUrl: this.getOption('image')
    };
  },
  events: {
    'click': 'destroy'
  },
  onRender: function onRender() {
    jquery_default()('body').on('keydown.purechat-files', this.onKeyDown.bind(this));
  },
  onDestroy: function onDestroy() {
    jquery_default()('body').off('keydown.purechat-files');
  },
  onKeyDown: function onKeyDown(e) {
    if ((e.which || e.keyCode) !== ESCAPE_KEY) return;
    this.destroy();
  }
});
/* harmony default export */ var image_preview_view = (ImagePreviewView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/file.html
var file = __webpack_require__(649);
var file_default = /*#__PURE__*/__webpack_require__.n(file);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/file.view.js





var FileView = message_view.extend({
  template: file_default.a,
  extendedClassName: 'purechat-file',
  templateHelpers: function templateHelpers() {
    var _this = this;

    return no_conflict["c" /* _ */].extend({
      isError: this.isError.bind(this),
      isUploading: this.isUploading.bind(this),
      getMessageDescription: this.getMessageDescription.bind(this),
      transferStateClass: function transferStateClass() {
        if (_this.isUploading()) return 'purechat-file-status-uploading';
        if (_this.isError()) return 'purechat-file-status-error';
        if (_this.isComplete()) return 'purechat-file-status-complete';
        return '';
      },
      isOperator: function isOperator() {
        return _this.getOption('settings').get('isOperator');
      },
      isImage: this.isImage.bind(this),
      getGeneralError: function getGeneralError() {
        return _this.getOption('settings').getResource('error_fileTransfer') || constants["a" /* default */].UploadErrorMessages.default;
      },
      parsed: this.model.parseMessage()
    }, message_view.prototype.templateHelpers.apply(this, arguments));
  },
  ui: {
    fileActions: '.purechat-file-actions',
    fileImage: '.purechat-file-image img',
    fileImageSpinner: '.purechat-file-image .purechat-loading'
  },
  events: no_conflict["c" /* _ */].extend({
    'click .purechat-file-delete': 'deleteFile',
    'click @ui.fileImage': 'imageClicked'
  }, message_view.prototype.events),
  modelEvents: no_conflict["c" /* _ */].extend({
    change: 'render'
  }, message_view.prototype.modelEvents),
  onRender: function onRender() {
    this.ui.fileImage.on('load.purechat-file', this.fileImageLoaded.bind(this));
    this.$el.addClass(this.model.get('isClosedChat') ? 'closed' : '');
  },
  onDestroy: function onDestroy() {
    this.ui.fileImage.off('.purechat-file');
  },
  fileImageLoaded: function fileImageLoaded() {
    this.ui.fileImageSpinner.purechatDisplay('none');
    this.ui.fileImage.purechatDisplay('inline').addClass('purechat-animate purechat-animate-somewhat-fast purechat-animation-fadeIn');
    this.trigger('file:image-loaded', {
      fromFileImage: true
    });
  },
  imageClicked: function imageClicked() {
    var settings = this.getOption('settings');
    var isMobile = settings.isMobileRequest() && !settings.isDesktopDimension();
    if (!this.isImage()) return;

    if (isMobile) {
      this.$('.purechat-file-image').toggleClass('purechat-file-image-active');
    } else {
      var parsed = this.model.parseMessage();
      var previewView = new image_preview_view({
        image: parsed.url
      });
      previewView.on('destroy', function () {
        previewView.$el.remove();
        previewView.off('destroy');
      });
      previewView.render();
      previewView.$el.appendTo('body');
    }
  },
  deleteFile: function deleteFile() {
    this.trigger('file:delete', this.model.toJSON());
  },
  isImage: function isImage() {
    var parsed = this.model.parseMessage();
    return (parsed.mimeType || '').indexOf('image/') === 0;
  },
  isStatus: function isStatus(status) {
    return this.model.get('status') === status;
  },
  isError: function isError() {
    return this.isStatus(constants["a" /* default */].UploadStatuses.Error) || this.isStatus(constants["a" /* default */].UploadStatuses.Unauthorized);
  },
  isUploading: function isUploading() {
    return this.isStatus(constants["a" /* default */].UploadStatuses.Start) || this.isStatus(constants["a" /* default */].UploadStatuses.Uploading) || this.isStatus(constants["a" /* default */].UploadStatuses.Unfinalized);
  },
  isComplete: function isComplete() {
    return this.isStatus(null) || this.isStatus(undefined) || this.isStatus(constants["a" /* default */].UploadStatuses.Complete);
  },
  getMessageDescription: function getMessageDescription() {
    if (this.isUploading()) {
      return this.model.get('myMessage') ? 'Uploading...' : 'Receiving...';
    }

    if (this.isComplete()) {
      var parsed = this.model.parseMessage();
      return "".concat(parsed.name, "<br/><small>").concat(parsed.size, " \u2022 ").concat(parsed.mimeType, "</small>");
    }

    return '';
  }
});
/* harmony default export */ var file_view = (FileView);
// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/message_list.html
var message_list = __webpack_require__(650);
var message_list_default = /*#__PURE__*/__webpack_require__.n(message_list);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/message_list.view.js
/* eslint-disable no-invalid-this */













var SCROLL_BOTTOM_BUFFER_PX = 50;
var SCROLL_DEBOUNCE = 250;
var ONE_MINUTE_IN_MILLISECONDS = 60000;
var NEW_MESSAGE_ADDED_TIMEOUT_MS = 100;
var MessageListView = no_conflict["b" /* Marionette */].CompositeView.extend({
  template: message_list_default.a,
  id: 'purechat-message-display-container',
  className: 'purechat-message-display-container',
  ui: {
    messageListContainer: '.purechat-message-display',
    showPrevious: '.purechat-showPrevious'
  },
  events: {
    'click .purechat-showPrevious': 'showPrevious' // Backbone doesn't register a scroll event for some reason, so this event is
    // hooked up manually with jQuery in the render function.
    // 'scroll @ui.messageListContainer': 'listScrolled'

  },
  modelEvents: {
    'change:HasMoreTransactions': 'updatePreviousVisibility',
    'change:expanded': 'checkForMobileExpand'
  },
  collectionEvents: {
    'add': 'listChanged'
  },
  childEvents: {
    'chat:rated': function chatRated(view, up) {
      this.trigger('chat:rated', up);
    },
    'file:image-loaded': 'listScrolled',
    'file:delete': 'deleteFile'
  },
  triggers: {
    showPrevious: 'showPrevious'
  },
  onAddChild: function onAddChild() {
    var _this = this;

    if (this.newMessageAddedTimerId) {
      clearTimeout(this.newMessageAddedTimerId);
    }

    this.newMessageAddedTimerId = setTimeout(function () {
      _this.unfurlChildren();

      clearTimeout(_this.newMessageAddedTimerId);
    }, NEW_MESSAGE_ADDED_TIMEOUT_MS);
  },
  getChildView: function getChildView(messageModel) {
    switch (messageModel.get('type')) {
      case constants["a" /* default */].MessageTypes.UnfurlLink:
        return unfurl_link_view;

      case constants["a" /* default */].MessageTypes.UnfurlImage:
        return unfurl_image_view;

      case constants["a" /* default */].MessageTypes.UnfurlGiphy:
        return unfurl_giphy_view;

      case constants["a" /* default */].MessageTypes.UnfurlYoutube:
        return unfurl_youtube_view;

      case constants["a" /* default */].MessageTypes.UnfurlTwitter:
        return unfurl_twitter_view;

      case constants["a" /* default */].MessageTypes.File:
        return file_view;

      case constants["a" /* default */].MessageTypes.Closed:
        return closed_message_view;

      case constants["a" /* default */].MessageTypes.Message:
      default:
        return message_view;
    }
  },
  childViewOptions: function childViewOptions() {
    return {
      rm: no_conflict["b" /* Marionette */].getOption(this, 'rm'),
      settings: no_conflict["b" /* Marionette */].getOption(this, 'settings'),
      messages: this.collection.toJSON()
    };
  },
  childViewContainer: '.purechat-message-display',
  emptyView: empty_view,
  onDestroy: function onDestroy() {
    clearInterval(this.lastMessageTimeHandler);
    this.ui.messageListContainer.off('.purechat-messages');
  },
  onRender: function onRender() {
    this.ui.messageListContainer.on('scroll.purechat-messages', this.listScrolled.bind(this));
    this.updatePreviousVisibility();
  },
  initialize: function initialize() {
    var _this2 = this;

    this.chatModel = no_conflict["b" /* Marionette */].getOption(this, 'chatModel');
    this.unfurled = this.model.get('type') !== constants["a" /* default */].MessageTypes.Message;

    if (!this.chatModel.get('scrollBottom')) {
      this.chatModel.set('scrollBottom', 0);
    }

    this.lastMessageTimeHandler = setInterval(function () {
      var lastChild = _this2.children.last();

      if (!lastChild || !lastChild.updateTimestamp) return;
      lastChild.updateTimestamp();
    }, ONE_MINUTE_IN_MILLISECONDS);
  },
  getScrollBottom: function getScrollBottom() {
    return this.chatModel.get('scrollBottom');
  },
  setScrollBottom: function setScrollBottom(value) {
    this.chatModel.set('scrollBottom', value);
  },
  listScrolled: no_conflict["c" /* _ */].debounce(function (event, args) {
    if (!this.ui.messageListContainer || no_conflict["c" /* _ */].isString(this.ui.messageListContainer)) return;
    var controller = this.getOption('viewController');
    var container = this.ui.messageListContainer;
    var domContainer = this.ui.messageListContainer.get(0);
    var scrollBottom = domContainer.scrollHeight - container.height() - container.scrollTop();
    var currentScrollBottom = this.getScrollBottom();

    if (args && args.fromFileImage && currentScrollBottom <= SCROLL_BOTTOM_BUFFER_PX) {
      this.setScrollBottom(0);
      this.updateScroll();
      if (controller.scrolledToBottom) controller.scrolledToBottom();
    } else {
      this.setScrollBottom(scrollBottom);

      if (scrollBottom <= SCROLL_BOTTOM_BUFFER_PX && controller.scrolledToBottom) {
        controller.scrolledToBottom();
      }
    }

    this.unfurlChildren();
  }, SCROLL_DEBOUNCE),
  unfurlChildren: function unfurlChildren() {
    var viewportTop = this.$el.offset().top;
    var viewportBottom = viewportTop + this.$el.innerHeight();
    this.children.forEach(function (messageView) {
      if (messageView.unfurlLinks && typeof messageView.unfurlLinks === 'function') {
        messageView.unfurlLinks(viewportTop, viewportBottom);
      }
    });
  },
  listChanged: function listChanged(model) {
    var _this3 = this;

    // Don't scroll if this is an unfurl message
    var unfurlTypes = [constants["a" /* default */].MessageTypes.UnfurlLink, constants["a" /* default */].MessageTypes.UnfurlImage, constants["a" /* default */].MessageTypes.UnfurlGiphy, constants["a" /* default */].MessageTypes.UnfurlYoutube, constants["a" /* default */].MessageTypes.UnfurlTwitter];
    if (unfurlTypes.indexOf(model.get('type')) > -1 && this.getScrollBottom() > SCROLL_BOTTOM_BUFFER_PX) return; // Get rid of all previous closed messages

    if (model.get('type') !== constants["a" /* default */].MessageTypes.Closed) {
      var closedMessages = this.collection.where({
        type: constants["a" /* default */].MessageTypes.Closed
      });
      this.collection.remove(closedMessages);
    } //Adjust the bottom scroll if we get a message and we are at the top since the scroll position won't update.


    if (!model.get('isClosedChat') && this.getScrollBottom() !== 0 && this.ui.messageListContainer.scrollTop() === 0) {
      this.setScrollBottom(this.ui.messageListContainer[0].scrollHeight - this.ui.messageListContainer.height());
    } //If this is you message and not from a closed chat, stick to the bottom.;


    if (!model.get('isClosedChat') && this.model.get('userId') === model.get('userId')) {
      this.setScrollBottom(0);
    } //Give us some margin for error


    if (this.getScrollBottom() <= SCROLL_BOTTOM_BUFFER_PX) {
      this.setScrollBottom(0);
    }

    if (this.getScrollBottom() === 0 || model.get('isClosedChat')) {
      if (this.scrollTimeout) {
        clearTimeout(this.scrollTimeout);
        this.scrollTimeout = null;
      }

      this.scrollTimeout = setTimeout(function () {
        _this3.scrollTimeout = null;
        if (model.get('isClosedChat')) _this3.setScrollBottom(0);

        _this3.updateScroll();
      }, 0);
    }
  },
  updateScroll: function updateScroll() {
    if (no_conflict["c" /* _ */].isString(this.ui.messageListContainer)) return;
    this.ui.messageListContainer.scrollTop(this.ui.messageListContainer[0].scrollHeight - this.ui.messageListContainer.height() - this.getScrollBottom());
  },
  showPrevious: function showPrevious() {
    this.triggerMethod('showPrevious');
  },
  updatePreviousVisibility: function updatePreviousVisibility() {
    if (this.model.get('HasMoreTransactions')) {
      this.ui.showPrevious.purechatDisplay('block');
    } else {
      this.ui.showPrevious.purechatDisplay('none');
    }
  },
  checkForMobileExpand: function checkForMobileExpand(model, expanded) {
    var settings = this.getOption('settings');
    var isMobile = settings.useMobile() && !settings.isDesktopDimension();

    if (expanded && isMobile) {
      this.setScrollBottom(0);
      this.updateScroll();
    }
  },
  deleteFile: function deleteFile(view, data) {
    var service = this.getOption('viewController').getDataController();
    service.deleteMessage(data);
  }
});
/* harmony default export */ var message_list_view = __webpack_exports__["a"] = (MessageListView);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// EXTERNAL MODULE: ../node_modules/tinycolor2/tinycolor.js
var tinycolor = __webpack_require__(625);
var tinycolor_default = /*#__PURE__*/__webpack_require__.n(tinycolor);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/utils/css.js


var LUMINANCE_THRESHOLD = 0.5;
var LIGHTNESS_DELTA = 90;
var DESATURATION_LEVEL = 90;
var supportsCssVars = window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)');

function invert(tColor, lightness, desat) {
  if (!no_conflict["c" /* _ */].isNumber(lightness)) lightness = LIGHTNESS_DELTA;
  if (!no_conflict["c" /* _ */].isNumber(desat)) desat = DESATURATION_LEVEL;

  if (tColor.isDark()) {
    return tColor.lighten(lightness).desaturate(desat);
  } else if (tColor.isLight()) {
    return tColor.darken(lightness).desaturate(desat);
  }
}

function legacyInvert(tColor, lightness, desat) {
  if (!no_conflict["c" /* _ */].isNumber(lightness)) lightness = LIGHTNESS_DELTA;
  if (!no_conflict["c" /* _ */].isNumber(desat)) desat = DESATURATION_LEVEL;

  if (tColor.getLuminance() < LUMINANCE_THRESHOLD) {
    return tColor.lighten(lightness).desaturate(desat);
  } else {
    return tColor.darken(lightness).desaturate(desat);
  }
}

function polyfillCssVars(styleBlockId, variables) {
  var cssEl = document.getElementById(styleBlockId);
  var originalCssTemplateId = "".concat(styleBlockId, "_orig");
  var originalCssTemplate = document.getElementById(originalCssTemplateId);

  if (!originalCssTemplate) {
    // A template is used so that the contents aren't rendered on the page.
    originalCssTemplate = document.createElement('template');
    originalCssTemplate.id = originalCssTemplateId;
    originalCssTemplate.innerHTML = cssEl.innerHTML;
    originalCssTemplate.style.display = 'none';
    document.head.appendChild(originalCssTemplate);
  }

  var css = originalCssTemplate.innerHTML;
  Object.keys(variables).forEach(function (key) {
    var regex = new RegExp("var\\(\\s*?".concat(key, "(\\)|,([\\s\\,\\w]*\\)))"), 'g');
    css = css.replace(regex, variables[key]);
  });
  cssEl.innerHTML = css;
}

function writeCssVars(styleBlockId, vars) {
  var varBlockId = "".concat(styleBlockId, "_vars");
  var varBlock = document.getElementById(varBlockId);

  if (!varBlock) {
    varBlock = document.createElement('style');
    varBlock.id = varBlockId;
    document.head.appendChild(varBlock);
  }

  var rules = Object.keys(vars).reduce(function (acc, el) {
    return "".concat(acc, " ").concat(el, ": ").concat(vars[el], ";");
  }, '');
  varBlock.innerHTML = ":root { ".concat(rules, " }");
}

function setCssVars(styleBlockId, baseColor, isMinimal) {
  baseColor = baseColor.indexOf('#') === 0 ? baseColor : "#".concat(baseColor);
  var c = new tinycolor_default.a(baseColor);
  var FIVE_PERCENT = 5; // Css Vars
  //
  // -p- = Primary
  // -s- = Secondary
  // -bg = Background
  // -bg-d/l = Dark/Light
  // -fg = Foreground
  // -btn-b = Button Border
  // -btn-b-h = Button Border Hover

  var vars = {
    '--purechat-p-bg': c.clone().toString(),
    '--purechat-p-bg-d': c.clone().darken(FIVE_PERCENT).toString(),
    '--purechat-p-bg-l': c.clone().lighten(FIVE_PERCENT).toString(),
    '--purechat-p-fg': legacyInvert(c.clone()).toString(),
    '--purechat-p-fg-l': invert(c.clone()).lighten(FIVE_PERCENT).toString()
  };

  if (isMinimal) {
    vars['--purechat-s-bg'] = '#f8f7f5';
    vars['--purechat-s-bg-d'] = '#e8e5df';
    vars['--purechat-s-bg-l'] = '#ffffff';
    vars['--purechat-s-fg'] = '#676a6d';
    vars['--purechat-s-fg-l'] = '#3b404c';
    vars['--purechat-s-fg-d'] = '#3b404c';
    vars['--purechat-a-d'] = '#c11e1f';
    vars['--purechat-a-d-bg'] = '#c11e1f';
    vars['--purechat-a-d-fg'] = '#ffffff';
    vars['--purechat-btn-bg'] = c.clone().toString();
    vars['--purechat-btn-fg'] = legacyInvert(c.clone()).toString();
    vars['--purechat-btn-b'] = 'rgba(255,255,255,0.5)';
    vars['--purechat-btn-b-h'] = 'rgba(255, 255, 255, 1)';
  } else {
    vars['--purechat-s-bg'] = c.clone().toString();
    vars['--purechat-s-bg-d'] = c.clone().darken(FIVE_PERCENT).toString();
    vars['--purechat-s-bg-l'] = c.clone().lighten(FIVE_PERCENT).toString();
    vars['--purechat-s-fg'] = legacyInvert(c.clone()).toString();
    vars['--purechat-s-fg-l'] = invert(c.clone()).lighten(FIVE_PERCENT).toString();
    vars['--purechat-s-fg-d'] = legacyInvert(c.clone()).toString();
    vars['--purechat-a-d'] = legacyInvert(c.clone()).toString();
    vars['--purechat-btn-bg'] = c.clone().darken(FIVE_PERCENT).toString();
    vars['--purechat-btn-fg'] = legacyInvert(c.clone()).toString();
    vars['--purechat-btn-b'] = 'transparent';
    vars['--purechat-btn-b-h'] = 'transparent';
  }

  if (!supportsCssVars) {
    polyfillCssVars(styleBlockId, vars);
  } else {
    writeCssVars(styleBlockId, vars);
  }
}
// EXTERNAL MODULE: ../node_modules/jquery/src/jquery.js
var jquery = __webpack_require__(0);
var jquery_default = /*#__PURE__*/__webpack_require__.n(jquery);

// EXTERNAL MODULE: ../node_modules/autolinker/dist/Autolinker.js
var Autolinker = __webpack_require__(326);
var Autolinker_default = /*#__PURE__*/__webpack_require__.n(Autolinker);

// EXTERNAL MODULE: ./Scripts/shared/utils/regular-expressions.js
var regular_expressions = __webpack_require__(300);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/utils/base.js



var ONE_SECOND_IN_MILLISECONDS = 1000;
var ONE_MINUTE_IN_SECONDS = 60;
var TWO_MINUTES_IN_SECONDS = 120;
var ONE_HOUR_IN_SECONDS = 3600;
var TWO_HOURS_IN_SECONDS = 7200;
var ONE_DAY_IN_SECONDS = 86400;
var ONE_MONTH_IN_DAYS = 31;
var ONE_WEEK_IN_DAYS = 7;
var ONE_YEAR_IN_MONTHS = 12;
var urlMatcher = new Autolinker_default.a.matcher.Url({
  stripPrefix: true,
  stripTrailingSlash: true,
  tagBuilder: {},
  decodePercentEncoding: true
});

var isInIframe = function isInIframe() {
  try {
    return window.self !== window.top;
  } catch (ex) {
    return true;
  }
};

var Utils = {};

Utils.linkify = function (message) {
  if (!message) return null;
  message = message.replace(/&amp;/gm, '&');
  message = message.replace(regular_expressions["default"].brTags, ' <br/> ');
  return Autolinker_default.a.link(message, {
    'stripPrefix': false,
    className: 'purechat-message-link'
  });
};

Utils.getLinks = function (message) {
  var updatedMessage = message.split(' ').filter(function (word) {
    return word.indexOf('@') < 0;
  }).join(' ');
  return urlMatcher.parseMatches(updatedMessage).map(function (match) {
    return match.url;
  });
};

Utils.formatWhitespace = function (message) {
  var m = message.replace(/\n|\r/gm, ' <br/> ');
  m = m.replace(/\t/gm, ' &nbsp; &nbsp; ');
  return m.replace(/\s\s/g, ' &nbsp;');
};

Utils.GaEvent = function (widgetSettings, eventEnabled, event) {
  var category = 'GAEventCategory';
  var failedGa = false;

  var eventFnc = function eventFnc() {
    if (window._gaq || window.ga) {
      if (window.ga) {
        try {
          window.ga('create', widgetSettings.get('GoogId'), 'auto', 'pcTracker');
          window.ga('pcTracker.send', 'event', widgetSettings.get(category), widgetSettings.get(event));
        } catch (ex) {
          failedGa = true;
          console.log('Unable to push event to Google via _gaq');
        }
      }

      if (window.ga && failedGa && window._gaq || !failedGa && window._gaq) {
        try {
          window._gaq.push(['_setAccount', widgetSettings.get('GoogId')]);

          window._gaq.push(['_trackEvent', widgetSettings.get(category), widgetSettings.get(event)]);
        } catch (ex) {
          console.log('Unable to push event to Google via _gaq');
        }
      }
    }
  };

  if (widgetSettings.get('UsingGa') && widgetSettings.get(eventEnabled) && widgetSettings.get(event)) {
    if (!window._gaq && !window.ga && !this.isOperator) {
      (function () {
        var ga = document.createElement('script');
        ga.type = 'text/javascript';
        ga.async = true;
        ga.src = (document.location.protocol === 'https:' ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var loaded = false;

        ga.onreadystatechange = ga.onload = function () {
          if (!loaded && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) {
            window._gaq = window._gaq || [];
            eventFnc();
            loaded = true;
          }
        };

        document.getElementsByTagName('head').item(0).appendChild(ga);
      })();
    } else if (!this.isOperator) {
      eventFnc();
    }
  }
};

Utils.Notifier = function () {
  this.isTitleModified = false;
  this.windowNotifyTimeout = null;
  this.timeoutId = null;
  this.active = false;
  this.mobileActive = false;
  this.mobileAnimationInterval = null;
};

Utils.Notifier.prototype.notify = function (message, additionalElement, mouseStopElement) {
  var t = this;
  t.mouseStopElement = mouseStopElement; // Don't notify multiple times at once

  if (t.active) return;
  t.active = true;
  var originalElementTitle;
  var originalTitle = document.title;
  if (additionalElement) originalElementTitle = additionalElement.text();

  var switchTitle = function switchTitle() {
    if (t.active == false) {
      document.title = originalTitle;
      if (additionalElement) additionalElement.text(originalElementTitle);
      t.isTitleModified = false;
      return;
    }

    if (t.isTitleModified == true) {
      t.isTitleModified = false;
      document.title = originalTitle;
      if (additionalElement) additionalElement.text(originalElementTitle);
    } else {
      t.isTitleModified = true;
      document.title = message;
      if (additionalElement) additionalElement.text(message);
    }

    t.timeoutId = setTimeout(switchTitle, 900);
  };

  t.timeoutId = setTimeout(switchTitle, 900);

  if (t.mouseStopElement) {
    t.mouseStopElement.on('mousemove.notifier', function () {
      t.stop();
    });
  } else {
    jquery_default()(document).on('mousemove.notifier', function () {
      t.stop();
    });
  }
};

Utils.Notifier.prototype.stop = function () {
  this.active = false;

  if (this.mouseStopElement) {
    this.mouseStopElement.off('mousemove.notifier');
  } else {
    jquery_default()(document).off('mousemove.notifier');
  }
};

Utils.stripDangerousTags = function (text) {
  return text.replace(/<script>.+<\/script>/gim, '');
};

Utils.stripOpenCloseTage = function (text) {
  return text.replace(/<.+?>/gim, '');
};

Utils.escapeHtml = function (text, replaceQuotes) {
  var escapedText = jquery_default()('<div/>').text(text || '').html().replace(/&amp;/gi, '&');
  return replaceQuotes ? escapedText.replace(/"/g, '') : escapedText;
};

Utils.iconRootUrl = function (isDemo) {
  var isSafari = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/);
  if (isDemo || isInIframe() || !window.location.search || !isSafari) return '';
  return "".concat(window.location.origin).concat(window.location.pathname).concat(window.location.search);
};

Utils.svgHrefAttr = function () {
  var ua = navigator.userAgent || navigator.vendor || window.opera;
  var isSafari = /Version\/[\d\.]+.*Safari/.test(ua) || ua.indexOf('CriOS/') > -1;
  var isFacebookApp = ua.indexOf('FBAN') > -1 || ua.indexOf('FBAV') > -1;
  var isFirefoxMobile = ua.indexOf('Mozilla') > -1 && ua.indexOf('Gecko') > -1 && ua.indexOf('Mobile') > -1;
  return isSafari || isFacebookApp || isFirefoxMobile ? 'xlink:href' : 'href';
};
/*
 * JavaScript Pretty Date
 * Copyright (c) 2011 John Resig (ejohn.org)
 * Licensed under the MIT and GPL licenses.
 * http://ejohn.org/blog/javascript-pretty-date/
 */
// Takes a date object and returns a string representing how
// long ago the date represents.


Utils.prettyDate = function (date) {
  var diff = (new Date().getTime() - date.getTime()) / ONE_SECOND_IN_MILLISECONDS;
  var dayDiff = Math.floor(diff / ONE_DAY_IN_SECONDS);
  var monthDiff = Math.floor(dayDiff / ONE_MONTH_IN_DAYS);
  var yearDiff = Math.floor(monthDiff / ONE_YEAR_IN_MONTHS);
  if (isNaN(dayDiff) || dayDiff < 0) return 'Just now';
  return dayDiff === 0 && (diff < ONE_MINUTE_IN_SECONDS && 'Just now' || diff < TWO_MINUTES_IN_SECONDS && '1 minute ago' || diff < ONE_HOUR_IN_SECONDS && Math.floor(diff / ONE_MINUTE_IN_SECONDS) + ' minutes ago' || diff < TWO_HOURS_IN_SECONDS && '1 hour ago' || diff < ONE_DAY_IN_SECONDS && Math.floor(diff / ONE_HOUR_IN_SECONDS) + ' hours ago') || dayDiff === 1 && 'Yesterday' || dayDiff < ONE_WEEK_IN_DAYS && dayDiff + ' days ago' || dayDiff < ONE_MONTH_IN_DAYS && Math.ceil(dayDiff / ONE_WEEK_IN_DAYS) + ' weeks ago' || monthDiff === 1 && 'Last month' || monthDiff < ONE_YEAR_IN_MONTHS && monthDiff + ' months ago' || yearDiff === 1 && 'Last year' || yearDiff + ' years ago';
};

function toHourMinuteString(dt) {
  var includeSeconds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  var hours = dt.getHours();
  var minutes = dt.getMinutes();
  var seconds = dt.getSeconds();
  var amPM = hours >= 12 ? ' PM' : ' AM';
  var computedHours = hours == 0 ? 12 : hours > 12 ? hours - 12 : hours;
  return computedHours + ':' + (minutes < 10 ? '0' + minutes : minutes) + (includeSeconds ? ':' + (seconds < 10 ? '0' + seconds : seconds) : '') + amPM;
}

function getCookie(c_name) {
  var c_value = document.cookie;
  var c_start = c_value.indexOf(' ' + c_name + '=');

  if (c_start == -1) {
    c_start = c_value.indexOf(c_name + '=');
  }

  if (c_start == -1) {
    c_value = null;
  } else {
    c_start = c_value.indexOf('=', c_start) + 1;
    var c_end = c_value.indexOf(';', c_start);

    if (c_end == -1) {
      c_end = c_value.length;
    }

    c_value = unescape(c_value.substring(c_start, c_end));
  }

  return c_value;
}

Utils.getCookie = getCookie;
Utils.toHourMinuteString = toHourMinuteString;
/* harmony default export */ var base = (Utils);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/utils/index.js


base.setCssVars = setCssVars;
/* harmony default export */ var utils = __webpack_exports__["a"] = (base);
// CONCATENATED MODULE: ./Scripts/constants/timezones.js
/* harmony default export */ var timezones = ([{
  displayName: '(UTC-12:00) International Date Line West',
  id: 'Dateline Standard Time',
  standardName: 'Dateline Standard Time'
}, {
  displayName: '(UTC-11:00) Coordinated Universal Time-11',
  id: 'UTC-11',
  standardName: 'UTC-11'
}, {
  displayName: '(UTC-10:00) Aleutian Islands',
  id: 'Aleutian Standard Time',
  standardName: 'Aleutian Standard Time'
}, {
  displayName: '(UTC-10:00) Hawaii',
  id: 'Hawaiian Standard Time',
  standardName: 'Hawaiian Standard Time'
}, {
  displayName: '(UTC-09:30) Marquesas Islands',
  id: 'Marquesas Standard Time',
  standardName: 'Marquesas Standard Time'
}, {
  displayName: '(UTC-09:00) Alaska',
  id: 'Alaskan Standard Time',
  standardName: 'Alaskan Standard Time'
}, {
  displayName: '(UTC-09:00) Coordinated Universal Time-09',
  id: 'UTC-09',
  standardName: 'UTC-09'
}, {
  displayName: '(UTC-08:00) Baja California',
  id: 'Pacific Standard Time (Mexico)',
  standardName: 'Pacific Standard Time (Mexico)'
}, {
  displayName: '(UTC-08:00) Coordinated Universal Time-08',
  id: 'UTC-08',
  standardName: 'UTC-08'
}, {
  displayName: "(UTC-08:00) Pacific Time (US & Canada)",
  id: 'Pacific Standard Time',
  standardName: 'Pacific Standard Time'
}, {
  displayName: '(UTC-07:00) Arizona',
  id: 'US Mountain Standard Time',
  standardName: 'US Mountain Standard Time'
}, {
  displayName: '(UTC-07:00) Chihuahua, La Paz, Mazatlan',
  id: 'Mountain Standard Time (Mexico)',
  standardName: 'Mountain Standard Time (Mexico)'
}, {
  displayName: "(UTC-07:00) Mountain Time (US & Canada)",
  id: 'Mountain Standard Time',
  standardName: 'Mountain Standard Time'
}, {
  displayName: '(UTC-06:00) Central America',
  id: 'Central America Standard Time',
  standardName: 'Central America Standard Time'
}, {
  displayName: "(UTC-06:00) Central Time (US & Canada)",
  id: 'Central Standard Time',
  standardName: 'Central Standard Time'
}, {
  displayName: '(UTC-06:00) Easter Island',
  id: 'Easter Island Standard Time',
  standardName: 'Easter Island Standard Time'
}, {
  displayName: '(UTC-06:00) Guadalajara, Mexico City, Monterrey',
  id: 'Central Standard Time (Mexico)',
  standardName: 'Central Standard Time (Mexico)'
}, {
  displayName: '(UTC-06:00) Saskatchewan',
  id: 'Canada Central Standard Time',
  standardName: 'Canada Central Standard Time'
}, {
  displayName: '(UTC-05:00) Bogota, Lima, Quito, Rio Branco',
  id: 'SA Pacific Standard Time',
  standardName: 'SA Pacific Standard Time'
}, {
  displayName: '(UTC-05:00) Chetumal',
  id: 'Eastern Standard Time (Mexico)',
  standardName: 'Eastern Standard Time (Mexico)'
}, {
  displayName: "(UTC-05:00) Eastern Time (US & Canada)",
  id: 'Eastern Standard Time',
  standardName: 'Eastern Standard Time'
}, {
  displayName: '(UTC-05:00) Haiti',
  id: 'Haiti Standard Time',
  standardName: 'Haiti Standard Time'
}, {
  displayName: '(UTC-05:00) Havana',
  id: 'Cuba Standard Time',
  standardName: 'Cuba Standard Time'
}, {
  displayName: '(UTC-05:00) Indiana (East)',
  id: 'US Eastern Standard Time',
  standardName: 'US Eastern Standard Time'
}, {
  displayName: '(UTC-04:00) Asuncion',
  id: 'Paraguay Standard Time',
  standardName: 'Paraguay Standard Time'
}, {
  displayName: '(UTC-04:00) Atlantic Time (Canada)',
  id: 'Atlantic Standard Time',
  standardName: 'Atlantic Standard Time'
}, {
  displayName: '(UTC-04:00) Caracas',
  id: 'Venezuela Standard Time',
  standardName: 'Venezuela Standard Time'
}, {
  displayName: '(UTC-04:00) Cuiaba',
  id: 'Central Brazilian Standard Time',
  standardName: 'Central Brazilian Standard Time'
}, {
  displayName: '(UTC-04:00) Georgetown, La Paz, Manaus, San Juan',
  id: 'SA Western Standard Time',
  standardName: 'SA Western Standard Time'
}, {
  displayName: '(UTC-04:00) Santiago',
  id: 'Pacific SA Standard Time',
  standardName: 'Pacific SA Standard Time'
}, {
  displayName: '(UTC-04:00) Turks and Caicos',
  id: 'Turks And Caicos Standard Time',
  standardName: 'Turks and Caicos Standard Time'
}, {
  displayName: '(UTC-03:30) Newfoundland',
  id: 'Newfoundland Standard Time',
  standardName: 'Newfoundland Standard Time'
}, {
  displayName: '(UTC-03:00) Araguaina',
  id: 'Tocantins Standard Time',
  standardName: 'Tocantins Standard Time'
}, {
  displayName: '(UTC-03:00) Brasilia',
  id: 'E. South America Standard Time',
  standardName: 'E. South America Standard Time'
}, {
  displayName: '(UTC-03:00) Cayenne, Fortaleza',
  id: 'SA Eastern Standard Time',
  standardName: 'SA Eastern Standard Time'
}, {
  displayName: '(UTC-03:00) City of Buenos Aires',
  id: 'Argentina Standard Time',
  standardName: 'Argentina Standard Time'
}, {
  displayName: '(UTC-03:00) Greenland',
  id: 'Greenland Standard Time',
  standardName: 'Greenland Standard Time'
}, {
  displayName: '(UTC-03:00) Montevideo',
  id: 'Montevideo Standard Time',
  standardName: 'Montevideo Standard Time'
}, {
  displayName: '(UTC-03:00) Saint Pierre and Miquelon',
  id: 'Saint Pierre Standard Time',
  standardName: 'Saint Pierre Standard Time'
}, {
  displayName: '(UTC-03:00) Salvador',
  id: 'Bahia Standard Time',
  standardName: 'Bahia Standard Time'
}, {
  displayName: '(UTC-02:00) Coordinated Universal Time-02',
  id: 'UTC-02',
  standardName: 'UTC-02'
}, {
  displayName: '(UTC-02:00) Mid-Atlantic - Old',
  id: 'Mid-Atlantic Standard Time',
  standardName: 'Mid-Atlantic Standard Time'
}, {
  displayName: '(UTC-01:00) Azores',
  id: 'Azores Standard Time',
  standardName: 'Azores Standard Time'
}, {
  displayName: '(UTC-01:00) Cabo Verde Is.',
  id: 'Cape Verde Standard Time',
  standardName: 'Cabo Verde Standard Time'
}, {
  displayName: '(UTC) Coordinated Universal Time',
  id: 'UTC',
  standardName: 'Coordinated Universal Time'
}, {
  displayName: '(UTC+00:00) Casablanca',
  id: 'Morocco Standard Time',
  standardName: 'Morocco Standard Time'
}, {
  displayName: '(UTC+00:00) Dublin, Edinburgh, Lisbon, London',
  id: 'GMT Standard Time',
  standardName: 'GMT Standard Time'
}, {
  displayName: '(UTC+00:00) Monrovia, Reykjavik',
  id: 'Greenwich Standard Time',
  standardName: 'Greenwich Standard Time'
}, {
  displayName: '(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna',
  id: 'W. Europe Standard Time',
  standardName: 'W. Europe Standard Time'
}, {
  displayName: '(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague',
  id: 'Central Europe Standard Time',
  standardName: 'Central Europe Standard Time'
}, {
  displayName: '(UTC+01:00) Brussels, Copenhagen, Madrid, Paris',
  id: 'Romance Standard Time',
  standardName: 'Romance Standard Time'
}, {
  displayName: '(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb',
  id: 'Central European Standard Time',
  standardName: 'Central European Standard Time'
}, {
  displayName: '(UTC+01:00) West Central Africa',
  id: 'W. Central Africa Standard Time',
  standardName: 'W. Central Africa Standard Time'
}, {
  displayName: '(UTC+01:00) Windhoek',
  id: 'Namibia Standard Time',
  standardName: 'Namibia Standard Time'
}, {
  displayName: '(UTC+02:00) Amman',
  id: 'Jordan Standard Time',
  standardName: 'Jordan Standard Time'
}, {
  displayName: '(UTC+02:00) Athens, Bucharest',
  id: 'GTB Standard Time',
  standardName: 'GTB Standard Time'
}, {
  displayName: '(UTC+02:00) Beirut',
  id: 'Middle East Standard Time',
  standardName: 'Middle East Standard Time'
}, {
  displayName: '(UTC+02:00) Cairo',
  id: 'Egypt Standard Time',
  standardName: 'Egypt Standard Time'
}, {
  displayName: '(UTC+02:00) Chisinau',
  id: 'E. Europe Standard Time',
  standardName: 'E. Europe Standard Time'
}, {
  displayName: '(UTC+02:00) Damascus',
  id: 'Syria Standard Time',
  standardName: 'Syria Standard Time'
}, {
  displayName: '(UTC+02:00) Gaza, Hebron',
  id: 'West Bank Standard Time',
  standardName: 'West Bank Gaza Standard Time'
}, {
  displayName: '(UTC+02:00) Harare, Pretoria',
  id: 'South Africa Standard Time',
  standardName: 'South Africa Standard Time'
}, {
  displayName: '(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius',
  id: 'FLE Standard Time',
  standardName: 'FLE Standard Time'
}, {
  displayName: '(UTC+02:00) Jerusalem',
  id: 'Israel Standard Time',
  standardName: 'Jerusalem Standard Time'
}, {
  displayName: '(UTC+02:00) Kaliningrad',
  id: 'Kaliningrad Standard Time',
  standardName: 'Russia TZ 1 Standard Time'
}, {
  displayName: '(UTC+02:00) Tripoli',
  id: 'Libya Standard Time',
  standardName: 'Libya Standard Time'
}, {
  displayName: '(UTC+03:00) Baghdad',
  id: 'Arabic Standard Time',
  standardName: 'Arabic Standard Time'
}, {
  displayName: '(UTC+03:00) Istanbul',
  id: 'Turkey Standard Time',
  standardName: 'Turkey Standard Time'
}, {
  displayName: '(UTC+03:00) Kuwait, Riyadh',
  id: 'Arab Standard Time',
  standardName: 'Arab Standard Time'
}, {
  displayName: '(UTC+03:00) Minsk',
  id: 'Belarus Standard Time',
  standardName: 'Belarus Standard Time'
}, {
  displayName: '(UTC+03:00) Moscow, St. Petersburg, Volgograd',
  id: 'Russian Standard Time',
  standardName: 'Russia TZ 2 Standard Time'
}, {
  displayName: '(UTC+03:00) Nairobi',
  id: 'E. Africa Standard Time',
  standardName: 'E. Africa Standard Time'
}, {
  displayName: '(UTC+03:30) Tehran',
  id: 'Iran Standard Time',
  standardName: 'Iran Standard Time'
}, {
  displayName: '(UTC+04:00) Abu Dhabi, Muscat',
  id: 'Arabian Standard Time',
  standardName: 'Arabian Standard Time'
}, {
  displayName: '(UTC+04:00) Astrakhan, Ulyanovsk',
  id: 'Astrakhan Standard Time',
  standardName: 'Astrakhan Standard Time'
}, {
  displayName: '(UTC+04:00) Baku',
  id: 'Azerbaijan Standard Time',
  standardName: 'Azerbaijan Standard Time'
}, {
  displayName: '(UTC+04:00) Izhevsk, Samara',
  id: 'Russia Time Zone 3',
  standardName: 'Russia TZ 3 Standard Time'
}, {
  displayName: '(UTC+04:00) Port Louis',
  id: 'Mauritius Standard Time',
  standardName: 'Mauritius Standard Time'
}, {
  displayName: '(UTC+04:00) Tbilisi',
  id: 'Georgian Standard Time',
  standardName: 'Georgian Standard Time'
}, {
  displayName: '(UTC+04:00) Yerevan',
  id: 'Caucasus Standard Time',
  standardName: 'Caucasus Standard Time'
}, {
  displayName: '(UTC+04:30) Kabul',
  id: 'Afghanistan Standard Time',
  standardName: 'Afghanistan Standard Time'
}, {
  displayName: '(UTC+05:00) Ashgabat, Tashkent',
  id: 'West Asia Standard Time',
  standardName: 'West Asia Standard Time'
}, {
  displayName: '(UTC+05:00) Ekaterinburg',
  id: 'Ekaterinburg Standard Time',
  standardName: 'Russia TZ 4 Standard Time'
}, {
  displayName: '(UTC+05:00) Islamabad, Karachi',
  id: 'Pakistan Standard Time',
  standardName: 'Pakistan Standard Time'
}, {
  displayName: '(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi',
  id: 'India Standard Time',
  standardName: 'India Standard Time'
}, {
  displayName: '(UTC+05:30) Sri Jayawardenepura',
  id: 'Sri Lanka Standard Time',
  standardName: 'Sri Lanka Standard Time'
}, {
  displayName: '(UTC+05:45) Kathmandu',
  id: 'Nepal Standard Time',
  standardName: 'Nepal Standard Time'
}, {
  displayName: '(UTC+06:00) Astana',
  id: 'Central Asia Standard Time',
  standardName: 'Central Asia Standard Time'
}, {
  displayName: '(UTC+06:00) Dhaka',
  id: 'Bangladesh Standard Time',
  standardName: 'Bangladesh Standard Time'
}, {
  displayName: '(UTC+06:00) Omsk',
  id: 'Omsk Standard Time',
  standardName: 'Omsk Standard Time'
}, {
  displayName: '(UTC+06:30) Yangon (Rangoon)',
  id: 'Myanmar Standard Time',
  standardName: 'Myanmar Standard Time'
}, {
  displayName: '(UTC+07:00) Bangkok, Hanoi, Jakarta',
  id: 'SE Asia Standard Time',
  standardName: 'SE Asia Standard Time'
}, {
  displayName: '(UTC+07:00) Barnaul, Gorno-Altaysk',
  id: 'Altai Standard Time',
  standardName: 'Altai Standard Time'
}, {
  displayName: '(UTC+07:00) Hovd',
  id: 'W. Mongolia Standard Time',
  standardName: 'W. Mongolia Standard Time'
}, {
  displayName: '(UTC+07:00) Krasnoyarsk',
  id: 'North Asia Standard Time',
  standardName: 'Russia TZ 6 Standard Time'
}, {
  displayName: '(UTC+07:00) Novosibirsk',
  id: 'N. Central Asia Standard Time',
  standardName: 'Novosibirsk Standard Time'
}, {
  displayName: '(UTC+07:00) Tomsk',
  id: 'Tomsk Standard Time',
  standardName: 'Tomsk Standard Time'
}, {
  displayName: '(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi',
  id: 'China Standard Time',
  standardName: 'China Standard Time'
}, {
  displayName: '(UTC+08:00) Irkutsk',
  id: 'North Asia East Standard Time',
  standardName: 'Russia TZ 7 Standard Time'
}, {
  displayName: '(UTC+08:00) Kuala Lumpur, Singapore',
  id: 'Singapore Standard Time',
  standardName: 'Malay Peninsula Standard Time'
}, {
  displayName: '(UTC+08:00) Perth',
  id: 'W. Australia Standard Time',
  standardName: 'W. Australia Standard Time'
}, {
  displayName: '(UTC+08:00) Taipei',
  id: 'Taipei Standard Time',
  standardName: 'Taipei Standard Time'
}, {
  displayName: '(UTC+08:00) Ulaanbaatar',
  id: 'Ulaanbaatar Standard Time',
  standardName: 'Ulaanbaatar Standard Time'
}, {
  displayName: '(UTC+08:30) Pyongyang',
  id: 'North Korea Standard Time',
  standardName: 'North Korea Standard Time'
}, {
  displayName: '(UTC+08:45) Eucla',
  id: 'Aus Central W. Standard Time',
  standardName: 'Aus Central W. Standard Time'
}, {
  displayName: '(UTC+09:00) Chita',
  id: 'Transbaikal Standard Time',
  standardName: 'Transbaikal Standard Time'
}, {
  displayName: '(UTC+09:00) Osaka, Sapporo, Tokyo',
  id: 'Tokyo Standard Time',
  standardName: 'Tokyo Standard Time'
}, {
  displayName: '(UTC+09:00) Seoul',
  id: 'Korea Standard Time',
  standardName: 'Korea Standard Time'
}, {
  displayName: '(UTC+09:00) Yakutsk',
  id: 'Yakutsk Standard Time',
  standardName: 'Russia TZ 8 Standard Time'
}, {
  displayName: '(UTC+09:30) Adelaide',
  id: 'Cen. Australia Standard Time',
  standardName: 'Cen. Australia Standard Time'
}, {
  displayName: '(UTC+09:30) Darwin',
  id: 'AUS Central Standard Time',
  standardName: 'AUS Central Standard Time'
}, {
  displayName: '(UTC+10:00) Brisbane',
  id: 'E. Australia Standard Time',
  standardName: 'E. Australia Standard Time'
}, {
  displayName: '(UTC+10:00) Canberra, Melbourne, Sydney',
  id: 'AUS Eastern Standard Time',
  standardName: 'AUS Eastern Standard Time'
}, {
  displayName: '(UTC+10:00) Guam, Port Moresby',
  id: 'West Pacific Standard Time',
  standardName: 'West Pacific Standard Time'
}, {
  displayName: '(UTC+10:00) Hobart',
  id: 'Tasmania Standard Time',
  standardName: 'Tasmania Standard Time'
}, {
  displayName: '(UTC+10:00) Vladivostok',
  id: 'Vladivostok Standard Time',
  standardName: 'Russia TZ 9 Standard Time'
}, {
  displayName: '(UTC+10:30) Lord Howe Island',
  id: 'Lord Howe Standard Time',
  standardName: 'Lord Howe Standard Time'
}, {
  displayName: '(UTC+11:00) Bougainville Island',
  id: 'Bougainville Standard Time',
  standardName: 'Bougainville Standard Time'
}, {
  displayName: '(UTC+11:00) Chokurdakh',
  id: 'Russia Time Zone 10',
  standardName: 'Russia TZ 10 Standard Time'
}, {
  displayName: '(UTC+11:00) Magadan',
  id: 'Magadan Standard Time',
  standardName: 'Magadan Standard Time'
}, {
  displayName: '(UTC+11:00) Norfolk Island',
  id: 'Norfolk Standard Time',
  standardName: 'Norfolk Standard Time'
}, {
  displayName: '(UTC+11:00) Sakhalin',
  id: 'Sakhalin Standard Time',
  standardName: 'Sakhalin Standard Time'
}, {
  displayName: '(UTC+11:00) Solomon Is., New Caledonia',
  id: 'Central Pacific Standard Time',
  standardName: 'Central Pacific Standard Time'
}, {
  displayName: '(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky',
  id: 'Russia Time Zone 11',
  standardName: 'Russia TZ 11 Standard Time'
}, {
  displayName: '(UTC+12:00) Auckland, Wellington',
  id: 'New Zealand Standard Time',
  standardName: 'New Zealand Standard Time'
}, {
  displayName: '(UTC+12:00) Coordinated Universal Time+12',
  id: 'UTC+12',
  standardName: 'UTC+12'
}, {
  displayName: '(UTC+12:00) Fiji',
  id: 'Fiji Standard Time',
  standardName: 'Fiji Standard Time'
}, {
  displayName: '(UTC+12:00) Petropavlovsk-Kamchatsky - Old',
  id: 'Kamchatka Standard Time',
  standardName: 'Kamchatka Standard Time'
}, {
  displayName: '(UTC+12:45) Chatham Islands',
  id: 'Chatham Islands Standard Time',
  standardName: 'Chatham Islands Standard Time'
}, {
  displayName: "(UTC+13:00) Nuku'alofa",
  id: 'Tonga Standard Time',
  standardName: 'Tonga Standard Time'
}, {
  displayName: '(UTC+13:00) Samoa',
  id: 'Samoa Standard Time',
  standardName: 'Samoa Standard Time'
}, {
  displayName: '(UTC+14:00) Kiritimati Island',
  id: 'Line Islands Standard Time',
  standardName: 'Line Islands Standard Time'
}]);
// CONCATENATED MODULE: ./Scripts/constants/index.js
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ActivityTypesEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return CannedResponseTypesEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return DateDisplayFormatsEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return DateRangeEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return IntegrationTypesEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return OnboardingStepsEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return OnboardingStepStatusesEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return RolesEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return WebsiteAssignmentTypesEnum; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return WidgetTypesEnum; });
/* unused harmony export ExpandWidgetTimeoutTypesEnum */
/* unused harmony export MobileDisplayTypesEnum */
/* unused harmony export WidgetPositionsEnum */
/* unused harmony export WidgetStatusEnum */
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return DeviceType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return RoomType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return ChatRecordType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return UploadStatuses; });
/* unused harmony export UploadErrorMessages */
/* concated harmony reexport Timezones */__webpack_require__.d(__webpack_exports__, "l", function() { return timezones; });
var ActivityTypesEnum = {
  PageView: 1,
  LiveChat: 2,
  Email: 3
};
var CannedResponseTypesEnum = {
  Private: 1,
  Public: 2
};
var DateDisplayFormatsEnum = {
  MonthDayYear: 0,
  DayMonthYear: 1,
  YearMonthDay: 2
};
var DateRangeEnum = {
  Today: 0,
  Yesterday: 1,
  Past7: 2,
  Past30: 3,
  PastYear: 4,
  AllTime: 5,
  CustomDate: 6,
  CustomRange: 7,
  stringify: function stringify(range, startDate, endDate) {
    switch (range) {
      case DateRangeEnum.Today:
        return 'today';

      case DateRangeEnum.Yesterday:
        return 'yesterday';

      case DateRangeEnum.Past7:
        return 'past 7 days';

      case DateRangeEnum.Past30:
        return 'past 30 days';

      case DateRangeEnum.PastYear:
        return 'past year';

      case DateRangeEnum.AllTime:
        return 'all time';

      case DateRangeEnum.CustomDate:
        return startDate;

      case DateRangeEnum.CustomRange:
      default:
        return "".concat(startDate, " to ").concat(endDate);
    }
  }
};
var IntegrationTypesEnum = {
  Generic: 0,
  Infusionsoft: 1,
  Apptivo: 3,
  Weebly: 5,
  Wordpress: 6,
  Shopify: 7,
  Zapier: 8,
  HubSpot: 9
};
var OnboardingStepsEnum = {
  SignUp: 1,
  InstallWidget: 2,
  GetMobile: 3,
  AddTeam: 4,
  CustomizeWidget: 5,
  DemoChat: 6,
  Visitors: 7,
  ChoosePlan: 8,
  StartTrial: 9
};
var OnboardingStepStatusesEnum = {
  Incomplete: 1,
  Complete: 2,
  Skipped: 3,
  Viewed: 4
};
var RolesEnum = {
  Administrator: 'Administrator',
  Operator: 'Operator',
  SystemAdministrator: 'System Administrator',
  Support: 'Support',
  PowerUser: 'Power User'
};
var WebsiteAssignmentTypesEnum = {
  All: 1,
  Specific: 2
};
var WidgetTypesEnum = {
  Basic: 1,
  Personal: 2
};
var ExpandWidgetTimeoutTypesEnum = {
  SiteWide: 1,
  SinglePage: 2
};
var MobileDisplayTypesEnum = {
  Hidden: 0,
  SameAsDesktop: 1,
  MobileOptimized: 2
};
var WidgetPositionsEnum = {
  BottomLeft: 1,
  BottomRight: 2,
  TopLeft: 3,
  TopRight: 4
};
var WidgetStatusEnum = {
  Active: 0,
  Deleted: 1,
  Disabled: 2
};
var DeviceType = {
  Desktop: 0,
  Ios: 1
};
var RoomType = {
  Account: 0,
  Operator: 1,
  Visitor: 2
};
var ChatRecordType = {
  Message: 0,
  Join: 1,
  Leave: 2,
  Close: 3,
  File: 4
};
var UploadStatuses = {
  Start: 0,
  Uploading: 1,
  Unauthorized: 2,
  Error: 3,
  Complete: 4
};
var UploadErrorMessages = {
  default: 'File Send Failed',
  401: 'You are not authorized to upload.',
  413: 'This file is too large. 10MB Limit.',
  415: 'This file type is not supported.'
};

// EXTERNAL MODULE: ../node_modules/jquery/src/jquery.js
var jquery = __webpack_require__(0);
var jquery_default = /*#__PURE__*/__webpack_require__.n(jquery);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// EXTERNAL MODULE: ../node_modules/underscore-template-loader!./Scripts/widgets/legacy/templates/emoji_picker.html
var emoji_picker = __webpack_require__(651);
var emoji_picker_default = /*#__PURE__*/__webpack_require__.n(emoji_picker);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/views/emoji_list.view.js + 1 modules
var emoji_list_view = __webpack_require__(302);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/models/emojis.collection.js + 1 modules
var emojis_collection = __webpack_require__(217);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/emojis.json
var emojis = __webpack_require__(204);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/most_used_emojis.collection.js



var NUM_EMOJI_SLOTS = 10;
var CURATED_EMOJIS = '👍,👎,🙂,😄,😂,🎉,❤️,👏,✅,💥';
var LOCAL_STORAGE_KEY = 'purechat_emojis';
var MostUsedEmojisCollection = emojis_collection["a" /* default */].extend({
  addSelected: function addSelected(model) {
    var found = this.findWhere({
      emoji: model.get('emoji')
    });

    if (found) {
      this.moveModel(found);
    } else {
      this.insertModel(model);
    }
  },
  moveModel: function moveModel(model) {
    var clicked = (model.get('clicked') || 0) + 1;
    var modelIndex = this.indexOf(model);
    var prevIndex = modelIndex - 1;

    while (prevIndex > -1) {
      var prev = this.at(prevIndex);

      if (prev.get('clicked') > clicked) {
        break;
      }

      this.remove(model);
      this.add(model, {
        at: prevIndex
      });
      prevIndex -= 1;
    }

    model.save({
      clicked: clicked
    });
  },
  insertModel: function insertModel(model) {
    var cloned = model.clone();
    var i = 0;
    var len = this.length;
    var clicked = (model.get('clicked') || 0) + 1;

    for (i; i < len; i += 1) {
      if (clicked >= this.at(i).get('clicked')) {
        break;
      }
    }

    cloned.set({
      clicked: clicked
    });
    this.add(cloned, {
      at: i
    });
    cloned.save(); // Remove the last item in the list with destroy so that it triggers a sync.

    this.last().destroy();
  },
  sync: function sync(method, model, options) {
    var resp = new Array(NUM_EMOJI_SLOTS).map(function () {
      return null;
    });
    var errorMessage;
    var dfr = jquery_default.a.Deferred();

    try {
      var mostUsedEmojisStr = window.localStorage.getItem(LOCAL_STORAGE_KEY) || CURATED_EMOJIS;
      var mostUsedEmojis = mostUsedEmojisStr.split(',');

      switch (method) {
        case 'read':
          (function () {
            var found = 0;
            var i = 0;
            var len = emojis.length;

            for (i; i < len; i += 1) {
              var emoji = emojis[i];
              var pos = mostUsedEmojis.indexOf(emoji.emoji);

              if (pos > -1) {
                resp[pos] = emoji;
                found += 1;
              } // stop when 10 emojis are found for efficiency


              if (found === NUM_EMOJI_SLOTS) break;
            }
          })();

          break;

        case 'delete':
          mostUsedEmojis.splice(mostUsedEmojis.indexOf(model.get('emoji')), 1);
          window.localStorage.setItem(LOCAL_STORAGE_KEY, mostUsedEmojis.join(','));
          break;

        case 'update':
          window.localStorage.setItem(LOCAL_STORAGE_KEY, this.map(function (emoji) {
            return emoji.get('emoji');
          }).join(','));
          break;
      }
    } catch (error) {
      errorMessage = error.message;
    }

    if (resp) {
      if (options.success) {
        options.success.call(model, resp, options);
      }

      dfr.resolve(resp);
    } else {
      errorMessage = errorMessage ? errorMessage : 'Record Not Found';

      if (options.error) {
        options.error.call(model, errorMessage, options);
      }

      dfr.reject(errorMessage);
    } // add compatibility with $.ajax
    // always execute callback for success and error


    if (options.complete) {
      options.complete.call(model, resp);
    }

    return dfr.promise();
  },
  save: function save() {
    return this.sync('create', this, {});
  }
});
/* harmony default export */ var most_used_emojis_collection = (MostUsedEmojisCollection);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/emoji_picker.view.js







var EmojiPickerView = no_conflict["b" /* Marionette */].LayoutView.extend({
  template: emoji_picker_default.a,
  className: 'purechat-emoji-picker purechat-card purechat-card-flex purechat-display-none',
  ui: {
    searchInput: 'input'
  },
  events: {
    'keyup @ui.searchInput': 'search',
    'click': function click(e) {
      e.preventDefault();
      e.stopPropagation();
    }
  },
  regions: {
    curatedList: '.purechat-curated-emojis',
    fullList: '.purechat-all-emojis'
  },
  childEvents: {
    emojiSelected: function emojiSelected(view, model) {
      this.triggerMethod('emojiSelected', model);
      this.mostUsedCollection.addSelected(model);
    }
  },
  initialize: function initialize() {
    this.mostUsedCollection = new most_used_emojis_collection();
    this.fullListCollection = new emojis_collection["a" /* default */](emojis);
    this.mostUsedCollection.fetch();
  },
  onBeforeShow: function onBeforeShow() {
    this.showChildView('curatedList', new emoji_list_view["a" /* default */]({
      collection: this.mostUsedCollection
    }));
    this.showChildView('fullList', new emoji_list_view["a" /* default */]({
      collection: this.fullListCollection
    }));
  },
  open: function open() {
    this.$el.purechatDisplay('flex');
    this.ui.searchInput.focus();
    this.registerEmojiCloseClickHandler();
  },
  close: function close() {
    this.$el.purechatDisplay('none');
    this.ui.searchInput.val('');
    this.search();
    jquery_default()(window).off('.purechat-emojis');
  },
  search: function search() {
    var value = this.ui.searchInput.val();
    this.fullListCollection.each(function (model) {
      if (value === '') {
        model.set('filtered', false);
      } else {
        var nameMatches = model.get('names').some(function (name) {
          return name.indexOf(value) > -1;
        });
        var tagMatches = model.get('tags').some(function (tag) {
          return tag.indexOf(value) > -1;
        });
        model.set('filtered', !(nameMatches || tagMatches));
      }
    });
  },
  registerEmojiCloseClickHandler: function registerEmojiCloseClickHandler() {
    var _this = this;

    if (!this.getOption('registerClose')) return;
    jquery_default()(window).on('click.purechat-emojis', function () {
      _this.close();
    });
  }
});
/* harmony default export */ var emoji_picker_view = __webpack_exports__["a"] = (EmojiPickerView);
// EXTERNAL MODULE: ../node_modules/jquery/src/jquery.js
var jquery = __webpack_require__(0);
var jquery_default = /*#__PURE__*/__webpack_require__.n(jquery);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// EXTERNAL MODULE: ./Scripts/config/config.production.js
var config_production = __webpack_require__(11);
var config_production_default = /*#__PURE__*/__webpack_require__.n(config_production);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/services/base_data.js + 1 modules
var base_data = __webpack_require__(319);

// EXTERNAL MODULE: ./Scripts/chatserverclient/index.js + 1 modules
var chatserverclient = __webpack_require__(613);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/constants.js
var constants = __webpack_require__(4);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/models/message.model.js
var message_model = __webpack_require__(157);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/services/data_singleton.js
var data_singleton = __webpack_require__(116);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/file_message.model.js
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }





 // https://en.wikipedia.org/wiki/Kilobyte#1024_bytesc

var ONE_KIBI = 1024;
var ONE_MEBI = 1048576; // 1024*1024

var HTTP_UNAUTHORIZED = 401;
var FileMessageModel = message_model["a" /* default */].extend({
  url: "".concat(config_production_default.a.filesRootUrl, "/api/files"),
  defaults: {
    type: constants["a" /* default */].MessageTypes.File,
    file: null,
    myMessage: null,
    isClosedChat: null
  },
  save: function save(successCallback, errorCallback) {
    var _this = this;

    var file = this.get('file');
    return jquery_default.a.ajax(_objectSpread({
      type: 'POST',
      url: this.url,
      data: JSON.stringify({
        fileName: encodeURI(file.name),
        byteCount: file.size,
        accountId: 0,
        context: this.get('context'),
        fileType: this.get('fileType'),
        contentType: file.type
      }),
      contentType: 'application/json',
      crossDomain: true,
      xhrFields: {
        withCredentials: true
      }
    }, this.get('isOperator') ? {} : {
      headers: {
        authToken: this.get('authToken')
      }
    }, {
      error: function error(err) {
        return _this.setErrorStatus(err, errorCallback);
      },
      success: function success(authResponse) {
        _this.set({
          fileUsageId: authResponse.fileUsageId,
          fileUrl: authResponse.uploadUrl,
          downloadUrl: authResponse.downloadUrl
        });

        jquery_default.a.ajax({
          type: 'PUT',
          url: _this.get('fileUrl'),
          data: _this.get('file'),
          processData: false,
          contentType: file.type,
          xhrFields: {
            withCredentials: false
          },
          success: function success() {
            return successCallback();
          },
          error: function error(err) {
            return _this.setErrorStatus(err, errorCallback);
          }
        });
      }
    }));
  },
  finalize: function finalize() {
    var _this2 = this;

    return jquery_default.a.ajax({
      type: 'POST',
      url: "".concat(this.url, "/finalize/").concat(this.get('fileUsageId')),
      data: JSON.stringify({
        context: {
          chatRecordId: this.get('serverId')
        }
      }),
      contentType: 'application/json',
      crossDomain: true,
      xhrFields: {
        withCredentials: true
      }
    }).then(function () {
      return _this2.set('status', constants["a" /* default */].UploadStatuses.Complete);
    }).fail(function (err) {
      return _this2.setErrorStatus(err);
    });
  },
  updateContext: function updateContext() {
    return jquery_default.a.ajax({
      type: 'POST',
      url: "".concat(this.url, "/context/").concat(this.get('fileUsageId')),
      data: JSON.stringify({
        context: {
          chatRecordId: this.get('serverId')
        }
      }),
      contentType: 'application/json',
      crossDomain: true,
      xhrFields: {
        withCredentials: true
      }
    });
  },
  setErrorStatus: function setErrorStatus(err, callback) {
    var _this3 = this;

    var dataController = data_singleton["a" /* default */].getInstance();
    return dataController.getWidgetSettings().then(function (settings) {
      _this3.set({
        message: settings.resources.error_fileTransfer || constants["a" /* default */].UploadErrorMessages[err.status] || constants["a" /* default */].UploadErrorMessages.default,
        status: err.status === HTTP_UNAUTHORIZED ? constants["a" /* default */].UploadStatuses.Unauthorized : constants["a" /* default */].UploadStatuses.Error
      });

      if (callback) callback();
    });
  },
  getSize: function getSize() {
    var size = this.get('file').size;
    if (size <= ONE_KIBI) return '1KB';
    if (size < ONE_MEBI) return "".concat(Math.floor(size / ONE_KIBI), "KB");
    return "".concat(Math.floor(size / ONE_MEBI), "MB");
  }
});
/* harmony default export */ var file_message_model = (FileMessageModel);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/utils/index.js + 2 modules
var utils = __webpack_require__(15);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/utils/logger.js
var logger = __webpack_require__(61);

// EXTERNAL MODULE: ./Scripts/constants/index.js + 1 modules
var Scripts_constants = __webpack_require__(25);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/services/pc_data.js
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }

function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

/* global VERSION_NUM */










var TWENTY_MINUTES = 1200000;
var CHAT_FILE_USAGE_TYPE = 0;
var PROXY_AUTH_HTTP_STATUS = 407;
var CHECK_CHAT_AVAILABLE_CACHE_PERIOD = 3000;

var pc_data_PCDataController =
/*#__PURE__*/
function (_BaseDataController) {
  _inherits(PCDataController, _BaseDataController);

  function PCDataController() {
    _classCallCheck(this, PCDataController);

    return _possibleConstructorReturn(this, _getPrototypeOf(PCDataController).apply(this, arguments));
  }

  _createClass(PCDataController, [{
    key: "timeStampUrl",
    value: function timeStampUrl(url) {
      var now = new Date().getTime();
      return url.indexOf('?') > -1 ? "".concat(url, "&t=").concat(now) : "".concat(url, "?t=").concat(now);
    }
  }, {
    key: "closeChat",
    value: function closeChat(args) {
      this.chatServerConnection.destroyself(this.connectionInfo.get('roomId'), this.connectionInfo.get('roomType'), args);
      return jquery_default.a.Deferred().resolve();
    }
  }, {
    key: "leaveChat",
    value: function leaveChat() {
      this.chatServerConnection.leave(this.connectionInfo.get('roomId'), this.connectionInfo.get('roomType'));
      return jquery_default.a.Deferred().resolve();
    }
  }, {
    key: "restartChat",
    value: function restartChat() {
      this.connectionInfo.clearLocalStorage();
      return jquery_default.a.Deferred().resolve();
    }
  }, {
    key: "newMessage",
    value: function newMessage(message) {
      if (jquery_default.a.trim(message) === '') return;
      this.chatServerConnection.sendmessage(message, this.connectionInfo.get('roomId'), this.connectionInfo.get('roomType'));
    }
  }, {
    key: "deleteMessage",
    value: function deleteMessage(message) {
      this.chatServerConnection.deleteMessage({
        roomId: this.connectionInfo.get('roomId'),
        roomType: this.connectionInfo.get('roomType'),
        message: message
      });
    }
  }, {
    key: "upload",
    value: function upload(file, roomId, roomType) {
      var _this = this;

      var authToken = this.connectionInfo.get('authToken');
      var isOperator = this.getOption('isOperator');
      var fileMessage = new file_message_model({
        date: new Date(),
        myMessage: true,
        isClosedChat: false,
        file: file,
        status: constants["a" /* default */].UploadStatuses.Start,
        fileType: CHAT_FILE_USAGE_TYPE,
        context: {
          chatId: this.connectionInfo.get('roomId')
        },
        authToken: authToken,
        isOperator: isOperator
      });
      this.chatServerConnection.upload({
        roomId: roomId || this.connectionInfo.get('roomId'),
        roomType: roomType || this.connectionInfo.get('roomType'),
        status: fileMessage.get('status'),
        messageId: fileMessage.get('messageId')
      }, function (ack, response, httpStatus) {
        if (!ack) {
          var errStatus = httpStatus === PROXY_AUTH_HTTP_STATUS ? constants["a" /* default */].UploadStatuses.Unauthorized : constants["a" /* default */].UploadStatuses.Error;
          fileMessage.set({
            status: errStatus,
            message: constants["a" /* default */].UploadErrorMessages[httpStatus] || constants["a" /* default */].UploadErrorMessages.default
          });
          return;
        }

        fileMessage.set({
          messageId: response.messageId,
          status: constants["a" /* default */].UploadStatuses.Uploading
        });
        fileMessage.save( // Success handler
        function () {
          if (fileMessage.get('status') !== constants["a" /* default */].UploadStatuses.Error && fileMessage.get('status') !== constants["a" /* default */].UploadStatuses.Unauthorized) {
            fileMessage.finalize().then(function () {
              var msg = fileMessage.get('status') === constants["a" /* default */].UploadStatuses.Complete ? "".concat(file.name, "(").concat(fileMessage.get('downloadUrl'), ")\n").concat(fileMessage.getSize(), " \u2022 ").concat(file.type) : fileMessage.get('message');

              _this.chatServerConnection.upload({
                roomId: roomId || _this.connectionInfo.get('roomId'),
                roomType: roomType || _this.connectionInfo.get('roomType'),
                status: fileMessage.get('status'),
                messageId: fileMessage.get('messageId'),
                message: msg
              }, function (ack2, response2) {
                if (!ack2) return;

                if (fileMessage.get('status') !== constants["a" /* default */].UploadStatuses.Error && fileMessage.get('status') !== constants["a" /* default */].UploadStatuses.Unauthorized) {
                  fileMessage.set({
                    serverId: response2.serverId
                  });
                  fileMessage.updateContext();
                }
              });
            });
          }
        }, // On error, let chat server know of the change
        function () {
          _this.chatServerConnection.upload({
            roomId: roomId || _this.connectionInfo.get('roomId'),
            roomType: roomType || _this.connectionInfo.get('roomType'),
            status: fileMessage.get('status'),
            messageId: fileMessage.get('messageId'),
            message: fileMessage.get('message')
          });
        });
      });
    }
  }, {
    key: "getReasonFromResponse",
    value: function getReasonFromResponse(reason) {
      return reason == 1 ? 'Available' : reason == 2 ? 'NoOperators' : reason == 3 ? 'ServerDowntime' : reason == 4 ? 'AccountActivity' : reason == 5 ? 'ChatQuotaExceeded' : reason == 6 ? 'WidgetDisabled' : reason == 7 ? 'IpIsbanned' : '';
    }
  }, {
    key: "checkChatAvailable",
    value: function checkChatAvailable(accountId) {
      var _this2 = this;

      var badBrowser = false;
      accountId = accountId || this.widgetSettings.accountId;

      if (!window._checkChatAvailableDeferred || window._checkChatAvailableDeferred.state() === 'resolved') {
        window._checkChatAvailableDeferred = jquery_default.a.Deferred(); // Check if we have availability cached recently. 

        if (this.checkChatAvailableResultCache) {
          window._checkChatAvailableDeferred.resolve(this.checkChatAvailableResultCache);
        } else {
          // Listen for the chat available deferred and cache the result.
          window._checkChatAvailableDeferred.done(function (checkChatAvailableResultCache) {
            _this2.checkChatAvailableResultCache = checkChatAvailableResultCache;
            setTimeout(function () {
              _this2.checkChatAvailableResultCache = null;
            }, CHECK_CHAT_AVAILABLE_CACHE_PERIOD);
          });

          if (!badBrowser) {
            var urlOptions = {
              accountId: accountId,
              widgetId: this.options ? this.options.connectionSettings && this.options.connectionSettings.c ? this.options.connectionSettings.c : this.options.widgetId || this.options.Id : null
            };
            var url = config_production_default.a.widgetApiRootUrl + '/api/VisitorWidget/ChatAvailable/' + urlOptions.accountId + '/' + urlOptions.widgetId + '/?externalRequest=false';
            jquery_default.a.ajax({
              // This is really stupid, but if it works, then I guess ios devices need SUPER cachebusting urls :/
              url: this.timeStampUrl(url),
              type: 'GET',
              timeout: 20000,
              error: function error() {
                window._checkChatAvailableDeferred.resolve({
                  available: false,
                  reason: 0
                });
              },
              success: function success(response) {
                window._checkChatAvailableDeferred.resolve({
                  available: response.a == 1,
                  reason: _this2.getReasonFromResponse(response.r)
                });

                window._checkChatAvailableDeferred = null;
              }
            });
          } else {
            window._checkChatAvailableDeferred.resolve({
              a: 0,
              r: 2
            });
          }
        }
      }

      return window._checkChatAvailableDeferred.promise();
    }
  }, {
    key: "getDashboardVersion",
    value: function getDashboardVersion() {
      return jquery_default.a.ajax({
        url: "".concat(this.getOption('pureServerUrl'), "/version"),
        dataType: 'jsonp',
        timeout: 20000,
        jsonpCallback: '_WidgetJPCB_Version'
      });
    }
  }, {
    key: "getWidgetSettings",
    value: function getWidgetSettings() {
      var _this3 = this;

      var d = jquery_default.a.Deferred();
      var hasAllSettings = typeof this.getOption('hasAllSettings') === 'boolean' ? this.getOption('hasAllSettings') : false;

      if (!hasAllSettings) {
        jquery_default.a.when(this.getDashboardVersion(), jquery_default.a.ajax({
          url: "".concat(config_production_default.a.widgetApiRootUrl, "/api/VisitorWidget/Widget/").concat(this.getOption('widgetId'), "/").concat(new Date().getTime()),
          timeout: 20000
        })).done(function (dashboardResponse, widgetResponse) {
          var dashboardVersion = dashboardResponse[0].v;
          var response = widgetResponse[0];

          if (response.Valid) {
            // We don't want the hide widget behavior if its a hosted page.
            if (response.UnavailableBehavior === 0 && _this3.options.isDirectAccess) {
              response.UnavailableBehavior = 1;
            }

            response.UserWidgetSettings = new no_conflict["a" /* Backbone */].Model(response.UserWidgetSettings); // we got the widget info ok - render the widget and advance to the next state

            var widgetSettings = {
              success: true,
              version: dashboardVersion,
              accountId: response.AccountId,
              color: response.Color,
              position: response.Position,
              widgetType: response.WidgetType,
              widgetConfig: response,
              resources: response.StringResources,
              googleAnalytics: response.GoogleAnalytics,
              chatServerUrl: response.ChatServerUrl,
              userWidgetConfig: response.UserWidgetSettings
            };
            d.resolve(widgetSettings);
          }
        }).fail(function () {
          return d.reject();
        });
      } else {
        d.resolve({
          success: true,
          version: this.getOption('Version'),
          accountId: this.getOption('AccountId'),
          color: this.getOption('Color'),
          position: this.getOption('Position'),
          widgetType: this.getOption('WidgetType'),
          widgetConfig: this.options,
          resources: this.getOption('StringResources'),
          googleAnalytics: this.getOption('GoogleAnalytics'),
          chatServerUrl: this.getOption('ChatServerUrl'),
          userWidgetConfig: this.getOption('UserWidgetSettings')
        });
      }

      return d.promise();
    }
  }, {
    key: "submitEmailForm",
    value: function submitEmailForm(data) {
      var _this4 = this;

      var d = jquery_default.a.Deferred();
      var i = null;
      var s = null;

      try {
        i = this.cleanNulls(window.localStorage.getItem('i'));

        if (this.isActiveSession()) {
          s = this.cleanNulls(window.localStorage.getItem(this.getSessionItemName()));
        }
      } catch (e) {
        /* Do Nothing */
      }

      data.widgetId = this.getOption('widgetId');
      data.startPage = data.origin || window.location.toString() || 'unknown';
      data.acquisitionSource = window.localStorage.acquisitionSource || 'Direct';
      data.pccId = i;
      data.pccsId = s;
      jquery_default.a.ajax({
        url: this.getOption('apiServerUrl') + '/api/VisitorWidget/SendEmail',
        type: 'POST',
        data: data
      }).done(function (result) {
        try {
          if (result.customerId) {
            window.localStorage.setItem('i', result.customerId);
          }

          _this4.connectionInfo.set('hasHadEmail', true);

          _this4.connectionInfo.persistLocalStorage();

          utils["a" /* default */].GaEvent(new no_conflict["a" /* Backbone */].Model(_this4.widgetSettings.widgetConfig), 'GaTrackingEmail', 'GAEmailEvent');
        } catch (e) {
          return d.reject(e);
        }

        return d.resolve(result);
      }).fail(function () {
        return d.reject();
      });
      return d.promise();
    }
  }, {
    key: "cleanNulls",
    value: function cleanNulls(val) {
      //there was a bug out there for awhile and some of the ids where set to null
      //so lets clean.
      if (val === 'null') return undefined;
      if (val === null) return undefined;
      return val;
    }
  }, {
    key: "getSessionItemName",
    value: function getSessionItemName() {
      return 's_' + this.widgetSettings.accountId;
    }
  }, {
    key: "getLastCheckinItemName",
    value: function getLastCheckinItemName() {
      return 'lastCheckin_' + this.widgetSettings.accountId;
    }
  }, {
    key: "isActiveSession",
    value: function isActiveSession() {
      var now = Date.now();
      var lastCheckinItemName = this.getLastCheckinItemName();
      var lastCheckin = this.cleanNulls(window.localStorage.getItem(lastCheckinItemName));
      if (lastCheckin && now - lastCheckin >= this.sessionTimeout) return false;
      return true;
    }
  }, {
    key: "getContactId",
    value: function getContactId() {
      try {
        return this.cleanNulls(window.localStorage.getItem('i'));
      } catch (e) {
        return null;
      }
    }
  }, {
    key: "getSessionId",
    value: function getSessionId() {
      var sessionId = null;

      try {
        if (this.isActiveSession()) {
          sessionId = this.cleanNulls(window.localStorage.getItem(this.getSessionItemName()));
        }
      } catch (e) {
        /* Do Nothing */
      }

      return sessionId;
    }
  }, {
    key: "startChat",
    value: function startChat(data) {
      var self = this;
      var d = jquery_default.a.Deferred();
      var i = this.getContactId();
      var s = this.getSessionId(); // Escape the user's display name so that their xss attempts won't affect themselves and
      // so that the Pure Serer won't get mad over a "potentially dangerous querystring value" if they include
      // a bracket or something

      var escapedUserDisplayName = data.visitorName;
      var escapedUserDisplayFirstName = data.visitorFirstName;
      var escapedUserDisplayLastName = data.visitorLastName;
      var escapedUserDisplayCompany = data.visitorCompany;
      var url = this.getOption('apiServerUrl') + '/VisitorWidget/Chat/' + this.getOption('widgetId') + '?visitorName=' + encodeURIComponent(escapedUserDisplayName || '') + '&visitorFirstName=' + encodeURIComponent(escapedUserDisplayFirstName || '') + '&visitorLastName=' + encodeURIComponent(escapedUserDisplayLastName || '') + '&visitorCompany=' + encodeURIComponent(escapedUserDisplayCompany || '') + '&origin=' + encodeURIComponent(data.origin || window.location.toString() || 'unknown') + '&expandSource=' + (window.localStorage.getItem('expandSource') || '') + '&acquisitionSource=' + (localStorage.acquisitionSource || 'Direct') + '&operatorJoinIds=' + encodeURIComponent((data.operatorJoinIds || []).join(',')) + '&initiator=' + encodeURIComponent(data.initiator || '') + '&startedByOperator=' + (data.startedByOperator || false).toString() + '&pccid=' + i + '&pccsid=' + s + '&hubspotUtk=' + utils["a" /* default */].getCookie(constants["a" /* default */].HubspotCookieName) + '&sentChatRequest=' + (this.sentChatRequest || false).toString();

      if (data.visitorEmail) {
        url += '&visitorEmail=' + encodeURIComponent(data.visitorEmail);
      }

      if (data.visitorPhoneNumber) {
        url += '&visitorPhoneNumber=' + encodeURIComponent(data.visitorPhoneNumber);
      }

      if (data.visitorQuestion && data.initiator != 1) {
        //shouldn't send question if started by operator.
        url += '&visitorQuestion=' + encodeURIComponent(data.visitorQuestion);
      }

      if (!this.sentChatRequest) {
        this.sentChatRequest = true;
      }

      var widgetId = this.getOption('widgetId');
      var accountId = this.getOption('AccountId');
      jquery_default.a.ajax({
        url: url,
        dataType: 'jsonp',
        timeout: 20000,
        success: function success(response) {
          if (response.user && response.room) {
            var chatId = response.room.id;
            logger["a" /* default */].log(logger["a" /* default */].LEVELS.DEBUG, "Start chat success, WidgetId: ".concat(widgetId, ", ChatId: ").concat(chatId, ", AccountId: ").concat(accountId), '', false, response.server.url, '');

            try {
              if (response.customerId) {
                localStorage.setItem('i', response.customerId);
              }
            } catch (e) {//do nothing?
            }

            self.connectionInfo.set({
              userId: response.user.id,
              authToken: response.user.authToken,
              roomId: response.room.id,
              roomType: Scripts_constants["k" /* RoomType */].Visitor,
              chatId: response.chat.id,
              chatClosed: false,
              chatServerUrl: response.server.url,
              chatServerVersion: response.server.version,
              hasHadChat: true
            });
            d.resolve(self.connectionInfo);
          } else {
            if (typeof connectingView !== 'undefined' && connectingView !== null) {
              connectingView.showErrorMessage(response.message);
            }

            d.reject(response.message);
          }

          d.resolve();
        },
        error: function error(xhr, textStatus, _error) {
          d.reject(textStatus + ', ' + _error);
          logger["a" /* default */].log(logger["a" /* default */].LEVELS.ERROR, "Start chat failed: Account: ".concat(accountId, " -- Widget: ").concat(widgetId, " -- ").concat(textStatus, " -- ").concat(_error));
        },
        complete: function complete() {
          // Use setTimeout to let all of the listeners in the event loop run
          // prior to removing this flag
          setTimeout(function () {
            self.sentChatRequest = false;
          }, 0);
        }
      });
      return d;
    }
  }, {
    key: "connectToChatServer",
    value: function connectToChatServer(bindTo) {
      var d = jquery_default.a.Deferred();
      var accountId = this.widgetSettings.accountId;
      var widgetId = this.options.widgetId;
      var roomId = this.connectionInfo.get('roomId');
      var socketConnected = false;
      var chatServerUrl = this.connectionInfo.get('chatServerUrl'); // Connect to the chat server with the credentials we recieved from the web server

      function onIdentify(success, response, errorCode, errorMessage) {
        socketConnected = true;

        if (!success) {
          logger["a" /* default */].log(logger["a" /* default */].LEVELS.ERROR, "Failed to identify with chat server, WidgetId: ".concat(widgetId, ", ChatId: ").concat(roomId, ", AccountId: ").concat(accountId, ", Version: ").concat(110140, ", Error Code: ").concat(errorCode, ", ErrorMsg: ").concat(errorMessage), '', false, chatServerUrl, '');
          d.reject({
            response: response,
            errorCode: errorCode,
            errorMessage: errorMessage
          });
        } else {
          logger["a" /* default */].log(logger["a" /* default */].LEVELS.DEBUG, "Successfully identified with chat server, WidgetId: ".concat(widgetId, ", ChatId: ").concat(roomId, ", AccountId: ").concat(accountId, ", Version: ").concat(110140), '', false, chatServerUrl, ''); // Now switch to the chatting state

          d.resolve();
        }
      } // socket IO will not reconnect after a successful connect (e.g., when we connect, then use bad identify creds from a cookie, then try to reconnect)
      // so we have to keep the old connection and just identify instead of trying to reconnect


      if (!this.chatServerConnection || this.chatServerConnection.socket.disconnected) {
        this.chatServerConnection = chatserverclient["a" /* default */].getInstance(this.connectionInfo.get('chatServerVersion'), "".concat(chatServerUrl, "/client"), this.connectionInfo.get('userId'), accountId, this.connectionInfo.get('authToken'), onIdentify, function (response) {
          if (!socketConnected) {
            d.reject(response);
          }
        }, null, typeof this.options.connectionSettings.poppedOut === 'boolean' ? this.options.connectionSettings.poppedOut : false, this.options.isOperator);

        if (bindTo) {
          this.bindEvents(bindTo);
        }
      } else {
        this.chatServerConnection.identify(this.connectionInfo.get('userId'), accountId, this.connectionInfo.get('authToken'), onIdentify, typeof this.options.connectionSettings.poppedOut === 'boolean' ? this.options.connectionSettings.poppedOut : false);

        if (bindTo) {
          this.bindEvents(bindTo);
        }
      }

      return d;
    }
  }, {
    key: "setTypingIndicator",
    value: function setTypingIndicator(isTyping) {
      this.chatServerConnection.sendtyping(this.connectionInfo.get('roomId'), this.connectionInfo.get('roomType'), isTyping);
    }
  }, {
    key: "rateChat",
    value: function rateChat(rate) {
      return jquery_default.a.ajax({
        url: "".concat(this.getOption('apiServerUrl'), "/api/VisitorWidget/Rate"),
        method: "POST",
        data: {
          chatId: this.connectionInfo.get('chatId'),
          rating: rate,
          authToken: this.connectionInfo.get('authToken')
        }
      });
    }
  }, {
    key: "checkInRoom",
    value: function checkInRoom() {
      return this.connectionInfo.isInChat() || this.connectionInfo.loadFromLocalStorage().isInChat();
    }
  }, {
    key: "setCurrentPage",
    value: function setCurrentPage(page) {
      this.chatServerConnection.setVisitorDetails(this.connectionInfo.get('roomId'), this.connectionInfo.get('roomType'), {
        visitorReferer: page
      });
    }
  }, {
    key: "sendRoomHistory",
    value: function sendRoomHistory() {
      this.chatServerConnection.sendroomhistory(this.connectionInfo.get('roomId'), this.connectionInfo.get('roomType'));
    }
  }, {
    key: "unbindHandlerEvents",
    value: function unbindHandlerEvents() {
      _get(_getPrototypeOf(PCDataController.prototype), "unbindHandlerEvents", this).call(this);

      if (this.unbindHandlerEventsImpl) this.unbindHandlerEventsImpl();
    }
  }, {
    key: "bindEvents",
    value: function bindEvents(handler) {
      var self = this;
      self.handler = handler;
      var eventHandlers = {
        message: function message(_message) {
          if (self.connectionInfo.get('roomId') == _message.roomId) {
            handler.onMessage.apply(handler, arguments);
          }
        },
        messageDeleted: function messageDeleted(message) {
          if (self.connectionInfo.get('roomId') == message.roomId) {
            handler.onDeleteMessage.apply(handler, arguments);
          }
        },
        joined: function joined(userId, userDisplayName, roomId, roomDisplayName, time, isHistory) {
          if (self.connectionInfo.get('roomId') == roomId) {
            handler.onJoined.apply(handler, arguments);
          }
        },
        left: function left(userId, userDisplayName, roomId, roomDisplayName, time, isHistory) {
          if (self.connectionInfo.get('roomId') == roomId) {
            handler.onLeft.apply(handler, arguments);
          }
        },
        roomdestroyed: function roomdestroyed(roomId, roomDisplayName, time) {
          if (self.connectionInfo.get('roomId') == roomId) {
            handler.onRoomDestroyed.apply(handler, arguments);
          }
        },
        typing: function typing(userId, userDisplayName, roomId, roomDisplayName, isTyping, time) {
          if (self.connectionInfo.get('userId') == userId) return;
          if (self.connectionInfo.get('roomId') != roomId) return;
          handler.onTyping.apply(handler, arguments);
        },
        userDestroyed: function userDestroyed(userId) {
          if (self.connectionInfo.get('userId') != userId) return;
          handler.onRoomDestroyed.apply(handler);
        },
        roomdetailschanged: function roomdetailschanged(args) {
          if (self.connectionInfo.get('roomId') == args.id) {
            handler.onRoomDetailsChanged.apply(handler, arguments);
          }
        },
        roomchanged: function roomchanged(args) {
          if (self.connectionInfo.get('roomId') == args.room.id) {
            handler.onRoomChanged.apply(handler, arguments);
          }
        },
        noOperatorJoined: function noOperatorJoined(args) {
          if (self.connectionInfo.get('roomId') == args.roomId) {
            handler.onNoOperatorJoined.apply(handler, arguments);
          }
        },
        socketDisconnect: function socketDisconnect(_ref) {
          var reason = _ref.reason;
          var isOperator = self.getOption('isOperator');
          if (isOperator) return;
          var roomId = self.connectionInfo.get('roomId');
          handler.onRoomDestroyed.apply(handler, [roomId, '', new Date(), reason]);
        }
      };

      self.unbindHandlerEventsImpl = function () {
        self.chatServerConnection.off(eventHandlers);
        self.handler = null;
      };

      self.chatServerConnection.on(eventHandlers);
    }
  }, {
    key: "sessionTimeout",
    get: function get() {
      return TWENTY_MINUTES;
    }
  }]);

  return PCDataController;
}(base_data["a" /* default */]);

/* harmony default export */ var pc_data = __webpack_exports__["a"] = (pc_data_PCDataController);
// EXTERNAL MODULE: ./Scripts/chatserverclient/roomapi_chatserverclient.js
var roomapi_chatserverclient = __webpack_require__(640);

// EXTERNAL MODULE: ../node_modules/underscore/underscore.js
var underscore = __webpack_require__(5);
var underscore_default = /*#__PURE__*/__webpack_require__.n(underscore);

// EXTERNAL MODULE: ../node_modules/socket.io-client/lib/index.js
var lib = __webpack_require__(316);
var lib_default = /*#__PURE__*/__webpack_require__.n(lib);

// EXTERNAL MODULE: ./Scripts/constants/index.js + 1 modules
var constants = __webpack_require__(25);

// CONCATENATED MODULE: ./Scripts/chatserverclient/legacy_chatserverclient.js
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }




var array = [];
var slice = array.slice; // Regular expression used to split event strings.

var EVENT_SPLITTER = /\s+/; // A difficult-to-believe, but optimized internal dispatch function for
// triggering events. Tries to keep the usual cases speedy (most internal
// Backbone events have 3 arguments).

function triggerEvents(events, args) {
  var ev,
      i = -1,
      l = events.length,
      a1 = args[0],
      a2 = args[1],
      a3 = args[2]; // eslint-disable-line no-magic-numbers

  switch (args.length) {
    case 0:
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx);
      }

      return;

    case 1:
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx, a1);
      }

      return;

    case 2:
      // eslint-disable-line no-magic-numbers
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx, a1, a2);
      }

      return;

    case 3:
      // eslint-disable-line no-magic-numbers
      while (++i < l) {
        (ev = events[i]).callback.call(ev.ctx, a1, a2, a3);
      }

      return;

    default:
      while (++i < l) {
        (ev = events[i]).callback.apply(ev.ctx, args);
      }

  }
} // Implement fancy features of the Events API such as multiple event
// names `"change blur"` and jQuery-style event maps `{change: action}`
// in terms of the existing API.


function eventsApi(obj, action, name, rest) {
  if (!name) return true; // Handle event maps.

  if (_typeof(name) === 'object') {
    for (var key in name) {
      obj[action].apply(obj, [key, name[key]].concat(rest));
    }

    return false;
  } // Handle space separated event names.


  if (EVENT_SPLITTER.test(name)) {
    var names = name.split(EVENT_SPLITTER);

    for (var i = 0, l = names.length; i < l; i++) {
      obj[action].apply(obj, [names[i]].concat(rest));
    }

    return false;
  }

  return true;
} // private, context has to be set explicitly on call


var callCallback = {
  'message': function message(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedMessage = (args.message || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('message', {
      id: args.id,
      userId: args.userId,
      userDisplayName: escapedUserDisplayName,
      roomId: args.roomId,
      roomDisplayName: escapedRoomDisplayName,
      time: args.time,
      message: escapedMessage.length > 0 ? escapedMessage : null,
      isHistory: args.isHistory,
      timeElpased: args.timeElapsed,
      protocolVersion: args.protocolVersion,
      avatarUrl: args.avatarUrl,
      fromOperator: args.fromOperator,
      roomUtcOffset: args.roomUtcOffset,
      type: args.type,
      status: args.status
    });
  },
  messageDeleted: function messageDeleted(args) {
    this.trigger('messageDeleted', args);
  },
  'joined': function joined(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('joined', args.userId, escapedUserDisplayName, args.roomId, escapedRoomDisplayName, args.time, args.isHistory);
  },
  'left': function left(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('left', args.userId, escapedUserDisplayName, args.roomId, escapedRoomDisplayName, args.time, args.isHistory);
  },
  'roomdestroyed': function roomdestroyed(args) {
    var escapedRoomDisplayName = args.roomDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('roomdestroyed', args.roomId, escapedRoomDisplayName, args.time, args.reasonCode);
  },
  'userDestroyed': function userDestroyed(args) {
    this.trigger('userDestroyed', args.userId);
  },
  'typing': function typing(args) {
    var escapedUserDisplayName = args.userDisplayName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    this.trigger('typing', args.userId, escapedUserDisplayName, args.roomId, args.roomDisplayName, args.isTyping, args.time);
  },
  'roomchanged': function roomchanged(args) {
    if (args && args.action === 'closedroom' && window.PureChatEvents) {
      window.PureChatEvents.trigger('roomclosed', args.room.id);
    }

    this.trigger('roomchanged', args);
  },
  'default': function _default(event, args) {
    this.trigger(event, args);
  }
};

var legacy_chatserverclient_PureChat = function PureChat(socketUrl, userId, domainId, authToken, identifyStatus, errorStatus, restrictTransports, poppedOut, emailMD5Hash, reconnectLimit) {
  var _this = this;

  this.currentUserId = userId;
  this.currentDomainId = domainId;
  this.currentAuthToken = authToken;
  this.poppedOut = poppedOut;
  this.emailMD5Hash = emailMD5Hash;
  this.connectionAttempts = 0;
  lib_default.a.transports = ['websocket'];
  this.socket = lib_default.a.connect(socketUrl, {
    reconnectionAttempts: reconnectLimit || Infinity
  }); // stores socket.io messages that need to be sent out after the client registers callbacks

  this.messageQueue = []; // registers the handler for a message type - incoming messages will be sent to the callback if there is one, queued otherwise

  this.eventFncMappings = {};
  this.chatServerEvents = ['message', 'messageDeleted', 'joined', 'left', 'roomdestroyed', 'userDestroyed', 'typing', 'reidentify', 'userdeleted', 'chat-counts', 'opInvite', 'roomchanged', 'roomclosed', 'rooms', 'onlineOperatorStatus', 'opStatus', 'serverNotice', 'roomdetailschanged', 'userSettings:change', 'canned-responses:changed', 'canned-responses:added', 'canned-responses:deleted', 'userOnboarding:change', 'operator:refresh', 'noOperatorJoined', 'contact:changed', 'affiliate:reviewed', 'clientEvent' // All client events broadcast from api server. Should be used for all api events going forward.
  ];
  this.chatServerEvents.forEach(function (name) {
    _this.eventFncMappings[name] = function (args) {
      if (callCallback[name]) {
        callCallback[name].call(_this, args);
      } else {
        callCallback.default.call(_this, name, args);
      }
    };

    _this.socket.on(name, _this.eventFncMappings[name]);
  });
  this.socket.on('connect', function () {
    _this.reconnectCount = 0;

    _this.identify(_this.currentUserId, _this.currentDomainId, _this.currentAuthToken, identifyStatus, _this.poppedOut, _this.emailMD5Hash);

    _this.trigger('connection:connected:socketio');
  });
  this.socket.on('disconnect', function (reason) {
    console.log("SOCKET.IO -- DISCONNECT EVENT: ".concat(reason));

    _this.trigger('connection:disconnected:socketio');

    if (reason !== 'transport close') {
      _this.trigger('socketDisconnect', {
        reason: reason
      });
    }
  });
  this.socket.on('error', function (error) {
    console.log("SOCKET.IO -- ERROR EVENT: ".concat(error));
  });
  this.on('connection:retry:socketio', function () {
    return _this.socket.connected ? _this.trigger('connection:connected:socketio') : _this.socket.connect();
  });
  if (errorStatus) this.socket.on('error', errorStatus);
};

legacy_chatserverclient_PureChat.prototype.disconnect = function () {
  this.socket.disconnect();
  this.socket.removeAllListeners();
  this.socket = null;
};

legacy_chatserverclient_PureChat.prototype.identify = function (userId, domainId, authToken, status, poppedOut, emailMD5Hash) {
  this.currentUserId = userId;
  this.currentDomainId = domainId;
  this.currentAuthToken = authToken;
  this.deviceType = constants["f" /* DeviceType */].Desktop;
  this.poppedOut = poppedOut;
  this.protocolVersion = '2.0';
  this.emailMD5Hash = emailMD5Hash;
  this.socket.emit('identify', {
    'userId': this.currentUserId,
    'domainId': this.currentDomainId,
    'authToken': this.currentAuthToken,
    'deviceType': this.deviceType,
    'deviceVersion': legacy_chatserverclient_PureChat.deviceVersion,
    'poppedOut': this.poppedOut,
    'protocolVersion': this.protocolVersion,
    'emailMD5Hash': this.emailMD5Hash
  }, function () {
    // The `status` callback requires `this` to be the context of this
    // callback function, so don't change it.
    status.apply(this, arguments); // eslint-disable-line no-invalid-this
  });
};

legacy_chatserverclient_PureChat.prototype.sendmessage = function (message, roomId, roomType) {
  this.socket.emit('sendmessage', {
    message: message,
    roomId: roomId,
    type: constants["c" /* ChatRecordType */].Message
  });
};

legacy_chatserverclient_PureChat.prototype.deleteMessage = function (options) {
  if (!options.messageId) throw new TypeError('messageId is required');
  if (!options.roomId) throw new TypeError('roomId is required');
  this.socket.emit('deletemessage', options);
};

legacy_chatserverclient_PureChat.prototype.upload = function (options, callback) {
  if (!underscore_default.a.has(options, 'roomId')) throw new TypeError('roomId is required');
  if (!underscore_default.a.has(options, 'status')) throw new TypeError('status is required');
  this.socket.emit('upload', options, callback);
};

legacy_chatserverclient_PureChat.prototype.sendtyping = function (roomId, roomType, isTyping, statusCallback) {
  this.socket.emit('sendtyping', {
    roomId: roomId,
    isTyping: isTyping
  }, statusCallback);
};

legacy_chatserverclient_PureChat.prototype.destroyself = function (roomId, roomType, status, args) {
  this.socket.emit('destroyself', args || {}, status);
};

legacy_chatserverclient_PureChat.prototype.join = function (args, status) {
  var roomId = args.roomId;
  var invisible = args.invisible;
  var joinType = args.joinType;
  this.socket.emit('join', {
    roomId: roomId,
    invisible: invisible,
    joinType: joinType
  }, status);
};

legacy_chatserverclient_PureChat.prototype.leave = function (roomId, status) {
  this.socket.emit('leave', {
    roomId: roomId
  }, status);
};

legacy_chatserverclient_PureChat.prototype.closeroom = function (roomId, status) {
  this.socket.emit('closeroom', {
    roomId: roomId
  }, status);
};

legacy_chatserverclient_PureChat.prototype.createoperatorroom = function (roomName, otherUserIds, status, visitorEmailHash, visitorAvatarUrl) {
  this.socket.emit('createoperatorroom', {
    roomName: roomName,
    otherUserIds: otherUserIds
  }, status, visitorEmailHash, visitorAvatarUrl);
};

legacy_chatserverclient_PureChat.prototype.sendcurrentstate = function (status) {
  this.socket.emit('sendcurrentstate', {}, status);
};

legacy_chatserverclient_PureChat.prototype.getuser = function (status) {
  this.socket.emit('getuser', status);
};

legacy_chatserverclient_PureChat.prototype.getusers = function (status) {
  this.socket.emit('getusers', status);
};

legacy_chatserverclient_PureChat.prototype.sendroomhistory = function (roomId, roomType, status) {
  this.socket.emit('sendroomhistory', {
    'roomId': roomId
  }, status);
};

legacy_chatserverclient_PureChat.prototype.setavailable = function (userId, connectionId, available, statusCallback) {
  this.socket.emit('setavailable', {
    'userId': userId,
    'connectionId': connectionId,
    'available': available
  }, statusCallback);
};

legacy_chatserverclient_PureChat.prototype.setWidgetTypeAvailable = function (userId, widgetType, available, statusCallback) {
  this.socket.emit('setwidgettypeavailable', {
    'userId': userId,
    'widgetType': widgetType,
    'available': available
  }, statusCallback);
};

legacy_chatserverclient_PureChat.prototype.forcedisconnect = function (userId, connectionId, statusCallback) {
  this.socket.emit('forcedisconnect', {
    'userId': userId,
    'connectionId': connectionId
  }, statusCallback);
};

legacy_chatserverclient_PureChat.prototype.startdemo = function (widgetId, statusCallback) {
  this.socket.emit('startdemo', {
    'widgetId': widgetId
  }, statusCallback);
};

legacy_chatserverclient_PureChat.prototype.sendInvite = function (userId, roomId, roomName, fromName, statusCallback) {
  this.socket.emit('opInvite', {
    'userId': userId,
    'roomId': roomId,
    'roomName': roomName,
    'fromName': fromName
  }, statusCallback);
};

legacy_chatserverclient_PureChat.prototype.setVisitorDetails = function (roomId, roomType, details, statusCallback) {
  this.socket.emit('setvisitordetails', {
    roomId: roomId,
    details: details
  }, statusCallback);
};

legacy_chatserverclient_PureChat.deviceVersion = 1.0;

legacy_chatserverclient_PureChat.prototype.on = function (name, callback, context) {
  if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
  this._events = this._events || {};
  var events = this._events[name] || (this._events[name] = []);
  events.push({
    callback: callback,
    context: context,
    ctx: context || this
  });
  return this;
}; // Bind an event to only be triggered a single time. After the first time
// the callback is invoked, it will be removed.


legacy_chatserverclient_PureChat.prototype.once = function (name, callback, context) {
  var _this2 = this,
      _arguments = arguments;

  if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this;

  var once = underscore_default.a.once(function () {
    _this2.off(name, once);

    callback.apply(_this2, _arguments);
  });

  once._callback = callback;
  return this.on(name, once, context);
}; // Remove one or many callbacks. If `context` is null, removes all
// callbacks with that function. If `callback` is null, removes all
// callbacks for the event. If `name` is null, removes all bound
// callbacks for all events.


legacy_chatserverclient_PureChat.prototype.off = function (name, callback, context) {
  var retain;
  var ev;
  var events;
  if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;

  if (!name && !callback && !context) {
    this._events = void 0;
    return this;
  }

  var names = name ? [name] : underscore_default.a.keys(this._events);
  var i, l;

  for (i = 0, l = names.length; i < l; i++) {
    name = names[i];
    events = this._events[name];

    if (events) {
      this._events[name] = retain = [];

      if (callback || context) {
        var j = void 0,
            k = void 0;

        for (j = 0, k = events.length; j < k; j++) {
          ev = events[j];

          if (callback && callback !== ev.callback && callback !== ev.callback._callback || context && context !== ev.context) {
            retain.push(ev);
          }
        }
      }

      if (!retain.length) delete this._events[name];
    }
  }

  return this;
}; // Trigger one or many events, firing all bound callbacks. Callbacks are
// passed the same arguments as `trigger` is, apart from the event name
// (unless you're listening on `"all"`, which will cause your callback to
// receive the true name of the event as the first argument).


legacy_chatserverclient_PureChat.prototype.trigger = function (name) {
  if (!this._events) return this;
  var args = slice.call(arguments, 1);
  if (!eventsApi(this, 'trigger', name, args)) return this;
  var events = this._events[name];
  var allEvents = this._events.all;
  if (events) triggerEvents(events, args);
  if (allEvents) triggerEvents(allEvents, arguments);
  return this;
}; // Tell this object to stop listening to either specific events ... or
// to every object it's currently listening to.


legacy_chatserverclient_PureChat.prototype.stopListening = function (obj, name, callback) {
  var listeningTo = this._listeningTo;
  if (!listeningTo) return this;
  var remove = !name && !callback;
  if (!callback && _typeof(name) === 'object') callback = this;
  if (obj) (listeningTo = {})[obj._listenId] = obj;

  for (var id in listeningTo) {
    obj = listeningTo[id];
    obj.off(name, callback, this);
    if (remove || underscore_default.a.isEmpty(obj._events)) delete this._listeningTo[id];
  }

  return this;
};

/* harmony default export */ var legacy_chatserverclient = (legacy_chatserverclient_PureChat);
// CONCATENATED MODULE: ./Scripts/chatserverclient/index.js
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }



/* harmony default export */ var chatserverclient = __webpack_exports__["a"] = ({
  getInstance: function getInstance(version) {
    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }

    return !version || version === '1.0' ? _construct(legacy_chatserverclient, args) : _construct(roomapi_chatserverclient["a" /* default */], args);
  }
});
// EXTERNAL MODULE: ../node_modules/jquery/src/jquery.js
var jquery = __webpack_require__(0);
var jquery_default = /*#__PURE__*/__webpack_require__.n(jquery);

// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/chat_connection.model.js


var ChatConnection = no_conflict["a" /* Backbone */].Model.extend({
  defaults: {
    chatClosed: false
  },
  initialize: function initialize(data, options) {
    var _this = this;

    // I couldn't get the stupid storage change events to work so I resorted to this.
    // I am embarrassed!
    if (!options.isOperator && !options.poppedOut) {
      setInterval(function () {
        return _this.loadFromLocalStorage();
      }, 2000);
    }

    this.listenTo(this, 'change:userId, change:authToken, change:chatClosed', function () {
      this.trigger('change:isInChat', this, this.isInChat());
    });
  },
  persistedKeys: ['userId', 'authToken', 'roomId', 'roomType', 'chatId', 'visitorName', 'disabled', 'chatActiveInOtherWindow', 'chatClosed', 'expandSource', 'chatServerUrl', 'hasHadChat', 'hasHadEmail', 'chatServerVersion'],
  persistLocalStorage: function persistLocalStorage() {
    var self = this;

    no_conflict["c" /* _ */].each(self.persistedKeys, function (key) {
      if (self.get(key) != undefined) {
        localStorage['purechat_' + key] = self.get(key);
      }
    });

    return self;
  },
  clearLocalStorage: function clearLocalStorage() {
    this.persistedKeys.forEach(function (key) {
      delete localStorage[key];
    });
    this.clear();
    return this;
  },
  loadFromLocalStorage: function loadFromLocalStorage() {
    var _this2 = this;

    this.persistedKeys.forEach(function (key) {
      _this2.set(key, localStorage["purechat_".concat(key)]);
    });
    return this;
  },
  couldHaveContactRecord: function couldHaveContactRecord() {
    return Boolean(this.get('chatId')) || Boolean(this.get('hasHadChat')) || Boolean(this.get('hasHadEmail'));
  },
  isInChat: function isInChat() {
    return this.get('userId') && this.get('authToken') && (no_conflict["c" /* _ */].isUndefined(this.get('chatClosed')) || this.get('chatClosed') === 'false' || !this.get('chatClosed'));
  },
  loadChatServerUrl: function loadChatServerUrl() {
    if (!this.get('chatServerUrl')) this.set('chatServerUrl', localStorage.purechat_chatServerUrl);
    localStorage.purechat_chatServerUrl = this.get('chatServerUrl');
  }
});
/* harmony default export */ var chat_connection_model = (ChatConnection);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/services/base_data.js
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }




var base_data_BaseDataController =
/*#__PURE__*/
function () {
  function BaseDataController(options) {
    var _this = this,
        _arguments = arguments;

    _classCallCheck(this, BaseDataController);

    this.options = options;
    this.sentChatRequest = false;
    this.connectionInfo = new chat_connection_model({}, this.options);

    if (this.options.connectionInfo) {
      this.connectionInfo.set(this.options.connectionInfo);
    }

    this._originalGetWidgetSettings = this.getWidgetSettings;

    this.getWidgetSettings = function () {
      var deferred = jquery_default.a.Deferred();

      _this._originalGetWidgetSettings.apply(_this, _arguments).done(function (response) {
        if (response.widgetConfig && response.widgetConfig.AllowWidgetOnMobile && response.widgetConfig.RequestFromMobileDevice) {
          // CLEAR OUT expanded flag from local storage, because we don't want the widget to ever automatically open on the user's site
          window.localStorage.expanded = false;
        }

        deferred.resolve(response);
      });

      return deferred.promise();
    };
  }

  _createClass(BaseDataController, [{
    key: "getPreviousChat",
    value: function getPreviousChat() {
      var d = jquery_default.a.Deferred();
      d.resolve([]);
      return d.promise();
    }
  }, {
    key: "getContactInfo",
    value: function getContactInfo() {
      var d = jquery_default.a.Deferred();
      var contactId = this.getContactId();
      var widgetId = this.getOption('widgetId');
      var checkForContact = this.connectionInfo.couldHaveContactRecord(); //If they don't have a contactid and have not had a chat then we know that there
      //is not a contact record so don't bother checking.

      if (contactId && widgetId && checkForContact) {
        jquery_default.a.get("".concat(this.getOption('apiServerUrl'), "/api/contact/widget/").concat(widgetId, "/").concat(contactId)).done(function (result) {
          return d.resolve(result);
        }).fail(function () {
          return console.log('Error obtaining contact details');
        });
      } else {
        setTimeout(function () {
          return d.resolve();
        }, 0);
      }

      return d;
    }
  }, {
    key: "unbindHandlerEvents",
    value: function unbindHandlerEvents() {}
  }, {
    key: "loadWidgetSettings",
    value: function loadWidgetSettings() {
      var _this2 = this;

      var d = jquery_default.a.Deferred();
      this.getWidgetSettings().done(function (settings) {
        _this2.widgetSettings = settings;
        d.resolve();
      }).fail(function () {
        return d.reject();
      });
      return d;
    }
  }, {
    key: "getOption",
    value: function getOption(name) {
      return this.options[name];
    }
  }]);

  return BaseDataController;
}();

/* harmony default export */ var base_data = __webpack_exports__["a"] = (base_data_BaseDataController);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/emoji.view.js


var EmojiView = no_conflict["b" /* Marionette */].ItemView.extend({
  template: no_conflict["c" /* _ */].template('<%= obj.emoji %>'),
  tagName: 'button',
  className: 'purechat-emoji-button',
  attributes: function attributes() {
    return {
      type: 'button',
      title: this.model.get('description')
    };
  },
  events: {
    'click': 'selectEmoji',
    'mouseover': 'hoverEmoji'
  },
  modelEvents: {
    'change': 'render'
  },
  onRender: function onRender() {
    this.$el.purechatDisplay(this.model.get('filtered') ? 'none' : 'block');
    this.$el.toggleClass('purechat-emoji-button-active', this.model.get('selected'));
  },
  selectEmoji: function selectEmoji() {
    this.triggerMethod('emojiSelected', this.model);
  },
  hoverEmoji: function hoverEmoji() {
    this.triggerMethod('emojiHovered', this.model);
  }
});
/* harmony default export */ var emoji_view = (EmojiView);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/views/emoji_list.view.js


var EmojiListView = no_conflict["b" /* Marionette */].CollectionView.extend({
  childView: emoji_view,
  className: 'purechat-emoji-container',
  reorderOnSort: true,
  childEvents: {// The emojiSelected event will be be bubbled up to the parent of this view.
    // It seems like it should not do that, but it does.
  }
});
/* harmony default export */ var emoji_list_view = __webpack_exports__["a"] = (EmojiListView);
// EXTERNAL MODULE: ./Scripts/widgets/legacy/no-conflict.js
var no_conflict = __webpack_require__(3);

// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/emoji.model.js

var EmojiModel = no_conflict["a" /* Backbone */].Model.extend({
  idAttribute: 'emoji',
  defaults: function defaults() {
    return {
      clicked: 0,
      modified: new Date(),
      selected: false
    };
  },
  sync: function sync() {
    if (this.collection) {
      this.collection.sync.apply(this.collection, arguments);
    }
  }
});
/* harmony default export */ var emoji_model = (EmojiModel);
// CONCATENATED MODULE: ./Scripts/widgets/legacy/models/emojis.collection.js


var EmojisCollection = no_conflict["a" /* Backbone */].Collection.extend({
  model: emoji_model,
  getSelectedIndex: function getSelectedIndex() {
    return this.findIndex(function (model) {
      return model.get('selected');
    });
  },
  selectNext: function selectNext() {
    var n = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
    var selectedIndex = this.getSelectedIndex();
    if (selectedIndex < 0) return;
    var nextModel = this.at(selectedIndex + n);
    if (!nextModel) return;
    this.at(selectedIndex).set('selected', false);
    nextModel.set('selected', true);
  },
  selectPrev: function selectPrev() {
    var n = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
    var selectedIndex = this.getSelectedIndex();
    if (selectedIndex < 0 || selectedIndex - n < 0) return;
    var nextModel = this.at(selectedIndex - n);
    if (!nextModel) return;
    this.at(selectedIndex).set('selected', false);
    nextModel.set('selected', true);
  }
});
/* harmony default export */ var emojis_collection = __webpack_exports__["a"] = (EmojisCollection);