/******/
 (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _common = __webpack_require__(1);

	var _scale_team_users = __webpack_require__(434);

	var _scale_team_users2 = _interopRequireDefault(_scale_team_users);

	__webpack_require__(435);

	__webpack_require__(441);

	__webpack_require__(442);

	var _project = __webpack_require__(443);

	var _project2 = _interopRequireDefault(_project);

	var _graph = __webpack_require__(462);

	var _graph2 = _interopRequireDefault(_graph);

	var _stats = __webpack_require__(487);

	var _stats2 = _interopRequireDefault(_stats);

	var _sentry = __webpack_require__(488);

	var _sentry2 = _interopRequireDefault(_sentry);

	var _mailer = __webpack_require__(489);

	var _mailer2 = _interopRequireDefault(_mailer);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	// Common
	(0, _common.Init)().then(function () {

	  $("select.select:not(.chosen)").each(function () {
	    // todo => seems to be a fix
	    return $(this).val($(this).find("option[selected='selected']").val());
	  });

	  if ($(".scale-section-answers, .scale_team_feedback").length > 0) {
	    // todo => clean
	    $('input[type="range"]').rangeslider({ polyfill: false });
	    $('input[type="range"]').change();
	  }

	  if ($('canvas.graph-canvas').length) {
	    new _graph2.default($('canvas#view').data('fetch-url'));
	    //TODO remove when released for some time
	    if (!sessionStorage.getItem("seenHelp")) {
	      $("#graph_help").show();
	      sessionStorage.setItem("seenHelp", true);
	    }
	    // new Graph();
	  }

	  new _scale_team_users2.default();
	  new _project2.default();
	  new _sentry2.default();
	  new _mailer2.default();
	  new _stats2.default();
	});

	// Local assets


	// Components

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.Init = Init;

	__webpack_require__(2);

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _reactDom = __webpack_require__(64);

	var _reactDom2 = _interopRequireDefault(_reactDom);

	__webpack_require__(320);

	__webpack_require__(321);

	__webpack_require__(349);

	var _simplemde = __webpack_require__(350);

	var _simplemde2 = _interopRequireDefault(_simplemde);

	var _autosize = __webpack_require__(370);

	var _autosize2 = _interopRequireDefault(_autosize);

	var _ransack = __webpack_require__(371);

	var _ransack2 = _interopRequireDefault(_ransack);

	var _chartkick = __webpack_require__(372);

	var _chartkick2 = _interopRequireDefault(_chartkick);

	var _user_tooltip = __webpack_require__(373);

	var _user_tooltip2 = _interopRequireDefault(_user_tooltip);

	var _typeahead = __webpack_require__(374);

	var _typeahead2 = _interopRequireDefault(_typeahead);

	var _modal = __webpack_require__(377);

	var _modal2 = _interopRequireDefault(_modal);

	var _simple_form = __webpack_require__(379);

	var _simple_form2 = _interopRequireDefault(_simple_form);

	var _add_on = __webpack_require__(389);

	var _add_on2 = _interopRequireDefault(_add_on);

	var _data_events = __webpack_require__(395);

	var _data_events2 = _interopRequireDefault(_data_events);

	var _callback = __webpack_require__(396);

	var _callback2 = _interopRequireDefault(_callback);

	var _tags = __webpack_require__(399);

	var _tags2 = _interopRequireDefault(_tags);

	var _turbolinks = __webpack_require__(400);

	var _turbolinks2 = _interopRequireDefault(_turbolinks);

	var _markdownable = __webpack_require__(401);

	var _markdownable2 = _interopRequireDefault(_markdownable);

	var _manage_attachment = __webpack_require__(402);

	var _manage_attachment2 = _interopRequireDefault(_manage_attachment);

	var _simple_preview = __webpack_require__(403);

	var _simple_preview2 = _interopRequireDefault(_simple_preview);

	var _markdown_preview = __webpack_require__(404);

	var _markdown_preview2 = _interopRequireDefault(_markdown_preview);

	var _flashes = __webpack_require__(405);

	var _flashes2 = _interopRequireDefault(_flashes);

	var _fullscreen = __webpack_require__(406);

	var _fullscreen2 = _interopRequireDefault(_fullscreen);

	var _importer = __webpack_require__(407);

	var _importer2 = _interopRequireDefault(_importer);

	var _cache = __webpack_require__(408);

	var _cache2 = _interopRequireDefault(_cache);

	var _lockable = __webpack_require__(409);

	var _lockable2 = _interopRequireDefault(_lockable);

	var _multiple_actions = __webpack_require__(410);

	var _multiple_actions2 = _interopRequireDefault(_multiple_actions);

	var _remote_pagination = __webpack_require__(411);

	var _remote_pagination2 = _interopRequireDefault(_remote_pagination);

	var _menu_trigger = __webpack_require__(412);

	var _menu_trigger2 = _interopRequireDefault(_menu_trigger);

	var _sort = __webpack_require__(413);

	var _sort2 = _interopRequireDefault(_sort);

	var _overlay = __webpack_require__(416);

	var _overlay2 = _interopRequireDefault(_overlay);

	var _copy = __webpack_require__(417);

	var _copy2 = _interopRequireDefault(_copy);

	var _checkall = __webpack_require__(426);

	var _checkall2 = _interopRequireDefault(_checkall);

	var _replace_with = __webpack_require__(427);

	var _replace_with2 = _interopRequireDefault(_replace_with);

	var _emojis = __webpack_require__(428);

	var _emojis2 = _interopRequireDefault(_emojis);

	var _location_graph = __webpack_require__(430);

	var _location_graph2 = _interopRequireDefault(_location_graph);

	var _logtimes_chart = __webpack_require__(431);

	var _logtimes_chart2 = _interopRequireDefault(_logtimes_chart);

	var _bootstrap_flash_helper = __webpack_require__(432);

	var _bootstrap_flash_helper2 = _interopRequireDefault(_bootstrap_flash_helper);

	var _webhook_selector = __webpack_require__(433);

	var _webhook_selector2 = _interopRequireDefault(_webhook_selector);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	// Components
	// Todo => to remove , it's a test
	window.Chartkick = _chartkick2.default;

	// UJS
	// Load vendors


	/**
	 * Common code loaded between modules
	 */
	function common(done) {
	  window.SimpleMDE = _simplemde2.default;
	  new _user_tooltip2.default();
	  new _typeahead2.default();
	  new _simple_form2.default();
	  new _add_on2.default();
	  new _data_events2.default();
	  new _callback2.default();
	  new _tags2.default();
	  new _turbolinks2.default();
	  new _markdownable2.default();
	  new _markdown_preview2.default();
	  new _simple_preview2.default();
	  new _flashes2.default();
	  new _manage_attachment2.default();
	  new _fullscreen2.default();
	  new _importer2.default();
	  new _cache2.default();
	  new _lockable2.default();
	  new _multiple_actions2.default();
	  new _remote_pagination2.default();
	  new _menu_trigger2.default();
	  new _sort2.default();
	  new _overlay2.default();
	  new _copy2.default();
	  new _checkall2.default();
	  new _replace_with2.default();
	  new _modal2.default();
	  new _emojis2.default();
	  new _location_graph2.default();
	  new _logtimes_chart2.default();
	  new _bootstrap_flash_helper2.default();

	  (0, _webhook_selector2.default)();

	  (0, _jquery2.default)(".js-hidden").addClass("js-active").removeClass("js-hidden");
	  (0, _jquery2.default)('[data-toggle="tooltip"]').tooltip();
	  (0, _autosize2.default)(document.querySelectorAll('textarea[data-autosize]'));
	  done();
	}

	function Init() {
	  return new Promise(function (resolve) {
	    (0, _jquery2.default)(document).ready(function () {
	      return common(resolve);
	    });
	  });
	};

/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	__webpack_require__(3);

	__webpack_require__(6);

	__webpack_require__(9);

	__webpack_require__(10);

	__webpack_require__(12);

	__webpack_require__(25);

	__webpack_require__(26);

	__webpack_require__(27);

	__webpack_require__(211);

	__webpack_require__(214);

	var _exposeHighchartsHighcharts = __webpack_require__(317);

	var _exposeHighchartsHighcharts2 = _interopRequireDefault(_exposeHighchartsHighcharts);

	var _highchartsMore = __webpack_require__(319);

	var _highchartsMore2 = _interopRequireDefault(_highchartsMore);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	exports.default = function () {
	  (0, _highchartsMore2.default)(_exposeHighchartsHighcharts2.default);
	}();

/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["$"] = __webpack_require__(4);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["jQuery"] = __webpack_require__(5);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
	 * jQuery JavaScript Library v2.2.3
	 * http://jquery.com/
	 *
	 * Includes Sizzle.js
	 * http://sizzlejs.com/
	 *
	 * Copyright jQuery Foundation and other contributors
	 * Released under the MIT license
	 * http://jquery.org/license
	 *
	 * Date: 2016-04-05T19:26Z
	 */

	(function( global, factory ) {

		if ( typeof module === "object" && typeof module.exports === "object" ) {
			// For CommonJS and CommonJS-like environments where a proper `window`
			// is present, execute the factory and get jQuery.
			// For environments that do not have a `window` with a `document`
			// (such as Node.js), expose a factory as module.exports.
			// This accentuates the need for the creation of a real `window`.
			// e.g. var jQuery = require("jquery")(window);
			// See ticket #14549 for more info.
			module.exports = global.document ?
				factory( global, true ) :
				function( w ) {
					if ( !w.document ) {
						throw new Error( "jQuery requires a window with a document" );
					}
					return factory( w );
				};
		} else {
			factory( global );
		}

	// Pass this if window is not defined yet
	}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

	// Support: Firefox 18+
	// Can't be in strict mode, several libs including ASP.NET trace
	// the stack via arguments.caller.callee and Firefox dies if
	// you try to trace through "use strict" call chains. (#13335)
	//"use strict";
	var arr = [];

	var document = window.document;

	var slice = arr.slice;

	var concat = arr.concat;

	var push = arr.push;

	var indexOf = arr.indexOf;

	var class2type = {};

	var toString = class2type.toString;

	var hasOwn = class2type.hasOwnProperty;

	var support = {};



	var
		version = "2.2.3",

		// 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;
	}
	var Sizzle =
	/*!
	 * 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;
			}
		});
	}

	return Sizzle;

	})( window );



	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;



	var dir = 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;
	};


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

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

		return matched;
	};


	var rneedsContext = jQuery.expr.match.needsContext;

	var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );



	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;
		}
	} );


	// Initialize a jQuery object


	// 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 );


	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 );
		};
	} );
	var rnotwhite = ( /\S+/g );



	// 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;
	};


	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();
		}
	} );


	// 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();




	// 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;
	};
	var acceptData = function( owner ) {

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




	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 );
		}
	};
	var dataPriv = new Data();

	var dataUser = new Data();



	//	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 );
			} );
		}
	} );


	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 );
		}
	} );
	var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;

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


	var cssExpand = [ "Top", "Right", "Bottom", "Left" ];

	var isHidden = 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 );
		};



	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;
	}
	var rcheckableType = ( /^(?:checkbox|radio)$/i );

	var rtagName = ( /<([\w:-]+)/ );

	var rscriptType = ( /^$|\/(?:java|ecma)script/i );



	// 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;


	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;
	}


	// 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" )
			);
		}
	}


	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;
	}


	( 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;
	} )();


	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,

		preventDefault: function() {
			var e = this.originalEvent;

			this.isDefaultPrevented = returnTrue;

			if ( e ) {
				e.preventDefault();
			}
		},
		stopPropagation: function() {
			var e = this.originalEvent;

			this.isPropagationStopped = returnTrue;

			if ( e ) {
				e.stopPropagation();
			}
		},
		stopImmediatePropagation: function() {
			var e = this.originalEvent;

			this.isImmediatePropagationStopped = returnTrue;

			if ( e ) {
				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 );
			} );
		}
	} );


	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 );
		};
	} );


	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;
	}
	var rmargin = ( /^margin/ );

	var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );

	var getStyles = 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 );
		};

	var swap = 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;
	};


	var documentElement = document.documentElement;



	( 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;
			}
		} );
	} )();


	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;
	}


	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 );
			}
		};
	}


	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";

		// Support: IE11 only
		// In IE 11 fullscreen elements inside of an iframe have
		// 100x too small dimensions (gh-1764).
		if ( document.msFullscreenElement && window.top !== window ) {

			// Support: IE11 only
			// Running getBoundingClientRect on a disconnected node
			// in IE throws an error.
			if ( elem.getClientRects().length ) {
				val = Math.round( elem.getBoundingClientRect()[ name ] * 100 );
			}
		}

		// 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();
				}
			} );
		}
	} );


	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 = {};




	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
	};


	// 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 );
			};
		} );
	};


	( 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";
	} )();


	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;
		};
	} );




	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;
	} );




	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;
		}
	} );




	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;
			};
		}
	} );




	// Return jQuery for attributes-only inclusion


	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
		simulate: function( type, elem, event ) {
			var e = jQuery.extend(
				new jQuery.Event(),
				event,
				{
					type: type,
					isSimulated: true

					// Previously, `originalEvent: {}` was set here, so stopPropagation call
					// would not be triggered on donor event, since in our own
					// jQuery.event.stopPropagation function we had a check for existence of
					// originalEvent.stopPropagation method, so, consequently it would be a noop.
					//
					// But now, this "simulate" function is used only for events
					// for which stopPropagation() is noop, so there is no need for that anymore.
					//
					// For the 1.x branch though, guard for "click" and "submit"
					// events is still used, but was moved to jQuery.event.stopPropagation function
					// because `originalEvent` should point to the original event for the constancy
					// with other events and for more focused logic
				}
			);

			jQuery.event.trigger( e, null, elem );

			if ( e.isDefaultPrevented() ) {
				event.preventDefault();
			}
		}

	} );

	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 );
			}
		}
	} );


	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 );
		}
	} );




	support.focusin = "onfocusin" in window;


	// 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 );
					}
				}
			};
		} );
	}
	var location = window.location;

	var nonce = jQuery.now();

	var rquery = ( /\?/ );



	// Support: Android 2.3
	// Workaround failure to string-cast null input
	jQuery.parseJSON = function( data ) {
		return JSON.parse( data + "" );
	};


	// 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;
	};


	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 ) );
		};
	} );


	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
		} );
	};


	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();
		}
	} );


	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;
	};




	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();
		}
	} );


	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();
					}
				}
			};
		}
	} );




	// 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();
					}
				}
			};
		}
	} );




	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";
		}
	} );




	// 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 );
	};


	// 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;
	};




	// 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 );
		};
	} );




	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep( jQuery.timers, function( fn ) {
			return elem === fn.elem;
		} ).length;
	};




	/**
	 * 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;
				}
			}
		);
	} );


	// 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 );
			};
		} );
	} );


	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;




	// 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__));
	}



	var

		// Map over jQuery in case of overwrite
		_jQuery = window.jQuery,

		// Map over the $ in case of overwrite
		_$ = window.$;

	jQuery.noConflict = function( deep ) {
		if ( window.$ === jQuery ) {
			window.$ = _$;
		}

		if ( deep && window.jQuery === jQuery ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	};

	// Expose jQuery and $ identifiers, even in AMD
	// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
	// and CommonJS for browser emulators (#13566)
	if ( !noGlobal ) {
		window.jQuery = window.$ = jQuery;
	}

	return jQuery;
	}));


/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["_"] = __webpack_require__(7);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/**
	 * @license
	 * lodash 4.11.1 (Custom Build) <https://lodash.com/>
	 * Build: `lodash -d -o ./foo/lodash.js`
	 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
	 * Released under MIT license <https://lodash.com/license>
	 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
	 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
	 */
	;(function() {

	  /** Used as a safe reference for `undefined` in pre-ES5 environments. */
	  var undefined;

	  /** Used as the semantic version number. */
	  var VERSION = '4.11.1';

	  /** Used as the size to enable large array optimizations. */
	  var LARGE_ARRAY_SIZE = 200;

	  /** Used as the `TypeError` message for "Functions" methods. */
	  var FUNC_ERROR_TEXT = 'Expected a function';

	  /** Used to stand-in for `undefined` hash values. */
	  var HASH_UNDEFINED = '__lodash_hash_undefined__';

	  /** Used as the internal argument placeholder. */
	  var PLACEHOLDER = '__lodash_placeholder__';

	  /** Used to compose bitmasks for wrapper metadata. */
	  var BIND_FLAG = 1,
	      BIND_KEY_FLAG = 2,
	      CURRY_BOUND_FLAG = 4,
	      CURRY_FLAG = 8,
	      CURRY_RIGHT_FLAG = 16,
	      PARTIAL_FLAG = 32,
	      PARTIAL_RIGHT_FLAG = 64,
	      ARY_FLAG = 128,
	      REARG_FLAG = 256,
	      FLIP_FLAG = 512;

	  /** Used to compose bitmasks for comparison styles. */
	  var UNORDERED_COMPARE_FLAG = 1,
	      PARTIAL_COMPARE_FLAG = 2;

	  /** Used as default options for `_.truncate`. */
	  var DEFAULT_TRUNC_LENGTH = 30,
	      DEFAULT_TRUNC_OMISSION = '...';

	  /** Used to detect hot functions by number of calls within a span of milliseconds. */
	  var HOT_COUNT = 150,
	      HOT_SPAN = 16;

	  /** Used to indicate the type of lazy iteratees. */
	  var LAZY_FILTER_FLAG = 1,
	      LAZY_MAP_FLAG = 2,
	      LAZY_WHILE_FLAG = 3;

	  /** Used as references for various `Number` constants. */
	  var INFINITY = 1 / 0,
	      MAX_SAFE_INTEGER = 9007199254740991,
	      MAX_INTEGER = 1.7976931348623157e+308,
	      NAN = 0 / 0;

	  /** Used as references for the maximum length and index of an array. */
	  var MAX_ARRAY_LENGTH = 4294967295,
	      MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
	      HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;

	  /** `Object#toString` result references. */
	  var argsTag = '[object Arguments]',
	      arrayTag = '[object Array]',
	      boolTag = '[object Boolean]',
	      dateTag = '[object Date]',
	      errorTag = '[object Error]',
	      funcTag = '[object Function]',
	      genTag = '[object GeneratorFunction]',
	      mapTag = '[object Map]',
	      numberTag = '[object Number]',
	      objectTag = '[object Object]',
	      promiseTag = '[object Promise]',
	      regexpTag = '[object RegExp]',
	      setTag = '[object Set]',
	      stringTag = '[object String]',
	      symbolTag = '[object Symbol]',
	      weakMapTag = '[object WeakMap]',
	      weakSetTag = '[object WeakSet]';

	  var arrayBufferTag = '[object ArrayBuffer]',
	      dataViewTag = '[object DataView]',
	      float32Tag = '[object Float32Array]',
	      float64Tag = '[object Float64Array]',
	      int8Tag = '[object Int8Array]',
	      int16Tag = '[object Int16Array]',
	      int32Tag = '[object Int32Array]',
	      uint8Tag = '[object Uint8Array]',
	      uint8ClampedTag = '[object Uint8ClampedArray]',
	      uint16Tag = '[object Uint16Array]',
	      uint32Tag = '[object Uint32Array]';

	  /** Used to match empty string literals in compiled template source. */
	  var reEmptyStringLeading = /\b__p \+= '';/g,
	      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
	      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;

	  /** Used to match HTML entities and HTML characters. */
	  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
	      reUnescapedHtml = /[&<>"'`]/g,
	      reHasEscapedHtml = RegExp(reEscapedHtml.source),
	      reHasUnescapedHtml = RegExp(reUnescapedHtml.source);

	  /** Used to match template delimiters. */
	  var reEscape = /<%-([\s\S]+?)%>/g,
	      reEvaluate = /<%([\s\S]+?)%>/g,
	      reInterpolate = /<%=([\s\S]+?)%>/g;

	  /** Used to match property names within property paths. */
	  var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
	      reIsPlainProp = /^\w*$/,
	      rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g;

	  /**
	   * Used to match `RegExp`
	   * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns).
	   */
	  var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
	      reHasRegExpChar = RegExp(reRegExpChar.source);

	  /** Used to match leading and trailing whitespace. */
	  var reTrim = /^\s+|\s+$/g,
	      reTrimStart = /^\s+/,
	      reTrimEnd = /\s+$/;

	  /** Used to match non-compound words composed of alphanumeric characters. */
	  var reBasicWord = /[a-zA-Z0-9]+/g;

	  /** Used to match backslashes in property paths. */
	  var reEscapeChar = /\\(\\)?/g;

	  /**
	   * Used to match
	   * [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components).
	   */
	  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;

	  /** Used to match `RegExp` flags from their coerced string values. */
	  var reFlags = /\w*$/;

	  /** Used to detect hexadecimal string values. */
	  var reHasHexPrefix = /^0x/i;

	  /** Used to detect bad signed hexadecimal string values. */
	  var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

	  /** Used to detect binary string values. */
	  var reIsBinary = /^0b[01]+$/i;

	  /** Used to detect host constructors (Safari). */
	  var reIsHostCtor = /^\[object .+?Constructor\]$/;

	  /** Used to detect octal string values. */
	  var reIsOctal = /^0o[0-7]+$/i;

	  /** Used to detect unsigned integer values. */
	  var reIsUint = /^(?:0|[1-9]\d*)$/;

	  /** Used to match latin-1 supplementary letters (excluding mathematical operators). */
	  var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;

	  /** Used to ensure capturing order of template delimiters. */
	  var reNoMatch = /($^)/;

	  /** Used to match unescaped characters in compiled string literals. */
	  var reUnescapedString = /['\n\r\u2028\u2029\\]/g;

	  /** Used to compose unicode character classes. */
	  var rsAstralRange = '\\ud800-\\udfff',
	      rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23',
	      rsComboSymbolsRange = '\\u20d0-\\u20f0',
	      rsDingbatRange = '\\u2700-\\u27bf',
	      rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
	      rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
	      rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
	      rsQuoteRange = '\\u2018\\u2019\\u201c\\u201d',
	      rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
	      rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
	      rsVarRange = '\\ufe0e\\ufe0f',
	      rsBreakRange = rsMathOpRange + rsNonCharRange + rsQuoteRange + rsSpaceRange;

	  /** Used to compose unicode capture groups. */
	  var rsApos = "['\u2019]",
	      rsAstral = '[' + rsAstralRange + ']',
	      rsBreak = '[' + rsBreakRange + ']',
	      rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']',
	      rsDigits = '\\d+',
	      rsDingbat = '[' + rsDingbatRange + ']',
	      rsLower = '[' + rsLowerRange + ']',
	      rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
	      rsFitz = '\\ud83c[\\udffb-\\udfff]',
	      rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
	      rsNonAstral = '[^' + rsAstralRange + ']',
	      rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
	      rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
	      rsUpper = '[' + rsUpperRange + ']',
	      rsZWJ = '\\u200d';

	  /** Used to compose unicode regexes. */
	  var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')',
	      rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')',
	      rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
	      rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
	      reOptMod = rsModifier + '?',
	      rsOptVar = '[' + rsVarRange + ']?',
	      rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
	      rsSeq = rsOptVar + reOptMod + rsOptJoin,
	      rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
	      rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';

	  /** Used to match apostrophes. */
	  var reApos = RegExp(rsApos, 'g');

	  /**
	   * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
	   * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
	   */
	  var reComboMark = RegExp(rsCombo, 'g');

	  /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
	  var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');

	  /** Used to match complex or compound words. */
	  var reComplexWord = RegExp([
	    rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
	    rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')',
	    rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr,
	    rsUpper + '+' + rsOptUpperContr,
	    rsDigits,
	    rsEmoji
	  ].join('|'), 'g');

	  /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
	  var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange  + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']');

	  /** Used to detect strings that need a more robust regexp to match words. */
	  var reHasComplexWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;

	  /** Used to assign default `context` object properties. */
	  var contextProps = [
	    'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
	    'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
	    'Promise', 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError',
	    'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
	    '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
	  ];

	  /** Used to make template sourceURLs easier to identify. */
	  var templateCounter = -1;

	  /** Used to identify `toStringTag` values of typed arrays. */
	  var typedArrayTags = {};
	  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
	  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
	  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
	  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
	  typedArrayTags[uint32Tag] = true;
	  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
	  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
	  typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
	  typedArrayTags[errorTag] = typedArrayTags[funcTag] =
	  typedArrayTags[mapTag] = typedArrayTags[numberTag] =
	  typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
	  typedArrayTags[setTag] = typedArrayTags[stringTag] =
	  typedArrayTags[weakMapTag] = false;

	  /** Used to identify `toStringTag` values supported by `_.clone`. */
	  var cloneableTags = {};
	  cloneableTags[argsTag] = cloneableTags[arrayTag] =
	  cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
	  cloneableTags[boolTag] = cloneableTags[dateTag] =
	  cloneableTags[float32Tag] = cloneableTags[float64Tag] =
	  cloneableTags[int8Tag] = cloneableTags[int16Tag] =
	  cloneableTags[int32Tag] = cloneableTags[mapTag] =
	  cloneableTags[numberTag] = cloneableTags[objectTag] =
	  cloneableTags[regexpTag] = cloneableTags[setTag] =
	  cloneableTags[stringTag] = cloneableTags[symbolTag] =
	  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
	  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
	  cloneableTags[errorTag] = cloneableTags[funcTag] =
	  cloneableTags[weakMapTag] = false;

	  /** Used to map latin-1 supplementary letters to basic latin letters. */
	  var deburredLetters = {
	    '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
	    '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
	    '\xc7': 'C',  '\xe7': 'c',
	    '\xd0': 'D',  '\xf0': 'd',
	    '\xc8': 'E',  '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
	    '\xe8': 'e',  '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
	    '\xcC': 'I',  '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
	    '\xeC': 'i',  '\xed': 'i', '\xee': 'i', '\xef': 'i',
	    '\xd1': 'N',  '\xf1': 'n',
	    '\xd2': 'O',  '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
	    '\xf2': 'o',  '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
	    '\xd9': 'U',  '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
	    '\xf9': 'u',  '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
	    '\xdd': 'Y',  '\xfd': 'y', '\xff': 'y',
	    '\xc6': 'Ae', '\xe6': 'ae',
	    '\xde': 'Th', '\xfe': 'th',
	    '\xdf': 'ss'
	  };

	  /** Used to map characters to HTML entities. */
	  var htmlEscapes = {
	    '&': '&amp;',
	    '<': '&lt;',
	    '>': '&gt;',
	    '"': '&quot;',
	    "'": '&#39;',
	    '`': '&#96;'
	  };

	  /** Used to map HTML entities to characters. */
	  var htmlUnescapes = {
	    '&amp;': '&',
	    '&lt;': '<',
	    '&gt;': '>',
	    '&quot;': '"',
	    '&#39;': "'",
	    '&#96;': '`'
	  };

	  /** Used to determine if values are of the language type `Object`. */
	  var objectTypes = {
	    'function': true,
	    'object': true
	  };

	  /** Used to escape characters for inclusion in compiled string literals. */
	  var stringEscapes = {
	    '\\': '\\',
	    "'": "'",
	    '\n': 'n',
	    '\r': 'r',
	    '\u2028': 'u2028',
	    '\u2029': 'u2029'
	  };

	  /** Built-in method references without a dependency on `root`. */
	  var freeParseFloat = parseFloat,
	      freeParseInt = parseInt;

	  /** Detect free variable `exports`. */
	  var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType)
	    ? exports
	    : undefined;

	  /** Detect free variable `module`. */
	  var freeModule = (objectTypes[typeof module] && module && !module.nodeType)
	    ? module
	    : undefined;

	  /** Detect the popular CommonJS extension `module.exports`. */
	  var moduleExports = (freeModule && freeModule.exports === freeExports)
	    ? freeExports
	    : undefined;

	  /** Detect free variable `global` from Node.js. */
	  var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global);

	  /** Detect free variable `self`. */
	  var freeSelf = checkGlobal(objectTypes[typeof self] && self);

	  /** Detect free variable `window`. */
	  var freeWindow = checkGlobal(objectTypes[typeof window] && window);

	  /** Detect `this` as the global object. */
	  var thisGlobal = checkGlobal(objectTypes[typeof this] && this);

	  /**
	   * Used as a reference to the global object.
	   *
	   * The `this` value is used if it's the global object to avoid Greasemonkey's
	   * restricted `window` object, otherwise the `window` object is used.
	   */
	  var root = freeGlobal ||
	    ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) ||
	      freeSelf || thisGlobal || Function('return this')();

	  /*--------------------------------------------------------------------------*/

	  /**
	   * Adds the key-value `pair` to `map`.
	   *
	   * @private
	   * @param {Object} map The map to modify.
	   * @param {Array} pair The key-value pair to add.
	   * @returns {Object} Returns `map`.
	   */
	  function addMapEntry(map, pair) {
	    // Don't return `Map#set` because it doesn't return the map instance in IE 11.
	    map.set(pair[0], pair[1]);
	    return map;
	  }

	  /**
	   * Adds `value` to `set`.
	   *
	   * @private
	   * @param {Object} set The set to modify.
	   * @param {*} value The value to add.
	   * @returns {Object} Returns `set`.
	   */
	  function addSetEntry(set, value) {
	    set.add(value);
	    return set;
	  }

	  /**
	   * A faster alternative to `Function#apply`, this function invokes `func`
	   * with the `this` binding of `thisArg` and the arguments of `args`.
	   *
	   * @private
	   * @param {Function} func The function to invoke.
	   * @param {*} thisArg The `this` binding of `func`.
	   * @param {Array} args The arguments to invoke `func` with.
	   * @returns {*} Returns the result of `func`.
	   */
	  function apply(func, thisArg, args) {
	    var length = args.length;
	    switch (length) {
	      case 0: return func.call(thisArg);
	      case 1: return func.call(thisArg, args[0]);
	      case 2: return func.call(thisArg, args[0], args[1]);
	      case 3: return func.call(thisArg, args[0], args[1], args[2]);
	    }
	    return func.apply(thisArg, args);
	  }

	  /**
	   * A specialized version of `baseAggregator` for arrays.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} setter The function to set `accumulator` values.
	   * @param {Function} iteratee The iteratee to transform keys.
	   * @param {Object} accumulator The initial aggregated object.
	   * @returns {Function} Returns `accumulator`.
	   */
	  function arrayAggregator(array, setter, iteratee, accumulator) {
	    var index = -1,
	        length = array.length;

	    while (++index < length) {
	      var value = array[index];
	      setter(accumulator, value, iteratee(value), array);
	    }
	    return accumulator;
	  }

	  /**
	   * Creates a new array concatenating `array` with `other`.
	   *
	   * @private
	   * @param {Array} array The first array to concatenate.
	   * @param {Array} other The second array to concatenate.
	   * @returns {Array} Returns the new concatenated array.
	   */
	  function arrayConcat(array, other) {
	    var index = -1,
	        length = array.length,
	        othIndex = -1,
	        othLength = other.length,
	        result = Array(length + othLength);

	    while (++index < length) {
	      result[index] = array[index];
	    }
	    while (++othIndex < othLength) {
	      result[index++] = other[othIndex];
	    }
	    return result;
	  }

	  /**
	   * A specialized version of `_.forEach` for arrays without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @returns {Array} Returns `array`.
	   */
	  function arrayEach(array, iteratee) {
	    var index = -1,
	        length = array.length;

	    while (++index < length) {
	      if (iteratee(array[index], index, array) === false) {
	        break;
	      }
	    }
	    return array;
	  }

	  /**
	   * A specialized version of `_.forEachRight` for arrays without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @returns {Array} Returns `array`.
	   */
	  function arrayEachRight(array, iteratee) {
	    var length = array.length;

	    while (length--) {
	      if (iteratee(array[length], length, array) === false) {
	        break;
	      }
	    }
	    return array;
	  }

	  /**
	   * A specialized version of `_.every` for arrays without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} predicate The function invoked per iteration.
	   * @returns {boolean} Returns `true` if all elements pass the predicate check,
	   *  else `false`.
	   */
	  function arrayEvery(array, predicate) {
	    var index = -1,
	        length = array.length;

	    while (++index < length) {
	      if (!predicate(array[index], index, array)) {
	        return false;
	      }
	    }
	    return true;
	  }

	  /**
	   * A specialized version of `_.filter` for arrays without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} predicate The function invoked per iteration.
	   * @returns {Array} Returns the new filtered array.
	   */
	  function arrayFilter(array, predicate) {
	    var index = -1,
	        length = array.length,
	        resIndex = 0,
	        result = [];

	    while (++index < length) {
	      var value = array[index];
	      if (predicate(value, index, array)) {
	        result[resIndex++] = value;
	      }
	    }
	    return result;
	  }

	  /**
	   * A specialized version of `_.includes` for arrays without support for
	   * specifying an index to search from.
	   *
	   * @private
	   * @param {Array} array The array to search.
	   * @param {*} target The value to search for.
	   * @returns {boolean} Returns `true` if `target` is found, else `false`.
	   */
	  function arrayIncludes(array, value) {
	    return !!array.length && baseIndexOf(array, value, 0) > -1;
	  }

	  /**
	   * This function is like `arrayIncludes` except that it accepts a comparator.
	   *
	   * @private
	   * @param {Array} array The array to search.
	   * @param {*} target The value to search for.
	   * @param {Function} comparator The comparator invoked per element.
	   * @returns {boolean} Returns `true` if `target` is found, else `false`.
	   */
	  function arrayIncludesWith(array, value, comparator) {
	    var index = -1,
	        length = array.length;

	    while (++index < length) {
	      if (comparator(value, array[index])) {
	        return true;
	      }
	    }
	    return false;
	  }

	  /**
	   * A specialized version of `_.map` for arrays without support for iteratee
	   * shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @returns {Array} Returns the new mapped array.
	   */
	  function arrayMap(array, iteratee) {
	    var index = -1,
	        length = array.length,
	        result = Array(length);

	    while (++index < length) {
	      result[index] = iteratee(array[index], index, array);
	    }
	    return result;
	  }

	  /**
	   * Appends the elements of `values` to `array`.
	   *
	   * @private
	   * @param {Array} array The array to modify.
	   * @param {Array} values The values to append.
	   * @returns {Array} Returns `array`.
	   */
	  function arrayPush(array, values) {
	    var index = -1,
	        length = values.length,
	        offset = array.length;

	    while (++index < length) {
	      array[offset + index] = values[index];
	    }
	    return array;
	  }

	  /**
	   * A specialized version of `_.reduce` for arrays without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @param {*} [accumulator] The initial value.
	   * @param {boolean} [initAccum] Specify using the first element of `array` as
	   *  the initial value.
	   * @returns {*} Returns the accumulated value.
	   */
	  function arrayReduce(array, iteratee, accumulator, initAccum) {
	    var index = -1,
	        length = array.length;

	    if (initAccum && length) {
	      accumulator = array[++index];
	    }
	    while (++index < length) {
	      accumulator = iteratee(accumulator, array[index], index, array);
	    }
	    return accumulator;
	  }

	  /**
	   * A specialized version of `_.reduceRight` for arrays without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @param {*} [accumulator] The initial value.
	   * @param {boolean} [initAccum] Specify using the last element of `array` as
	   *  the initial value.
	   * @returns {*} Returns the accumulated value.
	   */
	  function arrayReduceRight(array, iteratee, accumulator, initAccum) {
	    var length = array.length;
	    if (initAccum && length) {
	      accumulator = array[--length];
	    }
	    while (length--) {
	      accumulator = iteratee(accumulator, array[length], length, array);
	    }
	    return accumulator;
	  }

	  /**
	   * A specialized version of `_.some` for arrays without support for iteratee
	   * shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} predicate The function invoked per iteration.
	   * @returns {boolean} Returns `true` if any element passes the predicate check,
	   *  else `false`.
	   */
	  function arraySome(array, predicate) {
	    var index = -1,
	        length = array.length;

	    while (++index < length) {
	      if (predicate(array[index], index, array)) {
	        return true;
	      }
	    }
	    return false;
	  }

	  /**
	   * The base implementation of methods like `_.max` and `_.min` which accepts a
	   * `comparator` to determine the extremum value.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The iteratee invoked per iteration.
	   * @param {Function} comparator The comparator used to compare values.
	   * @returns {*} Returns the extremum value.
	   */
	  function baseExtremum(array, iteratee, comparator) {
	    var index = -1,
	        length = array.length;

	    while (++index < length) {
	      var value = array[index],
	          current = iteratee(value);

	      if (current != null && (computed === undefined
	            ? current === current
	            : comparator(current, computed)
	          )) {
	        var computed = current,
	            result = value;
	      }
	    }
	    return result;
	  }

	  /**
	   * The base implementation of methods like `_.find` and `_.findKey`, without
	   * support for iteratee shorthands, which iterates over `collection` using
	   * `eachFunc`.
	   *
	   * @private
	   * @param {Array|Object} collection The collection to search.
	   * @param {Function} predicate The function invoked per iteration.
	   * @param {Function} eachFunc The function to iterate over `collection`.
	   * @param {boolean} [retKey] Specify returning the key of the found element
	   *  instead of the element itself.
	   * @returns {*} Returns the found element or its key, else `undefined`.
	   */
	  function baseFind(collection, predicate, eachFunc, retKey) {
	    var result;
	    eachFunc(collection, function(value, key, collection) {
	      if (predicate(value, key, collection)) {
	        result = retKey ? key : value;
	        return false;
	      }
	    });
	    return result;
	  }

	  /**
	   * The base implementation of `_.findIndex` and `_.findLastIndex` without
	   * support for iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to search.
	   * @param {Function} predicate The function invoked per iteration.
	   * @param {boolean} [fromRight] Specify iterating from right to left.
	   * @returns {number} Returns the index of the matched value, else `-1`.
	   */
	  function baseFindIndex(array, predicate, fromRight) {
	    var length = array.length,
	        index = fromRight ? length : -1;

	    while ((fromRight ? index-- : ++index < length)) {
	      if (predicate(array[index], index, array)) {
	        return index;
	      }
	    }
	    return -1;
	  }

	  /**
	   * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
	   *
	   * @private
	   * @param {Array} array The array to search.
	   * @param {*} value The value to search for.
	   * @param {number} fromIndex The index to search from.
	   * @returns {number} Returns the index of the matched value, else `-1`.
	   */
	  function baseIndexOf(array, value, fromIndex) {
	    if (value !== value) {
	      return indexOfNaN(array, fromIndex);
	    }
	    var index = fromIndex - 1,
	        length = array.length;

	    while (++index < length) {
	      if (array[index] === value) {
	        return index;
	      }
	    }
	    return -1;
	  }

	  /**
	   * This function is like `baseIndexOf` except that it accepts a comparator.
	   *
	   * @private
	   * @param {Array} array The array to search.
	   * @param {*} value The value to search for.
	   * @param {number} fromIndex The index to search from.
	   * @param {Function} comparator The comparator invoked per element.
	   * @returns {number} Returns the index of the matched value, else `-1`.
	   */
	  function baseIndexOfWith(array, value, fromIndex, comparator) {
	    var index = fromIndex - 1,
	        length = array.length;

	    while (++index < length) {
	      if (comparator(array[index], value)) {
	        return index;
	      }
	    }
	    return -1;
	  }

	  /**
	   * The base implementation of `_.mean` and `_.meanBy` without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @returns {number} Returns the mean.
	   */
	  function baseMean(array, iteratee) {
	    var length = array ? array.length : 0;
	    return length ? (baseSum(array, iteratee) / length) : NAN;
	  }

	  /**
	   * The base implementation of `_.reduce` and `_.reduceRight`, without support
	   * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
	   *
	   * @private
	   * @param {Array|Object} collection The collection to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @param {*} accumulator The initial value.
	   * @param {boolean} initAccum Specify using the first or last element of
	   *  `collection` as the initial value.
	   * @param {Function} eachFunc The function to iterate over `collection`.
	   * @returns {*} Returns the accumulated value.
	   */
	  function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
	    eachFunc(collection, function(value, index, collection) {
	      accumulator = initAccum
	        ? (initAccum = false, value)
	        : iteratee(accumulator, value, index, collection);
	    });
	    return accumulator;
	  }

	  /**
	   * The base implementation of `_.sortBy` which uses `comparer` to define the
	   * sort order of `array` and replaces criteria objects with their corresponding
	   * values.
	   *
	   * @private
	   * @param {Array} array The array to sort.
	   * @param {Function} comparer The function to define sort order.
	   * @returns {Array} Returns `array`.
	   */
	  function baseSortBy(array, comparer) {
	    var length = array.length;

	    array.sort(comparer);
	    while (length--) {
	      array[length] = array[length].value;
	    }
	    return array;
	  }

	  /**
	   * The base implementation of `_.sum` and `_.sumBy` without support for
	   * iteratee shorthands.
	   *
	   * @private
	   * @param {Array} array The array to iterate over.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @returns {number} Returns the sum.
	   */
	  function baseSum(array, iteratee) {
	    var result,
	        index = -1,
	        length = array.length;

	    while (++index < length) {
	      var current = iteratee(array[index]);
	      if (current !== undefined) {
	        result = result === undefined ? current : (result + current);
	      }
	    }
	    return result;
	  }

	  /**
	   * The base implementation of `_.times` without support for iteratee shorthands
	   * or max array length checks.
	   *
	   * @private
	   * @param {number} n The number of times to invoke `iteratee`.
	   * @param {Function} iteratee The function invoked per iteration.
	   * @returns {Array} Returns the array of results.
	   */
	  function baseTimes(n, iteratee) {
	    var index = -1,
	        result = Array(n);

	    while (++index < n) {
	      result[index] = iteratee(index);
	    }
	    return result;
	  }

	  /**
	   * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
	   * of key-value pairs for `object` corresponding to the property names of `props`.
	   *
	   * @private
	   * @param {Object} object The object to query.
	   * @param {Array} props The property names to get values for.
	   * @returns {Object} Returns the new array of key-value pairs.
	   */
	  function baseToPairs(object, props) {
	    return arrayMap(props, function(key) {
	      return [key, object[key]];
	    });
	  }

	  /**
	   * The base implementation of `_.unary` without support for storing wrapper metadata.
	   *
	   * @private
	   * @param {Function} func The function to cap arguments for.
	   * @returns {Function} Returns the new function.
	   */
	  function baseUnary(func) {
	    return function(value) {
	      return func(value);
	    };
	  }

	  /**
	   * The base implementation of `_.values` and `_.valuesIn` which creates an
	   * array of `object` property values corresponding to the property names
	   * of `props`.
	   *
	   * @private
	   * @param {Object} object The object to query.
	   * @param {Array} props The property names to get values for.
	   * @returns {Object} Returns the array of property values.
	   */
	  function baseValues(object, props) {
	    return arrayMap(props, function(key) {
	      return object[key];
	    });
	  }

	  /**
	   * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
	   * that is not found in the character symbols.
	   *
	   * @private
	   * @param {Array} strSymbols The string symbols to inspect.
	   * @param {Array} chrSymbols The character symbols to find.
	   * @returns {number} Returns the index of the first unmatched string symbol.
	   */
	  function charsStartIndex(strSymbols, chrSymbols) {
	    var index = -1,
	        length = strSymbols.length;

	    while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
	    return index;
	  }

	  /**
	   * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
	   * that is not found in the character symbols.
	   *
	   * @private
	   * @param {Array} strSymbols The string symbols to inspect.
	   * @param {Array} chrSymbols The character symbols to find.
	   * @returns {number} Returns the index of the last unmatched string symbol.
	   */
	  function charsEndIndex(strSymbols, chrSymbols) {
	    var index = strSymbols.length;

	    while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
	    return index;
	  }

	  /**
	   * Checks if `value` is a global object.
	   *
	   * @private
	   * @param {*} value The value to check.
	   * @returns {null|Object} Returns `value` if it's a global object, else `null`.
	   */
	  function checkGlobal(value) {
	    return (value && value.Object === Object) ? value : null;
	  }

	  /**
	   * Compares values to sort them in ascending order.
	   *
	   * @private
	   * @param {*} value The value to compare.
	   * @param {*} other The other value to compare.
	   * @returns {number} Returns the sort order indicator for `value`.
	   */
	  function compareAscending(value, other) {
	    if (value !== other) {
	      var valIsNull = value === null,
	          valIsUndef = value === undefined,
	          valIsReflexive = value === value;

	      var othIsNull = other === null,
	          othIsUndef = other === undefined,
	          othIsReflexive = other === other;

	      if ((value > other && !othIsNull) || !valIsReflexive ||
	          (valIsNull && !othIsUndef && othIsReflexive) ||
	          (valIsUndef && othIsReflexive)) {
	        return 1;
	      }
	      if ((value < other && !valIsNull) || !othIsReflexive ||
	          (othIsNull && !valIsUndef && valIsReflexive) ||
	          (othIsUndef && valIsReflexive)) {
	        return -1;
	      }
	    }
	    return 0;
	  }

	  /**
	   * Used by `_.orderBy` to compare multiple properties of a value to another
	   * and stable sort them.
	   *
	   * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
	   * specify an order of "desc" for descending or "asc" for ascending sort order
	   * of corresponding values.
	   *
	   * @private
	   * @param {Object} object The object to compare.
	   * @param {Object} other The other object to compare.
	   * @param {boolean[]|string[]} orders The order to sort by for each property.
	   * @returns {number} Returns the sort order indicator for `object`.
	   */
	  function compareMultiple(object, other, orders) {
	    var index = -1,
	        objCriteria = object.criteria,
	        othCriteria = other.criteria,
	        length = objCriteria.length,
	        ordersLength = orders.length;

	    while (++index < length) {
	      var result = compareAscending(objCriteria[index], othCriteria[index]);
	      if (result) {
	        if (index >= ordersLength) {
	          return result;
	        }
	        var order = orders[index];
	        return result * (order == 'desc' ? -1 : 1);
	      }
	    }
	    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
	    // that causes it, under certain circumstances, to provide the same value for
	    // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
	    // for more details.
	    //
	    // This also ensures a stable sort in V8 and other engines.
	    // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
	    return object.index - other.index;
	  }

	  /**
	   * Gets the number of `placeholder` occurrences in `array`.
	   *
	   * @private
	   * @param {Array} array The array to inspect.
	   * @param {*} placeholder The placeholder to search for.
	   * @returns {number} Returns the placeholder count.
	   */
	  function countHolders(array, placeholder) {
	    var length = array.length,
	        result = 0;

	    while (length--) {
	      if (array[length] === placeholder) {
	        result++;
	      }
	    }
	    return result;
	  }

	  /**
	   * Creates a function that performs a mathematical operation on two values.
	   *
	   * @private
	   * @param {Function} operator The function to perform the operation.
	   * @returns {Function} Returns the new mathematical operation function.
	   */
	  function createMathOperation(operator) {
	    return function(value, other) {
	      var result;
	      if (value === undefined && other === undefined) {
	        return 0;
	      }
	      if (value !== undefined) {
	        result = value;
	      }
	      if (other !== undefined) {
	        result = result === undefined ? other : operator(result, other);
	      }
	      return result;
	    };
	  }

	  /**
	   * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
	   *
	   * @private
	   * @param {string} letter The matched letter to deburr.
	   * @returns {string} Returns the deburred letter.
	   */
	  function deburrLetter(letter) {
	    return deburredLetters[letter];
	  }

	  /**
	   * Used by `_.escape` to convert characters to HTML entities.
	   *
	   * @private
	   * @param {string} chr The matched character to escape.
	   * @returns {string} Returns the escaped character.
	   */
	  function escapeHtmlChar(chr) {
	    return htmlEscapes[chr];
	  }

	  /**
	   * Used by `_.template` to escape characters for inclusion in compiled string literals.
	   *
	   * @private
	   * @param {string} chr The matched character to escape.
	   * @returns {string} Returns the escaped character.
	   */
	  function escapeStringChar(chr) {
	    return '\\' + stringEscapes[chr];
	  }

	  /**
	   * Gets the index at which the first occurrence of `NaN` is found in `array`.
	   *
	   * @private
	   * @param {Array} array The array to search.
	   * @param {number} fromIndex The index to search from.
	   * @param {boolean} [fromRight] Specify iterating from right to left.
	   * @returns {number} Returns the index of the matched `NaN`, else `-1`.
	   */
	  function indexOfNaN(array, fromIndex, fromRight) {
	    var length = array.length,
	        index = fromIndex + (fromRight ? 0 : -1);

	    while ((fromRight ? index-- : ++index < length)) {
	      var other = array[index];
	      if (other !== other) {
	        return index;
	      }
	    }
	    return -1;
	  }

	  /**
	   * Checks if `value` is a host object in IE < 9.
	   *
	   * @private
	   * @param {*} value The value to check.
	   * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
	   */
	  function isHostObject(value) {
	    // Many host objects are `Object` objects that can coerce to strings
	    // despite having improperly defined `toString` methods.
	    var result = false;
	    if (value != null && typeof value.toString != 'function') {
	      try {
	        result = !!(value + '');
	      } catch (e) {}
	    }
	    return result;
	  }

	  /**
	   * Checks if `value` is a valid array-like index.
	   *
	   * @private
	   * @param {*} value The value to check.
	   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
	   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
	   */
	  function isIndex(value, length) {
	    value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
	    length = length == null ? MAX_SAFE_INTEGER : length;
	    return value > -1 && value % 1 == 0 && value < length;
	  }

	  /**
	   * Converts `iterator` to an array.
	   *
	   * @private
	   * @param {Object} iterator The iterator to convert.
	   * @returns {Array} Returns the converted array.
	   */
	  function iteratorToArray(iterator) {
	    var data,
	        result = [];

	    while (!(data = iterator.next()).done) {
	      result.push(data.value);
	    }
	    return result;
	  }

	  /**
	   * Converts `map` to an array.
	   *
	   * @private
	   * @param {Object} map The map to convert.
	   * @returns {Array} Returns the converted array.
	   */
	  function mapToArray(map) {
	    var index = -1,
	        result = Array(map.size);

	    map.forEach(function(value, key) {
	      result[++index] = [key, value];
	    });
	    return result;
	  }

	  /**
	   * Replaces all `placeholder` elements in `array` with an internal placeholder
	   * and returns an array of their indexes.
	   *
	   * @private
	   * @param {Array} array The array to modify.
	   * @param {*} placeholder The placeholder to replace.
	   * @returns {Array} Returns the new array of placeholder indexes.
	   */
	  function replaceHolders(array, placeholder) {
	    var index = -1,
	        length = array.length,
	        resIndex = 0,
	        result = [];

	    while (++index < length) {
	      var value = array[index];
	      if (value === placeholder || value === PLACEHOLDER) {
	        array[index] = PLACEHOLDER;
	        result[resIndex++] = index;
	      }
	    }
	    return result;
	  }

	  /**
	   * Converts `set` to an array.
	   *
	   * @private
	   * @param {Object} set The set to convert.
	   * @returns {Array} Returns the converted array.
	   */
	  function setToArray(set) {
	    var index = -1,
	        result = Array(set.size);

	    set.forEach(function(value) {
	      result[++index] = value;
	    });
	    return result;
	  }

	  /**
	   * Gets the number of symbols in `string`.
	   *
	   * @private
	   * @param {string} string The string to inspect.
	   * @returns {number} Returns the string size.
	   */
	  function stringSize(string) {
	    if (!(string && reHasComplexSymbol.test(string))) {
	      return string.length;
	    }
	    var result = reComplexSymbol.lastIndex = 0;
	    while (reComplexSymbol.test(string)) {
	      result++;
	    }
	    return result;
	  }

	  /**
	   * Converts `string` to an array.
	   *
	   * @private
	   * @param {string} string The string to convert.
	   * @returns {Array} Returns the converted array.
	   */
	  function stringToArray(string) {
	    return string.match(reComplexSymbol);
	  }

	  /**
	   * Used by `_.unescape` to convert HTML entities to characters.
	   *
	   * @private
	   * @param {string} chr The matched character to unescape.
	   * @returns {string} Returns the unescaped character.
	   */
	  function unescapeHtmlChar(chr) {
	    return htmlUnescapes[chr];
	  }

	  /*--------------------------------------------------------------------------*/

	  /**
	   * Create a new pristine `lodash` function using the `context` object.
	   *
	   * @static
	   * @memberOf _
	   * @since 1.1.0
	   * @category Util
	   * @param {Object} [context=root] The context object.
	   * @returns {Function} Returns a new `lodash` function.
	   * @example
	   *
	   * _.mixin({ 'foo': _.constant('foo') });
	   *
	   * var lodash = _.runInContext();
	   * lodash.mixin({ 'bar': lodash.constant('bar') });
	   *
	   * _.isFunction(_.foo);
	   * // => true
	   * _.isFunction(_.bar);
	   * // => false
	   *
	   * lodash.isFunction(lodash.foo);
	   * // => false
	   * lodash.isFunction(lodash.bar);
	   * // => true
	   *
	   * // Use `context` to mock `Date#getTime` use in `_.now`.
	   * var mock = _.runInContext({
	   *   'Date': function() {
	   *     return { 'getTime': getTimeMock };
	   *   }
	   * });
	   *
	   * // Create a suped-up `defer` in Node.js.
	   * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
	   */
	  function runInContext(context) {
	    context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root;

	    /** Built-in constructor references. */
	    var Date = context.Date,
	        Error = context.Error,
	        Math = context.Math,
	        RegExp = context.RegExp,
	        TypeError = context.TypeError;

	    /** Used for built-in method references. */
	    var arrayProto = context.Array.prototype,
	        objectProto = context.Object.prototype,
	        stringProto = context.String.prototype;

	    /** Used to resolve the decompiled source of functions. */
	    var funcToString = context.Function.prototype.toString;

	    /** Used to check objects for own properties. */
	    var hasOwnProperty = objectProto.hasOwnProperty;

	    /** Used to generate unique IDs. */
	    var idCounter = 0;

	    /** Used to infer the `Object` constructor. */
	    var objectCtorString = funcToString.call(Object);

	    /**
	     * Used to resolve the
	     * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
	     * of values.
	     */
	    var objectToString = objectProto.toString;

	    /** Used to restore the original `_` reference in `_.noConflict`. */
	    var oldDash = root._;

	    /** Used to detect if a method is native. */
	    var reIsNative = RegExp('^' +
	      funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
	      .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
	    );

	    /** Built-in value references. */
	    var Buffer = moduleExports ? context.Buffer : undefined,
	        Reflect = context.Reflect,
	        Symbol = context.Symbol,
	        Uint8Array = context.Uint8Array,
	        clearTimeout = context.clearTimeout,
	        enumerate = Reflect ? Reflect.enumerate : undefined,
	        getOwnPropertySymbols = Object.getOwnPropertySymbols,
	        iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined,
	        objectCreate = Object.create,
	        propertyIsEnumerable = objectProto.propertyIsEnumerable,
	        setTimeout = context.setTimeout,
	        splice = arrayProto.splice;

	    /* Built-in method references for those with the same name as other `lodash` methods. */
	    var nativeCeil = Math.ceil,
	        nativeFloor = Math.floor,
	        nativeGetPrototype = Object.getPrototypeOf,
	        nativeIsFinite = context.isFinite,
	        nativeJoin = arrayProto.join,
	        nativeKeys = Object.keys,
	        nativeMax = Math.max,
	        nativeMin = Math.min,
	        nativeParseInt = context.parseInt,
	        nativeRandom = Math.random,
	        nativeReplace = stringProto.replace,
	        nativeReverse = arrayProto.reverse,
	        nativeSplit = stringProto.split;

	    /* Built-in method references that are verified to be native. */
	    var DataView = getNative(context, 'DataView'),
	        Map = getNative(context, 'Map'),
	        Promise = getNative(context, 'Promise'),
	        Set = getNative(context, 'Set'),
	        WeakMap = getNative(context, 'WeakMap'),
	        nativeCreate = getNative(Object, 'create');

	    /** Used to store function metadata. */
	    var metaMap = WeakMap && new WeakMap;

	    /** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */
	    var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf');

	    /** Used to lookup unminified function names. */
	    var realNames = {};

	    /** Used to detect maps, sets, and weakmaps. */
	    var dataViewCtorString = toSource(DataView),
	        mapCtorString = toSource(Map),
	        promiseCtorString = toSource(Promise),
	        setCtorString = toSource(Set),
	        weakMapCtorString = toSource(WeakMap);

	    /** Used to convert symbols to primitives and strings. */
	    var symbolProto = Symbol ? Symbol.prototype : undefined,
	        symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
	        symbolToString = symbolProto ? symbolProto.toString : undefined;

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates a `lodash` object which wraps `value` to enable implicit method
	     * chain sequences. Methods that operate on and return arrays, collections,
	     * and functions can be chained together. Methods that retrieve a single value
	     * or may return a primitive value will automatically end the chain sequence
	     * and return the unwrapped value. Otherwise, the value must be unwrapped
	     * with `_#value`.
	     *
	     * Explicit chain sequences, which must be unwrapped with `_#value`, may be
	     * enabled using `_.chain`.
	     *
	     * The execution of chained methods is lazy, that is, it's deferred until
	     * `_#value` is implicitly or explicitly called.
	     *
	     * Lazy evaluation allows several methods to support shortcut fusion.
	     * Shortcut fusion is an optimization to merge iteratee calls; this avoids
	     * the creation of intermediate arrays and can greatly reduce the number of
	     * iteratee executions. Sections of a chain sequence qualify for shortcut
	     * fusion if the section is applied to an array of at least `200` elements
	     * and any iteratees accept only one argument. The heuristic for whether a
	     * section qualifies for shortcut fusion is subject to change.
	     *
	     * Chaining is supported in custom builds as long as the `_#value` method is
	     * directly or indirectly included in the build.
	     *
	     * In addition to lodash methods, wrappers have `Array` and `String` methods.
	     *
	     * The wrapper `Array` methods are:
	     * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
	     *
	     * The wrapper `String` methods are:
	     * `replace` and `split`
	     *
	     * The wrapper methods that support shortcut fusion are:
	     * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
	     * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
	     * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
	     *
	     * The chainable wrapper methods are:
	     * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
	     * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
	     * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
	     * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
	     * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
	     * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
	     * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
	     * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
	     * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
	     * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
	     * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
	     * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
	     * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
	     * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
	     * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
	     * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
	     * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
	     * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
	     * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
	     * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
	     * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
	     * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
	     * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
	     * `zipObject`, `zipObjectDeep`, and `zipWith`
	     *
	     * The wrapper methods that are **not** chainable by default are:
	     * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
	     * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `divide`, `each`,
	     * `eachRight`, `endsWith`, `eq`, `escape`, `escapeRegExp`, `every`, `find`,
	     * `findIndex`, `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `first`,
	     * `floor`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`,
	     * `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`, `head`, `identity`,
	     * `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`, `isArray`,
	     * `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`, `isBuffer`,
	     * `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`, `isError`,
	     * `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`, `isMatch`,
	     * `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`,
	     * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`,
	     * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`,
	     * `join`, `kebabCase`, `last`, `lastIndexOf`, `lowerCase`, `lowerFirst`,
	     * `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, `min`, `minBy`, `multiply`,
	     * `noConflict`, `noop`, `now`, `nth`, `pad`, `padEnd`, `padStart`, `parseInt`,
	     * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `round`,
	     * `runInContext`, `sample`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`,
	     * `sortedIndexBy`, `sortedLastIndex`, `sortedLastIndexBy`, `startCase`,
	     * `startsWith`, `subtract`, `sum`, `sumBy`, `template`, `times`, `toInteger`,
	     * `toJSON`, `toLength`, `toLower`, `toNumber`, `toSafeInteger`, `toString`,
	     * `toUpper`, `trim`, `trimEnd`, `trimStart`, `truncate`, `unescape`,
	     * `uniqueId`, `upperCase`, `upperFirst`, `value`, and `words`
	     *
	     * @name _
	     * @constructor
	     * @category Seq
	     * @param {*} value The value to wrap in a `lodash` instance.
	     * @returns {Object} Returns the new `lodash` wrapper instance.
	     * @example
	     *
	     * function square(n) {
	     *   return n * n;
	     * }
	     *
	     * var wrapped = _([1, 2, 3]);
	     *
	     * // Returns an unwrapped value.
	     * wrapped.reduce(_.add);
	     * // => 6
	     *
	     * // Returns a wrapped value.
	     * var squares = wrapped.map(square);
	     *
	     * _.isArray(squares);
	     * // => false
	     *
	     * _.isArray(squares.value());
	     * // => true
	     */
	    function lodash(value) {
	      if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
	        if (value instanceof LodashWrapper) {
	          return value;
	        }
	        if (hasOwnProperty.call(value, '__wrapped__')) {
	          return wrapperClone(value);
	        }
	      }
	      return new LodashWrapper(value);
	    }

	    /**
	     * The function whose prototype chain sequence wrappers inherit from.
	     *
	     * @private
	     */
	    function baseLodash() {
	      // No operation performed.
	    }

	    /**
	     * The base constructor for creating `lodash` wrapper objects.
	     *
	     * @private
	     * @param {*} value The value to wrap.
	     * @param {boolean} [chainAll] Enable explicit method chain sequences.
	     */
	    function LodashWrapper(value, chainAll) {
	      this.__wrapped__ = value;
	      this.__actions__ = [];
	      this.__chain__ = !!chainAll;
	      this.__index__ = 0;
	      this.__values__ = undefined;
	    }

	    /**
	     * By default, the template delimiters used by lodash are like those in
	     * embedded Ruby (ERB). Change the following template settings to use
	     * alternative delimiters.
	     *
	     * @static
	     * @memberOf _
	     * @type {Object}
	     */
	    lodash.templateSettings = {

	      /**
	       * Used to detect `data` property values to be HTML-escaped.
	       *
	       * @memberOf _.templateSettings
	       * @type {RegExp}
	       */
	      'escape': reEscape,

	      /**
	       * Used to detect code to be evaluated.
	       *
	       * @memberOf _.templateSettings
	       * @type {RegExp}
	       */
	      'evaluate': reEvaluate,

	      /**
	       * Used to detect `data` property values to inject.
	       *
	       * @memberOf _.templateSettings
	       * @type {RegExp}
	       */
	      'interpolate': reInterpolate,

	      /**
	       * Used to reference the data object in the template text.
	       *
	       * @memberOf _.templateSettings
	       * @type {string}
	       */
	      'variable': '',

	      /**
	       * Used to import variables into the compiled template.
	       *
	       * @memberOf _.templateSettings
	       * @type {Object}
	       */
	      'imports': {

	        /**
	         * A reference to the `lodash` function.
	         *
	         * @memberOf _.templateSettings.imports
	         * @type {Function}
	         */
	        '_': lodash
	      }
	    };

	    // Ensure wrappers are instances of `baseLodash`.
	    lodash.prototype = baseLodash.prototype;
	    lodash.prototype.constructor = lodash;

	    LodashWrapper.prototype = baseCreate(baseLodash.prototype);
	    LodashWrapper.prototype.constructor = LodashWrapper;

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
	     *
	     * @private
	     * @constructor
	     * @param {*} value The value to wrap.
	     */
	    function LazyWrapper(value) {
	      this.__wrapped__ = value;
	      this.__actions__ = [];
	      this.__dir__ = 1;
	      this.__filtered__ = false;
	      this.__iteratees__ = [];
	      this.__takeCount__ = MAX_ARRAY_LENGTH;
	      this.__views__ = [];
	    }

	    /**
	     * Creates a clone of the lazy wrapper object.
	     *
	     * @private
	     * @name clone
	     * @memberOf LazyWrapper
	     * @returns {Object} Returns the cloned `LazyWrapper` object.
	     */
	    function lazyClone() {
	      var result = new LazyWrapper(this.__wrapped__);
	      result.__actions__ = copyArray(this.__actions__);
	      result.__dir__ = this.__dir__;
	      result.__filtered__ = this.__filtered__;
	      result.__iteratees__ = copyArray(this.__iteratees__);
	      result.__takeCount__ = this.__takeCount__;
	      result.__views__ = copyArray(this.__views__);
	      return result;
	    }

	    /**
	     * Reverses the direction of lazy iteration.
	     *
	     * @private
	     * @name reverse
	     * @memberOf LazyWrapper
	     * @returns {Object} Returns the new reversed `LazyWrapper` object.
	     */
	    function lazyReverse() {
	      if (this.__filtered__) {
	        var result = new LazyWrapper(this);
	        result.__dir__ = -1;
	        result.__filtered__ = true;
	      } else {
	        result = this.clone();
	        result.__dir__ *= -1;
	      }
	      return result;
	    }

	    /**
	     * Extracts the unwrapped value from its lazy wrapper.
	     *
	     * @private
	     * @name value
	     * @memberOf LazyWrapper
	     * @returns {*} Returns the unwrapped value.
	     */
	    function lazyValue() {
	      var array = this.__wrapped__.value(),
	          dir = this.__dir__,
	          isArr = isArray(array),
	          isRight = dir < 0,
	          arrLength = isArr ? array.length : 0,
	          view = getView(0, arrLength, this.__views__),
	          start = view.start,
	          end = view.end,
	          length = end - start,
	          index = isRight ? end : (start - 1),
	          iteratees = this.__iteratees__,
	          iterLength = iteratees.length,
	          resIndex = 0,
	          takeCount = nativeMin(length, this.__takeCount__);

	      if (!isArr || arrLength < LARGE_ARRAY_SIZE ||
	          (arrLength == length && takeCount == length)) {
	        return baseWrapperValue(array, this.__actions__);
	      }
	      var result = [];

	      outer:
	      while (length-- && resIndex < takeCount) {
	        index += dir;

	        var iterIndex = -1,
	            value = array[index];

	        while (++iterIndex < iterLength) {
	          var data = iteratees[iterIndex],
	              iteratee = data.iteratee,
	              type = data.type,
	              computed = iteratee(value);

	          if (type == LAZY_MAP_FLAG) {
	            value = computed;
	          } else if (!computed) {
	            if (type == LAZY_FILTER_FLAG) {
	              continue outer;
	            } else {
	              break outer;
	            }
	          }
	        }
	        result[resIndex++] = value;
	      }
	      return result;
	    }

	    // Ensure `LazyWrapper` is an instance of `baseLodash`.
	    LazyWrapper.prototype = baseCreate(baseLodash.prototype);
	    LazyWrapper.prototype.constructor = LazyWrapper;

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates a hash object.
	     *
	     * @private
	     * @constructor
	     * @returns {Object} Returns the new hash object.
	     */
	    function Hash() {}

	    /**
	     * Removes `key` and its value from the hash.
	     *
	     * @private
	     * @param {Object} hash The hash to modify.
	     * @param {string} key The key of the value to remove.
	     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	     */
	    function hashDelete(hash, key) {
	      return hashHas(hash, key) && delete hash[key];
	    }

	    /**
	     * Gets the hash value for `key`.
	     *
	     * @private
	     * @param {Object} hash The hash to query.
	     * @param {string} key The key of the value to get.
	     * @returns {*} Returns the entry value.
	     */
	    function hashGet(hash, key) {
	      if (nativeCreate) {
	        var result = hash[key];
	        return result === HASH_UNDEFINED ? undefined : result;
	      }
	      return hasOwnProperty.call(hash, key) ? hash[key] : undefined;
	    }

	    /**
	     * Checks if a hash value for `key` exists.
	     *
	     * @private
	     * @param {Object} hash The hash to query.
	     * @param {string} key The key of the entry to check.
	     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	     */
	    function hashHas(hash, key) {
	      return nativeCreate ? hash[key] !== undefined : hasOwnProperty.call(hash, key);
	    }

	    /**
	     * Sets the hash `key` to `value`.
	     *
	     * @private
	     * @param {Object} hash The hash to modify.
	     * @param {string} key The key of the value to set.
	     * @param {*} value The value to set.
	     */
	    function hashSet(hash, key, value) {
	      hash[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
	    }

	    // Avoid inheriting from `Object.prototype` when possible.
	    Hash.prototype = nativeCreate ? nativeCreate(null) : objectProto;

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates a map cache object to store key-value pairs.
	     *
	     * @private
	     * @constructor
	     * @param {Array} [values] The values to cache.
	     */
	    function MapCache(values) {
	      var index = -1,
	          length = values ? values.length : 0;

	      this.clear();
	      while (++index < length) {
	        var entry = values[index];
	        this.set(entry[0], entry[1]);
	      }
	    }

	    /**
	     * Removes all key-value entries from the map.
	     *
	     * @private
	     * @name clear
	     * @memberOf MapCache
	     */
	    function mapClear() {
	      this.__data__ = {
	        'hash': new Hash,
	        'map': Map ? new Map : [],
	        'string': new Hash
	      };
	    }

	    /**
	     * Removes `key` and its value from the map.
	     *
	     * @private
	     * @name delete
	     * @memberOf MapCache
	     * @param {string} key The key of the value to remove.
	     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	     */
	    function mapDelete(key) {
	      var data = this.__data__;
	      if (isKeyable(key)) {
	        return hashDelete(typeof key == 'string' ? data.string : data.hash, key);
	      }
	      return Map ? data.map['delete'](key) : assocDelete(data.map, key);
	    }

	    /**
	     * Gets the map value for `key`.
	     *
	     * @private
	     * @name get
	     * @memberOf MapCache
	     * @param {string} key The key of the value to get.
	     * @returns {*} Returns the entry value.
	     */
	    function mapGet(key) {
	      var data = this.__data__;
	      if (isKeyable(key)) {
	        return hashGet(typeof key == 'string' ? data.string : data.hash, key);
	      }
	      return Map ? data.map.get(key) : assocGet(data.map, key);
	    }

	    /**
	     * Checks if a map value for `key` exists.
	     *
	     * @private
	     * @name has
	     * @memberOf MapCache
	     * @param {string} key The key of the entry to check.
	     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	     */
	    function mapHas(key) {
	      var data = this.__data__;
	      if (isKeyable(key)) {
	        return hashHas(typeof key == 'string' ? data.string : data.hash, key);
	      }
	      return Map ? data.map.has(key) : assocHas(data.map, key);
	    }

	    /**
	     * Sets the map `key` to `value`.
	     *
	     * @private
	     * @name set
	     * @memberOf MapCache
	     * @param {string} key The key of the value to set.
	     * @param {*} value The value to set.
	     * @returns {Object} Returns the map cache instance.
	     */
	    function mapSet(key, value) {
	      var data = this.__data__;
	      if (isKeyable(key)) {
	        hashSet(typeof key == 'string' ? data.string : data.hash, key, value);
	      } else if (Map) {
	        data.map.set(key, value);
	      } else {
	        assocSet(data.map, key, value);
	      }
	      return this;
	    }

	    // Add methods to `MapCache`.
	    MapCache.prototype.clear = mapClear;
	    MapCache.prototype['delete'] = mapDelete;
	    MapCache.prototype.get = mapGet;
	    MapCache.prototype.has = mapHas;
	    MapCache.prototype.set = mapSet;

	    /*------------------------------------------------------------------------*/

	    /**
	     *
	     * Creates a set cache object to store unique values.
	     *
	     * @private
	     * @constructor
	     * @param {Array} [values] The values to cache.
	     */
	    function SetCache(values) {
	      var index = -1,
	          length = values ? values.length : 0;

	      this.__data__ = new MapCache;
	      while (++index < length) {
	        this.push(values[index]);
	      }
	    }

	    /**
	     * Checks if `value` is in `cache`.
	     *
	     * @private
	     * @param {Object} cache The set cache to search.
	     * @param {*} value The value to search for.
	     * @returns {number} Returns `true` if `value` is found, else `false`.
	     */
	    function cacheHas(cache, value) {
	      var map = cache.__data__;
	      if (isKeyable(value)) {
	        var data = map.__data__,
	            hash = typeof value == 'string' ? data.string : data.hash;

	        return hash[value] === HASH_UNDEFINED;
	      }
	      return map.has(value);
	    }

	    /**
	     * Adds `value` to the set cache.
	     *
	     * @private
	     * @name push
	     * @memberOf SetCache
	     * @param {*} value The value to cache.
	     */
	    function cachePush(value) {
	      var map = this.__data__;
	      if (isKeyable(value)) {
	        var data = map.__data__,
	            hash = typeof value == 'string' ? data.string : data.hash;

	        hash[value] = HASH_UNDEFINED;
	      }
	      else {
	        map.set(value, HASH_UNDEFINED);
	      }
	    }

	    // Add methods to `SetCache`.
	    SetCache.prototype.push = cachePush;

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates a stack cache object to store key-value pairs.
	     *
	     * @private
	     * @constructor
	     * @param {Array} [values] The values to cache.
	     */
	    function Stack(values) {
	      var index = -1,
	          length = values ? values.length : 0;

	      this.clear();
	      while (++index < length) {
	        var entry = values[index];
	        this.set(entry[0], entry[1]);
	      }
	    }

	    /**
	     * Removes all key-value entries from the stack.
	     *
	     * @private
	     * @name clear
	     * @memberOf Stack
	     */
	    function stackClear() {
	      this.__data__ = { 'array': [], 'map': null };
	    }

	    /**
	     * Removes `key` and its value from the stack.
	     *
	     * @private
	     * @name delete
	     * @memberOf Stack
	     * @param {string} key The key of the value to remove.
	     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	     */
	    function stackDelete(key) {
	      var data = this.__data__,
	          array = data.array;

	      return array ? assocDelete(array, key) : data.map['delete'](key);
	    }

	    /**
	     * Gets the stack value for `key`.
	     *
	     * @private
	     * @name get
	     * @memberOf Stack
	     * @param {string} key The key of the value to get.
	     * @returns {*} Returns the entry value.
	     */
	    function stackGet(key) {
	      var data = this.__data__,
	          array = data.array;

	      return array ? assocGet(array, key) : data.map.get(key);
	    }

	    /**
	     * Checks if a stack value for `key` exists.
	     *
	     * @private
	     * @name has
	     * @memberOf Stack
	     * @param {string} key The key of the entry to check.
	     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	     */
	    function stackHas(key) {
	      var data = this.__data__,
	          array = data.array;

	      return array ? assocHas(array, key) : data.map.has(key);
	    }

	    /**
	     * Sets the stack `key` to `value`.
	     *
	     * @private
	     * @name set
	     * @memberOf Stack
	     * @param {string} key The key of the value to set.
	     * @param {*} value The value to set.
	     * @returns {Object} Returns the stack cache instance.
	     */
	    function stackSet(key, value) {
	      var data = this.__data__,
	          array = data.array;

	      if (array) {
	        if (array.length < (LARGE_ARRAY_SIZE - 1)) {
	          assocSet(array, key, value);
	        } else {
	          data.array = null;
	          data.map = new MapCache(array);
	        }
	      }
	      var map = data.map;
	      if (map) {
	        map.set(key, value);
	      }
	      return this;
	    }

	    // Add methods to `Stack`.
	    Stack.prototype.clear = stackClear;
	    Stack.prototype['delete'] = stackDelete;
	    Stack.prototype.get = stackGet;
	    Stack.prototype.has = stackHas;
	    Stack.prototype.set = stackSet;

	    /*------------------------------------------------------------------------*/

	    /**
	     * Removes `key` and its value from the associative array.
	     *
	     * @private
	     * @param {Array} array The array to modify.
	     * @param {string} key The key of the value to remove.
	     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	     */
	    function assocDelete(array, key) {
	      var index = assocIndexOf(array, key);
	      if (index < 0) {
	        return false;
	      }
	      var lastIndex = array.length - 1;
	      if (index == lastIndex) {
	        array.pop();
	      } else {
	        splice.call(array, index, 1);
	      }
	      return true;
	    }

	    /**
	     * Gets the associative array value for `key`.
	     *
	     * @private
	     * @param {Array} array The array to query.
	     * @param {string} key The key of the value to get.
	     * @returns {*} Returns the entry value.
	     */
	    function assocGet(array, key) {
	      var index = assocIndexOf(array, key);
	      return index < 0 ? undefined : array[index][1];
	    }

	    /**
	     * Checks if an associative array value for `key` exists.
	     *
	     * @private
	     * @param {Array} array The array to query.
	     * @param {string} key The key of the entry to check.
	     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	     */
	    function assocHas(array, key) {
	      return assocIndexOf(array, key) > -1;
	    }

	    /**
	     * Gets the index at which the `key` is found in `array` of key-value pairs.
	     *
	     * @private
	     * @param {Array} array The array to search.
	     * @param {*} key The key to search for.
	     * @returns {number} Returns the index of the matched value, else `-1`.
	     */
	    function assocIndexOf(array, key) {
	      var length = array.length;
	      while (length--) {
	        if (eq(array[length][0], key)) {
	          return length;
	        }
	      }
	      return -1;
	    }

	    /**
	     * Sets the associative array `key` to `value`.
	     *
	     * @private
	     * @param {Array} array The array to modify.
	     * @param {string} key The key of the value to set.
	     * @param {*} value The value to set.
	     */
	    function assocSet(array, key, value) {
	      var index = assocIndexOf(array, key);
	      if (index < 0) {
	        array.push([key, value]);
	      } else {
	        array[index][1] = value;
	      }
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Used by `_.defaults` to customize its `_.assignIn` use.
	     *
	     * @private
	     * @param {*} objValue The destination value.
	     * @param {*} srcValue The source value.
	     * @param {string} key The key of the property to assign.
	     * @param {Object} object The parent object of `objValue`.
	     * @returns {*} Returns the value to assign.
	     */
	    function assignInDefaults(objValue, srcValue, key, object) {
	      if (objValue === undefined ||
	          (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
	        return srcValue;
	      }
	      return objValue;
	    }

	    /**
	     * This function is like `assignValue` except that it doesn't assign
	     * `undefined` values.
	     *
	     * @private
	     * @param {Object} object The object to modify.
	     * @param {string} key The key of the property to assign.
	     * @param {*} value The value to assign.
	     */
	    function assignMergeValue(object, key, value) {
	      if ((value !== undefined && !eq(object[key], value)) ||
	          (typeof key == 'number' && value === undefined && !(key in object))) {
	        object[key] = value;
	      }
	    }

	    /**
	     * Assigns `value` to `key` of `object` if the existing value is not equivalent
	     * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons.
	     *
	     * @private
	     * @param {Object} object The object to modify.
	     * @param {string} key The key of the property to assign.
	     * @param {*} value The value to assign.
	     */
	    function assignValue(object, key, value) {
	      var objValue = object[key];
	      if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
	          (value === undefined && !(key in object))) {
	        object[key] = value;
	      }
	    }

	    /**
	     * Aggregates elements of `collection` on `accumulator` with keys transformed
	     * by `iteratee` and values set by `setter`.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} setter The function to set `accumulator` values.
	     * @param {Function} iteratee The iteratee to transform keys.
	     * @param {Object} accumulator The initial aggregated object.
	     * @returns {Function} Returns `accumulator`.
	     */
	    function baseAggregator(collection, setter, iteratee, accumulator) {
	      baseEach(collection, function(value, key, collection) {
	        setter(accumulator, value, iteratee(value), collection);
	      });
	      return accumulator;
	    }

	    /**
	     * The base implementation of `_.assign` without support for multiple sources
	     * or `customizer` functions.
	     *
	     * @private
	     * @param {Object} object The destination object.
	     * @param {Object} source The source object.
	     * @returns {Object} Returns `object`.
	     */
	    function baseAssign(object, source) {
	      return object && copyObject(source, keys(source), object);
	    }

	    /**
	     * The base implementation of `_.at` without support for individual paths.
	     *
	     * @private
	     * @param {Object} object The object to iterate over.
	     * @param {string[]} paths The property paths of elements to pick.
	     * @returns {Array} Returns the new array of picked elements.
	     */
	    function baseAt(object, paths) {
	      var index = -1,
	          isNil = object == null,
	          length = paths.length,
	          result = Array(length);

	      while (++index < length) {
	        result[index] = isNil ? undefined : get(object, paths[index]);
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.clamp` which doesn't coerce arguments to numbers.
	     *
	     * @private
	     * @param {number} number The number to clamp.
	     * @param {number} [lower] The lower bound.
	     * @param {number} upper The upper bound.
	     * @returns {number} Returns the clamped number.
	     */
	    function baseClamp(number, lower, upper) {
	      if (number === number) {
	        if (upper !== undefined) {
	          number = number <= upper ? number : upper;
	        }
	        if (lower !== undefined) {
	          number = number >= lower ? number : lower;
	        }
	      }
	      return number;
	    }

	    /**
	     * The base implementation of `_.clone` and `_.cloneDeep` which tracks
	     * traversed objects.
	     *
	     * @private
	     * @param {*} value The value to clone.
	     * @param {boolean} [isDeep] Specify a deep clone.
	     * @param {boolean} [isFull] Specify a clone including symbols.
	     * @param {Function} [customizer] The function to customize cloning.
	     * @param {string} [key] The key of `value`.
	     * @param {Object} [object] The parent object of `value`.
	     * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
	     * @returns {*} Returns the cloned value.
	     */
	    function baseClone(value, isDeep, isFull, customizer, key, object, stack) {
	      var result;
	      if (customizer) {
	        result = object ? customizer(value, key, object, stack) : customizer(value);
	      }
	      if (result !== undefined) {
	        return result;
	      }
	      if (!isObject(value)) {
	        return value;
	      }
	      var isArr = isArray(value);
	      if (isArr) {
	        result = initCloneArray(value);
	        if (!isDeep) {
	          return copyArray(value, result);
	        }
	      } else {
	        var tag = getTag(value),
	            isFunc = tag == funcTag || tag == genTag;

	        if (isBuffer(value)) {
	          return cloneBuffer(value, isDeep);
	        }
	        if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
	          if (isHostObject(value)) {
	            return object ? value : {};
	          }
	          result = initCloneObject(isFunc ? {} : value);
	          if (!isDeep) {
	            return copySymbols(value, baseAssign(result, value));
	          }
	        } else {
	          if (!cloneableTags[tag]) {
	            return object ? value : {};
	          }
	          result = initCloneByTag(value, tag, baseClone, isDeep);
	        }
	      }
	      // Check for circular references and return its corresponding clone.
	      stack || (stack = new Stack);
	      var stacked = stack.get(value);
	      if (stacked) {
	        return stacked;
	      }
	      stack.set(value, result);

	      if (!isArr) {
	        var props = isFull ? getAllKeys(value) : keys(value);
	      }
	      // Recursively populate clone (susceptible to call stack limits).
	      arrayEach(props || value, function(subValue, key) {
	        if (props) {
	          key = subValue;
	          subValue = value[key];
	        }
	        assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack));
	      });
	      return result;
	    }

	    /**
	     * The base implementation of `_.conforms` which doesn't clone `source`.
	     *
	     * @private
	     * @param {Object} source The object of property predicates to conform to.
	     * @returns {Function} Returns the new function.
	     */
	    function baseConforms(source) {
	      var props = keys(source),
	          length = props.length;

	      return function(object) {
	        if (object == null) {
	          return !length;
	        }
	        var index = length;
	        while (index--) {
	          var key = props[index],
	              predicate = source[key],
	              value = object[key];

	          if ((value === undefined &&
	              !(key in Object(object))) || !predicate(value)) {
	            return false;
	          }
	        }
	        return true;
	      };
	    }

	    /**
	     * The base implementation of `_.create` without support for assigning
	     * properties to the created object.
	     *
	     * @private
	     * @param {Object} prototype The object to inherit from.
	     * @returns {Object} Returns the new object.
	     */
	    function baseCreate(proto) {
	      return isObject(proto) ? objectCreate(proto) : {};
	    }

	    /**
	     * The base implementation of `_.delay` and `_.defer` which accepts an array
	     * of `func` arguments.
	     *
	     * @private
	     * @param {Function} func The function to delay.
	     * @param {number} wait The number of milliseconds to delay invocation.
	     * @param {Object} args The arguments to provide to `func`.
	     * @returns {number} Returns the timer id.
	     */
	    function baseDelay(func, wait, args) {
	      if (typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      return setTimeout(function() { func.apply(undefined, args); }, wait);
	    }

	    /**
	     * The base implementation of methods like `_.difference` without support
	     * for excluding multiple arrays or iteratee shorthands.
	     *
	     * @private
	     * @param {Array} array The array to inspect.
	     * @param {Array} values The values to exclude.
	     * @param {Function} [iteratee] The iteratee invoked per element.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new array of filtered values.
	     */
	    function baseDifference(array, values, iteratee, comparator) {
	      var index = -1,
	          includes = arrayIncludes,
	          isCommon = true,
	          length = array.length,
	          result = [],
	          valuesLength = values.length;

	      if (!length) {
	        return result;
	      }
	      if (iteratee) {
	        values = arrayMap(values, baseUnary(iteratee));
	      }
	      if (comparator) {
	        includes = arrayIncludesWith;
	        isCommon = false;
	      }
	      else if (values.length >= LARGE_ARRAY_SIZE) {
	        includes = cacheHas;
	        isCommon = false;
	        values = new SetCache(values);
	      }
	      outer:
	      while (++index < length) {
	        var value = array[index],
	            computed = iteratee ? iteratee(value) : value;

	        if (isCommon && computed === computed) {
	          var valuesIndex = valuesLength;
	          while (valuesIndex--) {
	            if (values[valuesIndex] === computed) {
	              continue outer;
	            }
	          }
	          result.push(value);
	        }
	        else if (!includes(values, computed, comparator)) {
	          result.push(value);
	        }
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.forEach` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} iteratee The function invoked per iteration.
	     * @returns {Array|Object} Returns `collection`.
	     */
	    var baseEach = createBaseEach(baseForOwn);

	    /**
	     * The base implementation of `_.forEachRight` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} iteratee The function invoked per iteration.
	     * @returns {Array|Object} Returns `collection`.
	     */
	    var baseEachRight = createBaseEach(baseForOwnRight, true);

	    /**
	     * The base implementation of `_.every` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} predicate The function invoked per iteration.
	     * @returns {boolean} Returns `true` if all elements pass the predicate check,
	     *  else `false`
	     */
	    function baseEvery(collection, predicate) {
	      var result = true;
	      baseEach(collection, function(value, index, collection) {
	        result = !!predicate(value, index, collection);
	        return result;
	      });
	      return result;
	    }

	    /**
	     * The base implementation of `_.fill` without an iteratee call guard.
	     *
	     * @private
	     * @param {Array} array The array to fill.
	     * @param {*} value The value to fill `array` with.
	     * @param {number} [start=0] The start position.
	     * @param {number} [end=array.length] The end position.
	     * @returns {Array} Returns `array`.
	     */
	    function baseFill(array, value, start, end) {
	      var length = array.length;

	      start = toInteger(start);
	      if (start < 0) {
	        start = -start > length ? 0 : (length + start);
	      }
	      end = (end === undefined || end > length) ? length : toInteger(end);
	      if (end < 0) {
	        end += length;
	      }
	      end = start > end ? 0 : toLength(end);
	      while (start < end) {
	        array[start++] = value;
	      }
	      return array;
	    }

	    /**
	     * The base implementation of `_.filter` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} predicate The function invoked per iteration.
	     * @returns {Array} Returns the new filtered array.
	     */
	    function baseFilter(collection, predicate) {
	      var result = [];
	      baseEach(collection, function(value, index, collection) {
	        if (predicate(value, index, collection)) {
	          result.push(value);
	        }
	      });
	      return result;
	    }

	    /**
	     * The base implementation of `_.flatten` with support for restricting flattening.
	     *
	     * @private
	     * @param {Array} array The array to flatten.
	     * @param {number} depth The maximum recursion depth.
	     * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
	     * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
	     * @param {Array} [result=[]] The initial result value.
	     * @returns {Array} Returns the new flattened array.
	     */
	    function baseFlatten(array, depth, predicate, isStrict, result) {
	      var index = -1,
	          length = array.length;

	      predicate || (predicate = isFlattenable);
	      result || (result = []);

	      while (++index < length) {
	        var value = array[index];
	        if (depth > 0 && predicate(value)) {
	          if (depth > 1) {
	            // Recursively flatten arrays (susceptible to call stack limits).
	            baseFlatten(value, depth - 1, predicate, isStrict, result);
	          } else {
	            arrayPush(result, value);
	          }
	        } else if (!isStrict) {
	          result[result.length] = value;
	        }
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `baseForOwn` which iterates over `object`
	     * properties returned by `keysFunc` and invokes `iteratee` for each property.
	     * Iteratee functions may exit iteration early by explicitly returning `false`.
	     *
	     * @private
	     * @param {Object} object The object to iterate over.
	     * @param {Function} iteratee The function invoked per iteration.
	     * @param {Function} keysFunc The function to get the keys of `object`.
	     * @returns {Object} Returns `object`.
	     */
	    var baseFor = createBaseFor();

	    /**
	     * This function is like `baseFor` except that it iterates over properties
	     * in the opposite order.
	     *
	     * @private
	     * @param {Object} object The object to iterate over.
	     * @param {Function} iteratee The function invoked per iteration.
	     * @param {Function} keysFunc The function to get the keys of `object`.
	     * @returns {Object} Returns `object`.
	     */
	    var baseForRight = createBaseFor(true);

	    /**
	     * The base implementation of `_.forOwn` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Object} object The object to iterate over.
	     * @param {Function} iteratee The function invoked per iteration.
	     * @returns {Object} Returns `object`.
	     */
	    function baseForOwn(object, iteratee) {
	      return object && baseFor(object, iteratee, keys);
	    }

	    /**
	     * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Object} object The object to iterate over.
	     * @param {Function} iteratee The function invoked per iteration.
	     * @returns {Object} Returns `object`.
	     */
	    function baseForOwnRight(object, iteratee) {
	      return object && baseForRight(object, iteratee, keys);
	    }

	    /**
	     * The base implementation of `_.functions` which creates an array of
	     * `object` function property names filtered from `props`.
	     *
	     * @private
	     * @param {Object} object The object to inspect.
	     * @param {Array} props The property names to filter.
	     * @returns {Array} Returns the new array of filtered property names.
	     */
	    function baseFunctions(object, props) {
	      return arrayFilter(props, function(key) {
	        return isFunction(object[key]);
	      });
	    }

	    /**
	     * The base implementation of `_.get` without support for default values.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path of the property to get.
	     * @returns {*} Returns the resolved value.
	     */
	    function baseGet(object, path) {
	      path = isKey(path, object) ? [path] : castPath(path);

	      var index = 0,
	          length = path.length;

	      while (object != null && index < length) {
	        object = object[path[index++]];
	      }
	      return (index && index == length) ? object : undefined;
	    }

	    /**
	     * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
	     * `keysFunc` and `symbolsFunc` to get the enumerable property names and
	     * symbols of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Function} keysFunc The function to get the keys of `object`.
	     * @param {Function} symbolsFunc The function to get the symbols of `object`.
	     * @returns {Array} Returns the array of property names and symbols.
	     */
	    function baseGetAllKeys(object, keysFunc, symbolsFunc) {
	      var result = keysFunc(object);
	      return isArray(object)
	        ? result
	        : arrayPush(result, symbolsFunc(object));
	    }

	    /**
	     * The base implementation of `_.has` without support for deep paths.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array|string} key The key to check.
	     * @returns {boolean} Returns `true` if `key` exists, else `false`.
	     */
	    function baseHas(object, key) {
	      // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`,
	      // that are composed entirely of index properties, return `false` for
	      // `hasOwnProperty` checks of them.
	      return hasOwnProperty.call(object, key) ||
	        (typeof object == 'object' && key in object && getPrototype(object) === null);
	    }

	    /**
	     * The base implementation of `_.hasIn` without support for deep paths.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array|string} key The key to check.
	     * @returns {boolean} Returns `true` if `key` exists, else `false`.
	     */
	    function baseHasIn(object, key) {
	      return key in Object(object);
	    }

	    /**
	     * The base implementation of `_.inRange` which doesn't coerce arguments to numbers.
	     *
	     * @private
	     * @param {number} number The number to check.
	     * @param {number} start The start of the range.
	     * @param {number} end The end of the range.
	     * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
	     */
	    function baseInRange(number, start, end) {
	      return number >= nativeMin(start, end) && number < nativeMax(start, end);
	    }

	    /**
	     * The base implementation of methods like `_.intersection`, without support
	     * for iteratee shorthands, that accepts an array of arrays to inspect.
	     *
	     * @private
	     * @param {Array} arrays The arrays to inspect.
	     * @param {Function} [iteratee] The iteratee invoked per element.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new array of shared values.
	     */
	    function baseIntersection(arrays, iteratee, comparator) {
	      var includes = comparator ? arrayIncludesWith : arrayIncludes,
	          length = arrays[0].length,
	          othLength = arrays.length,
	          othIndex = othLength,
	          caches = Array(othLength),
	          maxLength = Infinity,
	          result = [];

	      while (othIndex--) {
	        var array = arrays[othIndex];
	        if (othIndex && iteratee) {
	          array = arrayMap(array, baseUnary(iteratee));
	        }
	        maxLength = nativeMin(array.length, maxLength);
	        caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
	          ? new SetCache(othIndex && array)
	          : undefined;
	      }
	      array = arrays[0];

	      var index = -1,
	          seen = caches[0];

	      outer:
	      while (++index < length && result.length < maxLength) {
	        var value = array[index],
	            computed = iteratee ? iteratee(value) : value;

	        if (!(seen
	              ? cacheHas(seen, computed)
	              : includes(result, computed, comparator)
	            )) {
	          othIndex = othLength;
	          while (--othIndex) {
	            var cache = caches[othIndex];
	            if (!(cache
	                  ? cacheHas(cache, computed)
	                  : includes(arrays[othIndex], computed, comparator))
	                ) {
	              continue outer;
	            }
	          }
	          if (seen) {
	            seen.push(computed);
	          }
	          result.push(value);
	        }
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.invert` and `_.invertBy` which inverts
	     * `object` with values transformed by `iteratee` and set by `setter`.
	     *
	     * @private
	     * @param {Object} object The object to iterate over.
	     * @param {Function} setter The function to set `accumulator` values.
	     * @param {Function} iteratee The iteratee to transform values.
	     * @param {Object} accumulator The initial inverted object.
	     * @returns {Function} Returns `accumulator`.
	     */
	    function baseInverter(object, setter, iteratee, accumulator) {
	      baseForOwn(object, function(value, key, object) {
	        setter(accumulator, iteratee(value), key, object);
	      });
	      return accumulator;
	    }

	    /**
	     * The base implementation of `_.invoke` without support for individual
	     * method arguments.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path of the method to invoke.
	     * @param {Array} args The arguments to invoke the method with.
	     * @returns {*} Returns the result of the invoked method.
	     */
	    function baseInvoke(object, path, args) {
	      if (!isKey(path, object)) {
	        path = castPath(path);
	        object = parent(object, path);
	        path = last(path);
	      }
	      var func = object == null ? object : object[path];
	      return func == null ? undefined : apply(func, object, args);
	    }

	    /**
	     * The base implementation of `_.isEqual` which supports partial comparisons
	     * and tracks traversed objects.
	     *
	     * @private
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @param {Function} [customizer] The function to customize comparisons.
	     * @param {boolean} [bitmask] The bitmask of comparison flags.
	     *  The bitmask may be composed of the following flags:
	     *     1 - Unordered comparison
	     *     2 - Partial comparison
	     * @param {Object} [stack] Tracks traversed `value` and `other` objects.
	     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
	     */
	    function baseIsEqual(value, other, customizer, bitmask, stack) {
	      if (value === other) {
	        return true;
	      }
	      if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
	        return value !== value && other !== other;
	      }
	      return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
	    }

	    /**
	     * A specialized version of `baseIsEqual` for arrays and objects which performs
	     * deep comparisons and tracks traversed objects enabling objects with circular
	     * references to be compared.
	     *
	     * @private
	     * @param {Object} object The object to compare.
	     * @param {Object} other The other object to compare.
	     * @param {Function} equalFunc The function to determine equivalents of values.
	     * @param {Function} [customizer] The function to customize comparisons.
	     * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
	     *  for more details.
	     * @param {Object} [stack] Tracks traversed `object` and `other` objects.
	     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
	     */
	    function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
	      var objIsArr = isArray(object),
	          othIsArr = isArray(other),
	          objTag = arrayTag,
	          othTag = arrayTag;

	      if (!objIsArr) {
	        objTag = getTag(object);
	        objTag = objTag == argsTag ? objectTag : objTag;
	      }
	      if (!othIsArr) {
	        othTag = getTag(other);
	        othTag = othTag == argsTag ? objectTag : othTag;
	      }
	      var objIsObj = objTag == objectTag && !isHostObject(object),
	          othIsObj = othTag == objectTag && !isHostObject(other),
	          isSameTag = objTag == othTag;

	      if (isSameTag && !objIsObj) {
	        stack || (stack = new Stack);
	        return (objIsArr || isTypedArray(object))
	          ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
	          : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
	      }
	      if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
	        var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
	            othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

	        if (objIsWrapped || othIsWrapped) {
	          var objUnwrapped = objIsWrapped ? object.value() : object,
	              othUnwrapped = othIsWrapped ? other.value() : other;

	          stack || (stack = new Stack);
	          return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
	        }
	      }
	      if (!isSameTag) {
	        return false;
	      }
	      stack || (stack = new Stack);
	      return equalObjects(object, other, equalFunc, customizer, bitmask, stack);
	    }

	    /**
	     * The base implementation of `_.isMatch` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Object} object The object to inspect.
	     * @param {Object} source The object of property values to match.
	     * @param {Array} matchData The property names, values, and compare flags to match.
	     * @param {Function} [customizer] The function to customize comparisons.
	     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
	     */
	    function baseIsMatch(object, source, matchData, customizer) {
	      var index = matchData.length,
	          length = index,
	          noCustomizer = !customizer;

	      if (object == null) {
	        return !length;
	      }
	      object = Object(object);
	      while (index--) {
	        var data = matchData[index];
	        if ((noCustomizer && data[2])
	              ? data[1] !== object[data[0]]
	              : !(data[0] in object)
	            ) {
	          return false;
	        }
	      }
	      while (++index < length) {
	        data = matchData[index];
	        var key = data[0],
	            objValue = object[key],
	            srcValue = data[1];

	        if (noCustomizer && data[2]) {
	          if (objValue === undefined && !(key in object)) {
	            return false;
	          }
	        } else {
	          var stack = new Stack;
	          if (customizer) {
	            var result = customizer(objValue, srcValue, key, object, source, stack);
	          }
	          if (!(result === undefined
	                ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
	                : result
	              )) {
	            return false;
	          }
	        }
	      }
	      return true;
	    }

	    /**
	     * The base implementation of `_.iteratee`.
	     *
	     * @private
	     * @param {*} [value=_.identity] The value to convert to an iteratee.
	     * @returns {Function} Returns the iteratee.
	     */
	    function baseIteratee(value) {
	      // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
	      // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
	      if (typeof value == 'function') {
	        return value;
	      }
	      if (value == null) {
	        return identity;
	      }
	      if (typeof value == 'object') {
	        return isArray(value)
	          ? baseMatchesProperty(value[0], value[1])
	          : baseMatches(value);
	      }
	      return property(value);
	    }

	    /**
	     * The base implementation of `_.keys` which doesn't skip the constructor
	     * property of prototypes or treat sparse arrays as dense.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property names.
	     */
	    function baseKeys(object) {
	      return nativeKeys(Object(object));
	    }

	    /**
	     * The base implementation of `_.keysIn` which doesn't skip the constructor
	     * property of prototypes or treat sparse arrays as dense.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property names.
	     */
	    function baseKeysIn(object) {
	      object = object == null ? object : Object(object);

	      var result = [];
	      for (var key in object) {
	        result.push(key);
	      }
	      return result;
	    }

	    // Fallback for IE < 9 with es6-shim.
	    if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) {
	      baseKeysIn = function(object) {
	        return iteratorToArray(enumerate(object));
	      };
	    }

	    /**
	     * The base implementation of `_.map` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} iteratee The function invoked per iteration.
	     * @returns {Array} Returns the new mapped array.
	     */
	    function baseMap(collection, iteratee) {
	      var index = -1,
	          result = isArrayLike(collection) ? Array(collection.length) : [];

	      baseEach(collection, function(value, key, collection) {
	        result[++index] = iteratee(value, key, collection);
	      });
	      return result;
	    }

	    /**
	     * The base implementation of `_.matches` which doesn't clone `source`.
	     *
	     * @private
	     * @param {Object} source The object of property values to match.
	     * @returns {Function} Returns the new function.
	     */
	    function baseMatches(source) {
	      var matchData = getMatchData(source);
	      if (matchData.length == 1 && matchData[0][2]) {
	        return matchesStrictComparable(matchData[0][0], matchData[0][1]);
	      }
	      return function(object) {
	        return object === source || baseIsMatch(object, source, matchData);
	      };
	    }

	    /**
	     * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
	     *
	     * @private
	     * @param {string} path The path of the property to get.
	     * @param {*} srcValue The value to match.
	     * @returns {Function} Returns the new function.
	     */
	    function baseMatchesProperty(path, srcValue) {
	      if (isKey(path) && isStrictComparable(srcValue)) {
	        return matchesStrictComparable(path, srcValue);
	      }
	      return function(object) {
	        var objValue = get(object, path);
	        return (objValue === undefined && objValue === srcValue)
	          ? hasIn(object, path)
	          : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
	      };
	    }

	    /**
	     * The base implementation of `_.merge` without support for multiple sources.
	     *
	     * @private
	     * @param {Object} object The destination object.
	     * @param {Object} source The source object.
	     * @param {number} srcIndex The index of `source`.
	     * @param {Function} [customizer] The function to customize merged values.
	     * @param {Object} [stack] Tracks traversed source values and their merged
	     *  counterparts.
	     */
	    function baseMerge(object, source, srcIndex, customizer, stack) {
	      if (object === source) {
	        return;
	      }
	      if (!(isArray(source) || isTypedArray(source))) {
	        var props = keysIn(source);
	      }
	      arrayEach(props || source, function(srcValue, key) {
	        if (props) {
	          key = srcValue;
	          srcValue = source[key];
	        }
	        if (isObject(srcValue)) {
	          stack || (stack = new Stack);
	          baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
	        }
	        else {
	          var newValue = customizer
	            ? customizer(object[key], srcValue, (key + ''), object, source, stack)
	            : undefined;

	          if (newValue === undefined) {
	            newValue = srcValue;
	          }
	          assignMergeValue(object, key, newValue);
	        }
	      });
	    }

	    /**
	     * A specialized version of `baseMerge` for arrays and objects which performs
	     * deep merges and tracks traversed objects enabling objects with circular
	     * references to be merged.
	     *
	     * @private
	     * @param {Object} object The destination object.
	     * @param {Object} source The source object.
	     * @param {string} key The key of the value to merge.
	     * @param {number} srcIndex The index of `source`.
	     * @param {Function} mergeFunc The function to merge values.
	     * @param {Function} [customizer] The function to customize assigned values.
	     * @param {Object} [stack] Tracks traversed source values and their merged
	     *  counterparts.
	     */
	    function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
	      var objValue = object[key],
	          srcValue = source[key],
	          stacked = stack.get(srcValue);

	      if (stacked) {
	        assignMergeValue(object, key, stacked);
	        return;
	      }
	      var newValue = customizer
	        ? customizer(objValue, srcValue, (key + ''), object, source, stack)
	        : undefined;

	      var isCommon = newValue === undefined;

	      if (isCommon) {
	        newValue = srcValue;
	        if (isArray(srcValue) || isTypedArray(srcValue)) {
	          if (isArray(objValue)) {
	            newValue = objValue;
	          }
	          else if (isArrayLikeObject(objValue)) {
	            newValue = copyArray(objValue);
	          }
	          else {
	            isCommon = false;
	            newValue = baseClone(srcValue, true);
	          }
	        }
	        else if (isPlainObject(srcValue) || isArguments(srcValue)) {
	          if (isArguments(objValue)) {
	            newValue = toPlainObject(objValue);
	          }
	          else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
	            isCommon = false;
	            newValue = baseClone(srcValue, true);
	          }
	          else {
	            newValue = objValue;
	          }
	        }
	        else {
	          isCommon = false;
	        }
	      }
	      stack.set(srcValue, newValue);

	      if (isCommon) {
	        // Recursively merge objects and arrays (susceptible to call stack limits).
	        mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
	      }
	      stack['delete'](srcValue);
	      assignMergeValue(object, key, newValue);
	    }

	    /**
	     * The base implementation of `_.nth` which doesn't coerce `n` to an integer.
	     *
	     * @private
	     * @param {Array} array The array to query.
	     * @param {number} n The index of the element to return.
	     * @returns {*} Returns the nth element of `array`.
	     */
	    function baseNth(array, n) {
	      var length = array.length;
	      if (!length) {
	        return;
	      }
	      n += n < 0 ? length : 0;
	      return isIndex(n, length) ? array[n] : undefined;
	    }

	    /**
	     * The base implementation of `_.orderBy` without param guards.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
	     * @param {string[]} orders The sort orders of `iteratees`.
	     * @returns {Array} Returns the new sorted array.
	     */
	    function baseOrderBy(collection, iteratees, orders) {
	      var index = -1;
	      iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));

	      var result = baseMap(collection, function(value, key, collection) {
	        var criteria = arrayMap(iteratees, function(iteratee) {
	          return iteratee(value);
	        });
	        return { 'criteria': criteria, 'index': ++index, 'value': value };
	      });

	      return baseSortBy(result, function(object, other) {
	        return compareMultiple(object, other, orders);
	      });
	    }

	    /**
	     * The base implementation of `_.pick` without support for individual
	     * property identifiers.
	     *
	     * @private
	     * @param {Object} object The source object.
	     * @param {string[]} props The property identifiers to pick.
	     * @returns {Object} Returns the new object.
	     */
	    function basePick(object, props) {
	      object = Object(object);
	      return arrayReduce(props, function(result, key) {
	        if (key in object) {
	          result[key] = object[key];
	        }
	        return result;
	      }, {});
	    }

	    /**
	     * The base implementation of  `_.pickBy` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Object} object The source object.
	     * @param {Function} predicate The function invoked per property.
	     * @returns {Object} Returns the new object.
	     */
	    function basePickBy(object, predicate) {
	      var index = -1,
	          props = getAllKeysIn(object),
	          length = props.length,
	          result = {};

	      while (++index < length) {
	        var key = props[index],
	            value = object[key];

	        if (predicate(value, key)) {
	          result[key] = value;
	        }
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.property` without support for deep paths.
	     *
	     * @private
	     * @param {string} key The key of the property to get.
	     * @returns {Function} Returns the new function.
	     */
	    function baseProperty(key) {
	      return function(object) {
	        return object == null ? undefined : object[key];
	      };
	    }

	    /**
	     * A specialized version of `baseProperty` which supports deep paths.
	     *
	     * @private
	     * @param {Array|string} path The path of the property to get.
	     * @returns {Function} Returns the new function.
	     */
	    function basePropertyDeep(path) {
	      return function(object) {
	        return baseGet(object, path);
	      };
	    }

	    /**
	     * The base implementation of `_.pullAllBy` without support for iteratee
	     * shorthands.
	     *
	     * @private
	     * @param {Array} array The array to modify.
	     * @param {Array} values The values to remove.
	     * @param {Function} [iteratee] The iteratee invoked per element.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns `array`.
	     */
	    function basePullAll(array, values, iteratee, comparator) {
	      var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
	          index = -1,
	          length = values.length,
	          seen = array;

	      if (iteratee) {
	        seen = arrayMap(array, baseUnary(iteratee));
	      }
	      while (++index < length) {
	        var fromIndex = 0,
	            value = values[index],
	            computed = iteratee ? iteratee(value) : value;

	        while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
	          if (seen !== array) {
	            splice.call(seen, fromIndex, 1);
	          }
	          splice.call(array, fromIndex, 1);
	        }
	      }
	      return array;
	    }

	    /**
	     * The base implementation of `_.pullAt` without support for individual
	     * indexes or capturing the removed elements.
	     *
	     * @private
	     * @param {Array} array The array to modify.
	     * @param {number[]} indexes The indexes of elements to remove.
	     * @returns {Array} Returns `array`.
	     */
	    function basePullAt(array, indexes) {
	      var length = array ? indexes.length : 0,
	          lastIndex = length - 1;

	      while (length--) {
	        var index = indexes[length];
	        if (lastIndex == length || index != previous) {
	          var previous = index;
	          if (isIndex(index)) {
	            splice.call(array, index, 1);
	          }
	          else if (!isKey(index, array)) {
	            var path = castPath(index),
	                object = parent(array, path);

	            if (object != null) {
	              delete object[last(path)];
	            }
	          }
	          else {
	            delete array[index];
	          }
	        }
	      }
	      return array;
	    }

	    /**
	     * The base implementation of `_.random` without support for returning
	     * floating-point numbers.
	     *
	     * @private
	     * @param {number} lower The lower bound.
	     * @param {number} upper The upper bound.
	     * @returns {number} Returns the random number.
	     */
	    function baseRandom(lower, upper) {
	      return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
	    }

	    /**
	     * The base implementation of `_.range` and `_.rangeRight` which doesn't
	     * coerce arguments to numbers.
	     *
	     * @private
	     * @param {number} start The start of the range.
	     * @param {number} end The end of the range.
	     * @param {number} step The value to increment or decrement by.
	     * @param {boolean} [fromRight] Specify iterating from right to left.
	     * @returns {Array} Returns the new array of numbers.
	     */
	    function baseRange(start, end, step, fromRight) {
	      var index = -1,
	          length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
	          result = Array(length);

	      while (length--) {
	        result[fromRight ? length : ++index] = start;
	        start += step;
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.repeat` which doesn't coerce arguments.
	     *
	     * @private
	     * @param {string} string The string to repeat.
	     * @param {number} n The number of times to repeat the string.
	     * @returns {string} Returns the repeated string.
	     */
	    function baseRepeat(string, n) {
	      var result = '';
	      if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
	        return result;
	      }
	      // Leverage the exponentiation by squaring algorithm for a faster repeat.
	      // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
	      do {
	        if (n % 2) {
	          result += string;
	        }
	        n = nativeFloor(n / 2);
	        if (n) {
	          string += string;
	        }
	      } while (n);

	      return result;
	    }

	    /**
	     * The base implementation of `_.set`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path of the property to set.
	     * @param {*} value The value to set.
	     * @param {Function} [customizer] The function to customize path creation.
	     * @returns {Object} Returns `object`.
	     */
	    function baseSet(object, path, value, customizer) {
	      path = isKey(path, object) ? [path] : castPath(path);

	      var index = -1,
	          length = path.length,
	          lastIndex = length - 1,
	          nested = object;

	      while (nested != null && ++index < length) {
	        var key = path[index];
	        if (isObject(nested)) {
	          var newValue = value;
	          if (index != lastIndex) {
	            var objValue = nested[key];
	            newValue = customizer ? customizer(objValue, key, nested) : undefined;
	            if (newValue === undefined) {
	              newValue = objValue == null
	                ? (isIndex(path[index + 1]) ? [] : {})
	                : objValue;
	            }
	          }
	          assignValue(nested, key, newValue);
	        }
	        nested = nested[key];
	      }
	      return object;
	    }

	    /**
	     * The base implementation of `setData` without support for hot loop detection.
	     *
	     * @private
	     * @param {Function} func The function to associate metadata with.
	     * @param {*} data The metadata.
	     * @returns {Function} Returns `func`.
	     */
	    var baseSetData = !metaMap ? identity : function(func, data) {
	      metaMap.set(func, data);
	      return func;
	    };

	    /**
	     * The base implementation of `_.slice` without an iteratee call guard.
	     *
	     * @private
	     * @param {Array} array The array to slice.
	     * @param {number} [start=0] The start position.
	     * @param {number} [end=array.length] The end position.
	     * @returns {Array} Returns the slice of `array`.
	     */
	    function baseSlice(array, start, end) {
	      var index = -1,
	          length = array.length;

	      if (start < 0) {
	        start = -start > length ? 0 : (length + start);
	      }
	      end = end > length ? length : end;
	      if (end < 0) {
	        end += length;
	      }
	      length = start > end ? 0 : ((end - start) >>> 0);
	      start >>>= 0;

	      var result = Array(length);
	      while (++index < length) {
	        result[index] = array[index + start];
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.some` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} predicate The function invoked per iteration.
	     * @returns {boolean} Returns `true` if any element passes the predicate check,
	     *  else `false`.
	     */
	    function baseSome(collection, predicate) {
	      var result;

	      baseEach(collection, function(value, index, collection) {
	        result = predicate(value, index, collection);
	        return !result;
	      });
	      return !!result;
	    }

	    /**
	     * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
	     * performs a binary search of `array` to determine the index at which `value`
	     * should be inserted into `array` in order to maintain its sort order.
	     *
	     * @private
	     * @param {Array} array The sorted array to inspect.
	     * @param {*} value The value to evaluate.
	     * @param {boolean} [retHighest] Specify returning the highest qualified index.
	     * @returns {number} Returns the index at which `value` should be inserted
	     *  into `array`.
	     */
	    function baseSortedIndex(array, value, retHighest) {
	      var low = 0,
	          high = array ? array.length : low;

	      if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
	        while (low < high) {
	          var mid = (low + high) >>> 1,
	              computed = array[mid];

	          if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {
	            low = mid + 1;
	          } else {
	            high = mid;
	          }
	        }
	        return high;
	      }
	      return baseSortedIndexBy(array, value, identity, retHighest);
	    }

	    /**
	     * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
	     * which invokes `iteratee` for `value` and each element of `array` to compute
	     * their sort ranking. The iteratee is invoked with one argument; (value).
	     *
	     * @private
	     * @param {Array} array The sorted array to inspect.
	     * @param {*} value The value to evaluate.
	     * @param {Function} iteratee The iteratee invoked per element.
	     * @param {boolean} [retHighest] Specify returning the highest qualified index.
	     * @returns {number} Returns the index at which `value` should be inserted
	     *  into `array`.
	     */
	    function baseSortedIndexBy(array, value, iteratee, retHighest) {
	      value = iteratee(value);

	      var low = 0,
	          high = array ? array.length : 0,
	          valIsNaN = value !== value,
	          valIsNull = value === null,
	          valIsUndef = value === undefined;

	      while (low < high) {
	        var mid = nativeFloor((low + high) / 2),
	            computed = iteratee(array[mid]),
	            isDef = computed !== undefined,
	            isReflexive = computed === computed;

	        if (valIsNaN) {
	          var setLow = isReflexive || retHighest;
	        } else if (valIsNull) {
	          setLow = isReflexive && isDef && (retHighest || computed != null);
	        } else if (valIsUndef) {
	          setLow = isReflexive && (retHighest || isDef);
	        } else if (computed == null) {
	          setLow = false;
	        } else {
	          setLow = retHighest ? (computed <= value) : (computed < value);
	        }
	        if (setLow) {
	          low = mid + 1;
	        } else {
	          high = mid;
	        }
	      }
	      return nativeMin(high, MAX_ARRAY_INDEX);
	    }

	    /**
	     * The base implementation of `_.sortedUniq`.
	     *
	     * @private
	     * @param {Array} array The array to inspect.
	     * @returns {Array} Returns the new duplicate free array.
	     */
	    function baseSortedUniq(array) {
	      return baseSortedUniqBy(array);
	    }

	    /**
	     * The base implementation of `_.sortedUniqBy` without support for iteratee
	     * shorthands.
	     *
	     * @private
	     * @param {Array} array The array to inspect.
	     * @param {Function} [iteratee] The iteratee invoked per element.
	     * @returns {Array} Returns the new duplicate free array.
	     */
	    function baseSortedUniqBy(array, iteratee) {
	      var index = 0,
	          length = array.length,
	          value = array[0],
	          computed = iteratee ? iteratee(value) : value,
	          seen = computed,
	          resIndex = 1,
	          result = [value];

	      while (++index < length) {
	        value = array[index],
	        computed = iteratee ? iteratee(value) : value;

	        if (!eq(computed, seen)) {
	          seen = computed;
	          result[resIndex++] = value;
	        }
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.uniqBy` without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array} array The array to inspect.
	     * @param {Function} [iteratee] The iteratee invoked per element.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new duplicate free array.
	     */
	    function baseUniq(array, iteratee, comparator) {
	      var index = -1,
	          includes = arrayIncludes,
	          length = array.length,
	          isCommon = true,
	          result = [],
	          seen = result;

	      if (comparator) {
	        isCommon = false;
	        includes = arrayIncludesWith;
	      }
	      else if (length >= LARGE_ARRAY_SIZE) {
	        var set = iteratee ? null : createSet(array);
	        if (set) {
	          return setToArray(set);
	        }
	        isCommon = false;
	        includes = cacheHas;
	        seen = new SetCache;
	      }
	      else {
	        seen = iteratee ? [] : result;
	      }
	      outer:
	      while (++index < length) {
	        var value = array[index],
	            computed = iteratee ? iteratee(value) : value;

	        if (isCommon && computed === computed) {
	          var seenIndex = seen.length;
	          while (seenIndex--) {
	            if (seen[seenIndex] === computed) {
	              continue outer;
	            }
	          }
	          if (iteratee) {
	            seen.push(computed);
	          }
	          result.push(value);
	        }
	        else if (!includes(seen, computed, comparator)) {
	          if (seen !== result) {
	            seen.push(computed);
	          }
	          result.push(value);
	        }
	      }
	      return result;
	    }

	    /**
	     * The base implementation of `_.unset`.
	     *
	     * @private
	     * @param {Object} object The object to modify.
	     * @param {Array|string} path The path of the property to unset.
	     * @returns {boolean} Returns `true` if the property is deleted, else `false`.
	     */
	    function baseUnset(object, path) {
	      path = isKey(path, object) ? [path] : castPath(path);
	      object = parent(object, path);
	      var key = last(path);
	      return (object != null && has(object, key)) ? delete object[key] : true;
	    }

	    /**
	     * The base implementation of `_.update`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path of the property to update.
	     * @param {Function} updater The function to produce the updated value.
	     * @param {Function} [customizer] The function to customize path creation.
	     * @returns {Object} Returns `object`.
	     */
	    function baseUpdate(object, path, updater, customizer) {
	      return baseSet(object, path, updater(baseGet(object, path)), customizer);
	    }

	    /**
	     * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
	     * without support for iteratee shorthands.
	     *
	     * @private
	     * @param {Array} array The array to query.
	     * @param {Function} predicate The function invoked per iteration.
	     * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
	     * @param {boolean} [fromRight] Specify iterating from right to left.
	     * @returns {Array} Returns the slice of `array`.
	     */
	    function baseWhile(array, predicate, isDrop, fromRight) {
	      var length = array.length,
	          index = fromRight ? length : -1;

	      while ((fromRight ? index-- : ++index < length) &&
	        predicate(array[index], index, array)) {}

	      return isDrop
	        ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
	        : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
	    }

	    /**
	     * The base implementation of `wrapperValue` which returns the result of
	     * performing a sequence of actions on the unwrapped `value`, where each
	     * successive action is supplied the return value of the previous.
	     *
	     * @private
	     * @param {*} value The unwrapped value.
	     * @param {Array} actions Actions to perform to resolve the unwrapped value.
	     * @returns {*} Returns the resolved value.
	     */
	    function baseWrapperValue(value, actions) {
	      var result = value;
	      if (result instanceof LazyWrapper) {
	        result = result.value();
	      }
	      return arrayReduce(actions, function(result, action) {
	        return action.func.apply(action.thisArg, arrayPush([result], action.args));
	      }, result);
	    }

	    /**
	     * The base implementation of methods like `_.xor`, without support for
	     * iteratee shorthands, that accepts an array of arrays to inspect.
	     *
	     * @private
	     * @param {Array} arrays The arrays to inspect.
	     * @param {Function} [iteratee] The iteratee invoked per element.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new array of values.
	     */
	    function baseXor(arrays, iteratee, comparator) {
	      var index = -1,
	          length = arrays.length;

	      while (++index < length) {
	        var result = result
	          ? arrayPush(
	              baseDifference(result, arrays[index], iteratee, comparator),
	              baseDifference(arrays[index], result, iteratee, comparator)
	            )
	          : arrays[index];
	      }
	      return (result && result.length) ? baseUniq(result, iteratee, comparator) : [];
	    }

	    /**
	     * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
	     *
	     * @private
	     * @param {Array} props The property identifiers.
	     * @param {Array} values The property values.
	     * @param {Function} assignFunc The function to assign values.
	     * @returns {Object} Returns the new object.
	     */
	    function baseZipObject(props, values, assignFunc) {
	      var index = -1,
	          length = props.length,
	          valsLength = values.length,
	          result = {};

	      while (++index < length) {
	        var value = index < valsLength ? values[index] : undefined;
	        assignFunc(result, props[index], value);
	      }
	      return result;
	    }

	    /**
	     * Casts `value` to an empty array if it's not an array like object.
	     *
	     * @private
	     * @param {*} value The value to inspect.
	     * @returns {Array|Object} Returns the cast array-like object.
	     */
	    function castArrayLikeObject(value) {
	      return isArrayLikeObject(value) ? value : [];
	    }

	    /**
	     * Casts `value` to `identity` if it's not a function.
	     *
	     * @private
	     * @param {*} value The value to inspect.
	     * @returns {Function} Returns cast function.
	     */
	    function castFunction(value) {
	      return typeof value == 'function' ? value : identity;
	    }

	    /**
	     * Casts `value` to a path array if it's not one.
	     *
	     * @private
	     * @param {*} value The value to inspect.
	     * @returns {Array} Returns the cast property path array.
	     */
	    function castPath(value) {
	      return isArray(value) ? value : stringToPath(value);
	    }

	    /**
	     * Casts `array` to a slice if it's needed.
	     *
	     * @private
	     * @param {Array} array The array to inspect.
	     * @param {number} start The start position.
	     * @param {number} [end=array.length] The end position.
	     * @returns {Array} Returns the cast slice.
	     */
	    function castSlice(array, start, end) {
	      var length = array.length;
	      end = end === undefined ? length : end;
	      return (!start && end >= length) ? array : baseSlice(array, start, end);
	    }

	    /**
	     * Creates a clone of  `buffer`.
	     *
	     * @private
	     * @param {Buffer} buffer The buffer to clone.
	     * @param {boolean} [isDeep] Specify a deep clone.
	     * @returns {Buffer} Returns the cloned buffer.
	     */
	    function cloneBuffer(buffer, isDeep) {
	      if (isDeep) {
	        return buffer.slice();
	      }
	      var result = new buffer.constructor(buffer.length);
	      buffer.copy(result);
	      return result;
	    }

	    /**
	     * Creates a clone of `arrayBuffer`.
	     *
	     * @private
	     * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
	     * @returns {ArrayBuffer} Returns the cloned array buffer.
	     */
	    function cloneArrayBuffer(arrayBuffer) {
	      var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
	      new Uint8Array(result).set(new Uint8Array(arrayBuffer));
	      return result;
	    }

	    /**
	     * Creates a clone of `dataView`.
	     *
	     * @private
	     * @param {Object} dataView The data view to clone.
	     * @param {boolean} [isDeep] Specify a deep clone.
	     * @returns {Object} Returns the cloned data view.
	     */
	    function cloneDataView(dataView, isDeep) {
	      var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
	      return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
	    }

	    /**
	     * Creates a clone of `map`.
	     *
	     * @private
	     * @param {Object} map The map to clone.
	     * @param {Function} cloneFunc The function to clone values.
	     * @param {boolean} [isDeep] Specify a deep clone.
	     * @returns {Object} Returns the cloned map.
	     */
	    function cloneMap(map, isDeep, cloneFunc) {
	      var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map);
	      return arrayReduce(array, addMapEntry, new map.constructor);
	    }

	    /**
	     * Creates a clone of `regexp`.
	     *
	     * @private
	     * @param {Object} regexp The regexp to clone.
	     * @returns {Object} Returns the cloned regexp.
	     */
	    function cloneRegExp(regexp) {
	      var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
	      result.lastIndex = regexp.lastIndex;
	      return result;
	    }

	    /**
	     * Creates a clone of `set`.
	     *
	     * @private
	     * @param {Object} set The set to clone.
	     * @param {Function} cloneFunc The function to clone values.
	     * @param {boolean} [isDeep] Specify a deep clone.
	     * @returns {Object} Returns the cloned set.
	     */
	    function cloneSet(set, isDeep, cloneFunc) {
	      var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set);
	      return arrayReduce(array, addSetEntry, new set.constructor);
	    }

	    /**
	     * Creates a clone of the `symbol` object.
	     *
	     * @private
	     * @param {Object} symbol The symbol object to clone.
	     * @returns {Object} Returns the cloned symbol object.
	     */
	    function cloneSymbol(symbol) {
	      return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
	    }

	    /**
	     * Creates a clone of `typedArray`.
	     *
	     * @private
	     * @param {Object} typedArray The typed array to clone.
	     * @param {boolean} [isDeep] Specify a deep clone.
	     * @returns {Object} Returns the cloned typed array.
	     */
	    function cloneTypedArray(typedArray, isDeep) {
	      var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
	      return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
	    }

	    /**
	     * Creates an array that is the composition of partially applied arguments,
	     * placeholders, and provided arguments into a single array of arguments.
	     *
	     * @private
	     * @param {Array|Object} args The provided arguments.
	     * @param {Array} partials The arguments to prepend to those provided.
	     * @param {Array} holders The `partials` placeholder indexes.
	     * @params {boolean} [isCurried] Specify composing for a curried function.
	     * @returns {Array} Returns the new array of composed arguments.
	     */
	    function composeArgs(args, partials, holders, isCurried) {
	      var argsIndex = -1,
	          argsLength = args.length,
	          holdersLength = holders.length,
	          leftIndex = -1,
	          leftLength = partials.length,
	          rangeLength = nativeMax(argsLength - holdersLength, 0),
	          result = Array(leftLength + rangeLength),
	          isUncurried = !isCurried;

	      while (++leftIndex < leftLength) {
	        result[leftIndex] = partials[leftIndex];
	      }
	      while (++argsIndex < holdersLength) {
	        if (isUncurried || argsIndex < argsLength) {
	          result[holders[argsIndex]] = args[argsIndex];
	        }
	      }
	      while (rangeLength--) {
	        result[leftIndex++] = args[argsIndex++];
	      }
	      return result;
	    }

	    /**
	     * This function is like `composeArgs` except that the arguments composition
	     * is tailored for `_.partialRight`.
	     *
	     * @private
	     * @param {Array|Object} args The provided arguments.
	     * @param {Array} partials The arguments to append to those provided.
	     * @param {Array} holders The `partials` placeholder indexes.
	     * @params {boolean} [isCurried] Specify composing for a curried function.
	     * @returns {Array} Returns the new array of composed arguments.
	     */
	    function composeArgsRight(args, partials, holders, isCurried) {
	      var argsIndex = -1,
	          argsLength = args.length,
	          holdersIndex = -1,
	          holdersLength = holders.length,
	          rightIndex = -1,
	          rightLength = partials.length,
	          rangeLength = nativeMax(argsLength - holdersLength, 0),
	          result = Array(rangeLength + rightLength),
	          isUncurried = !isCurried;

	      while (++argsIndex < rangeLength) {
	        result[argsIndex] = args[argsIndex];
	      }
	      var offset = argsIndex;
	      while (++rightIndex < rightLength) {
	        result[offset + rightIndex] = partials[rightIndex];
	      }
	      while (++holdersIndex < holdersLength) {
	        if (isUncurried || argsIndex < argsLength) {
	          result[offset + holders[holdersIndex]] = args[argsIndex++];
	        }
	      }
	      return result;
	    }

	    /**
	     * Copies the values of `source` to `array`.
	     *
	     * @private
	     * @param {Array} source The array to copy values from.
	     * @param {Array} [array=[]] The array to copy values to.
	     * @returns {Array} Returns `array`.
	     */
	    function copyArray(source, array) {
	      var index = -1,
	          length = source.length;

	      array || (array = Array(length));
	      while (++index < length) {
	        array[index] = source[index];
	      }
	      return array;
	    }

	    /**
	     * Copies properties of `source` to `object`.
	     *
	     * @private
	     * @param {Object} source The object to copy properties from.
	     * @param {Array} props The property identifiers to copy.
	     * @param {Object} [object={}] The object to copy properties to.
	     * @param {Function} [customizer] The function to customize copied values.
	     * @returns {Object} Returns `object`.
	     */
	    function copyObject(source, props, object, customizer) {
	      object || (object = {});

	      var index = -1,
	          length = props.length;

	      while (++index < length) {
	        var key = props[index];

	        var newValue = customizer
	          ? customizer(object[key], source[key], key, object, source)
	          : source[key];

	        assignValue(object, key, newValue);
	      }
	      return object;
	    }

	    /**
	     * Copies own symbol properties of `source` to `object`.
	     *
	     * @private
	     * @param {Object} source The object to copy symbols from.
	     * @param {Object} [object={}] The object to copy symbols to.
	     * @returns {Object} Returns `object`.
	     */
	    function copySymbols(source, object) {
	      return copyObject(source, getSymbols(source), object);
	    }

	    /**
	     * Creates a function like `_.groupBy`.
	     *
	     * @private
	     * @param {Function} setter The function to set accumulator values.
	     * @param {Function} [initializer] The accumulator object initializer.
	     * @returns {Function} Returns the new aggregator function.
	     */
	    function createAggregator(setter, initializer) {
	      return function(collection, iteratee) {
	        var func = isArray(collection) ? arrayAggregator : baseAggregator,
	            accumulator = initializer ? initializer() : {};

	        return func(collection, setter, getIteratee(iteratee), accumulator);
	      };
	    }

	    /**
	     * Creates a function like `_.assign`.
	     *
	     * @private
	     * @param {Function} assigner The function to assign values.
	     * @returns {Function} Returns the new assigner function.
	     */
	    function createAssigner(assigner) {
	      return rest(function(object, sources) {
	        var index = -1,
	            length = sources.length,
	            customizer = length > 1 ? sources[length - 1] : undefined,
	            guard = length > 2 ? sources[2] : undefined;

	        customizer = typeof customizer == 'function'
	          ? (length--, customizer)
	          : undefined;

	        if (guard && isIterateeCall(sources[0], sources[1], guard)) {
	          customizer = length < 3 ? undefined : customizer;
	          length = 1;
	        }
	        object = Object(object);
	        while (++index < length) {
	          var source = sources[index];
	          if (source) {
	            assigner(object, source, index, customizer);
	          }
	        }
	        return object;
	      });
	    }

	    /**
	     * Creates a `baseEach` or `baseEachRight` function.
	     *
	     * @private
	     * @param {Function} eachFunc The function to iterate over a collection.
	     * @param {boolean} [fromRight] Specify iterating from right to left.
	     * @returns {Function} Returns the new base function.
	     */
	    function createBaseEach(eachFunc, fromRight) {
	      return function(collection, iteratee) {
	        if (collection == null) {
	          return collection;
	        }
	        if (!isArrayLike(collection)) {
	          return eachFunc(collection, iteratee);
	        }
	        var length = collection.length,
	            index = fromRight ? length : -1,
	            iterable = Object(collection);

	        while ((fromRight ? index-- : ++index < length)) {
	          if (iteratee(iterable[index], index, iterable) === false) {
	            break;
	          }
	        }
	        return collection;
	      };
	    }

	    /**
	     * Creates a base function for methods like `_.forIn` and `_.forOwn`.
	     *
	     * @private
	     * @param {boolean} [fromRight] Specify iterating from right to left.
	     * @returns {Function} Returns the new base function.
	     */
	    function createBaseFor(fromRight) {
	      return function(object, iteratee, keysFunc) {
	        var index = -1,
	            iterable = Object(object),
	            props = keysFunc(object),
	            length = props.length;

	        while (length--) {
	          var key = props[fromRight ? length : ++index];
	          if (iteratee(iterable[key], key, iterable) === false) {
	            break;
	          }
	        }
	        return object;
	      };
	    }

	    /**
	     * Creates a function that wraps `func` to invoke it with the optional `this`
	     * binding of `thisArg`.
	     *
	     * @private
	     * @param {Function} func The function to wrap.
	     * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
	     *  for more details.
	     * @param {*} [thisArg] The `this` binding of `func`.
	     * @returns {Function} Returns the new wrapped function.
	     */
	    function createBaseWrapper(func, bitmask, thisArg) {
	      var isBind = bitmask & BIND_FLAG,
	          Ctor = createCtorWrapper(func);

	      function wrapper() {
	        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
	        return fn.apply(isBind ? thisArg : this, arguments);
	      }
	      return wrapper;
	    }

	    /**
	     * Creates a function like `_.lowerFirst`.
	     *
	     * @private
	     * @param {string} methodName The name of the `String` case method to use.
	     * @returns {Function} Returns the new function.
	     */
	    function createCaseFirst(methodName) {
	      return function(string) {
	        string = toString(string);

	        var strSymbols = reHasComplexSymbol.test(string)
	          ? stringToArray(string)
	          : undefined;

	        var chr = strSymbols
	          ? strSymbols[0]
	          : string.charAt(0);

	        var trailing = strSymbols
	          ? castSlice(strSymbols, 1).join('')
	          : string.slice(1);

	        return chr[methodName]() + trailing;
	      };
	    }

	    /**
	     * Creates a function like `_.camelCase`.
	     *
	     * @private
	     * @param {Function} callback The function to combine each word.
	     * @returns {Function} Returns the new compounder function.
	     */
	    function createCompounder(callback) {
	      return function(string) {
	        return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
	      };
	    }

	    /**
	     * Creates a function that produces an instance of `Ctor` regardless of
	     * whether it was invoked as part of a `new` expression or by `call` or `apply`.
	     *
	     * @private
	     * @param {Function} Ctor The constructor to wrap.
	     * @returns {Function} Returns the new wrapped function.
	     */
	    function createCtorWrapper(Ctor) {
	      return function() {
	        // Use a `switch` statement to work with class constructors. See
	        // http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
	        // for more details.
	        var args = arguments;
	        switch (args.length) {
	          case 0: return new Ctor;
	          case 1: return new Ctor(args[0]);
	          case 2: return new Ctor(args[0], args[1]);
	          case 3: return new Ctor(args[0], args[1], args[2]);
	          case 4: return new Ctor(args[0], args[1], args[2], args[3]);
	          case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
	          case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
	          case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
	        }
	        var thisBinding = baseCreate(Ctor.prototype),
	            result = Ctor.apply(thisBinding, args);

	        // Mimic the constructor's `return` behavior.
	        // See https://es5.github.io/#x13.2.2 for more details.
	        return isObject(result) ? result : thisBinding;
	      };
	    }

	    /**
	     * Creates a function that wraps `func` to enable currying.
	     *
	     * @private
	     * @param {Function} func The function to wrap.
	     * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
	     *  for more details.
	     * @param {number} arity The arity of `func`.
	     * @returns {Function} Returns the new wrapped function.
	     */
	    function createCurryWrapper(func, bitmask, arity) {
	      var Ctor = createCtorWrapper(func);

	      function wrapper() {
	        var length = arguments.length,
	            args = Array(length),
	            index = length,
	            placeholder = getPlaceholder(wrapper);

	        while (index--) {
	          args[index] = arguments[index];
	        }
	        var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
	          ? []
	          : replaceHolders(args, placeholder);

	        length -= holders.length;
	        if (length < arity) {
	          return createRecurryWrapper(
	            func, bitmask, createHybridWrapper, wrapper.placeholder, undefined,
	            args, holders, undefined, undefined, arity - length);
	        }
	        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
	        return apply(fn, this, args);
	      }
	      return wrapper;
	    }

	    /**
	     * Creates a `_.flow` or `_.flowRight` function.
	     *
	     * @private
	     * @param {boolean} [fromRight] Specify iterating from right to left.
	     * @returns {Function} Returns the new flow function.
	     */
	    function createFlow(fromRight) {
	      return rest(function(funcs) {
	        funcs = baseFlatten(funcs, 1);

	        var length = funcs.length,
	            index = length,
	            prereq = LodashWrapper.prototype.thru;

	        if (fromRight) {
	          funcs.reverse();
	        }
	        while (index--) {
	          var func = funcs[index];
	          if (typeof func != 'function') {
	            throw new TypeError(FUNC_ERROR_TEXT);
	          }
	          if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
	            var wrapper = new LodashWrapper([], true);
	          }
	        }
	        index = wrapper ? index : length;
	        while (++index < length) {
	          func = funcs[index];

	          var funcName = getFuncName(func),
	              data = funcName == 'wrapper' ? getData(func) : undefined;

	          if (data && isLaziable(data[0]) &&
	                data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) &&
	                !data[4].length && data[9] == 1
	              ) {
	            wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
	          } else {
	            wrapper = (func.length == 1 && isLaziable(func))
	              ? wrapper[funcName]()
	              : wrapper.thru(func);
	          }
	        }
	        return function() {
	          var args = arguments,
	              value = args[0];

	          if (wrapper && args.length == 1 &&
	              isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
	            return wrapper.plant(value).value();
	          }
	          var index = 0,
	              result = length ? funcs[index].apply(this, args) : value;

	          while (++index < length) {
	            result = funcs[index].call(this, result);
	          }
	          return result;
	        };
	      });
	    }

	    /**
	     * Creates a function that wraps `func` to invoke it with optional `this`
	     * binding of `thisArg`, partial application, and currying.
	     *
	     * @private
	     * @param {Function|string} func The function or method name to wrap.
	     * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
	     *  for more details.
	     * @param {*} [thisArg] The `this` binding of `func`.
	     * @param {Array} [partials] The arguments to prepend to those provided to
	     *  the new function.
	     * @param {Array} [holders] The `partials` placeholder indexes.
	     * @param {Array} [partialsRight] The arguments to append to those provided
	     *  to the new function.
	     * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
	     * @param {Array} [argPos] The argument positions of the new function.
	     * @param {number} [ary] The arity cap of `func`.
	     * @param {number} [arity] The arity of `func`.
	     * @returns {Function} Returns the new wrapped function.
	     */
	    function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
	      var isAry = bitmask & ARY_FLAG,
	          isBind = bitmask & BIND_FLAG,
	          isBindKey = bitmask & BIND_KEY_FLAG,
	          isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG),
	          isFlip = bitmask & FLIP_FLAG,
	          Ctor = isBindKey ? undefined : createCtorWrapper(func);

	      function wrapper() {
	        var length = arguments.length,
	            index = length,
	            args = Array(length);

	        while (index--) {
	          args[index] = arguments[index];
	        }
	        if (isCurried) {
	          var placeholder = getPlaceholder(wrapper),
	              holdersCount = countHolders(args, placeholder);
	        }
	        if (partials) {
	          args = composeArgs(args, partials, holders, isCurried);
	        }
	        if (partialsRight) {
	          args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
	        }
	        length -= holdersCount;
	        if (isCurried && length < arity) {
	          var newHolders = replaceHolders(args, placeholder);
	          return createRecurryWrapper(
	            func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg,
	            args, newHolders, argPos, ary, arity - length
	          );
	        }
	        var thisBinding = isBind ? thisArg : this,
	            fn = isBindKey ? thisBinding[func] : func;

	        length = args.length;
	        if (argPos) {
	          args = reorder(args, argPos);
	        } else if (isFlip && length > 1) {
	          args.reverse();
	        }
	        if (isAry && ary < length) {
	          args.length = ary;
	        }
	        if (this && this !== root && this instanceof wrapper) {
	          fn = Ctor || createCtorWrapper(fn);
	        }
	        return fn.apply(thisBinding, args);
	      }
	      return wrapper;
	    }

	    /**
	     * Creates a function like `_.invertBy`.
	     *
	     * @private
	     * @param {Function} setter The function to set accumulator values.
	     * @param {Function} toIteratee The function to resolve iteratees.
	     * @returns {Function} Returns the new inverter function.
	     */
	    function createInverter(setter, toIteratee) {
	      return function(object, iteratee) {
	        return baseInverter(object, setter, toIteratee(iteratee), {});
	      };
	    }

	    /**
	     * Creates a function like `_.over`.
	     *
	     * @private
	     * @param {Function} arrayFunc The function to iterate over iteratees.
	     * @returns {Function} Returns the new invoker function.
	     */
	    function createOver(arrayFunc) {
	      return rest(function(iteratees) {
	        iteratees = (iteratees.length == 1 && isArray(iteratees[0]))
	          ? arrayMap(iteratees[0], baseUnary(getIteratee()))
	          : arrayMap(baseFlatten(iteratees, 1, isFlattenableIteratee), baseUnary(getIteratee()));

	        return rest(function(args) {
	          var thisArg = this;
	          return arrayFunc(iteratees, function(iteratee) {
	            return apply(iteratee, thisArg, args);
	          });
	        });
	      });
	    }

	    /**
	     * Creates the padding for `string` based on `length`. The `chars` string
	     * is truncated if the number of characters exceeds `length`.
	     *
	     * @private
	     * @param {number} length The padding length.
	     * @param {string} [chars=' '] The string used as padding.
	     * @returns {string} Returns the padding for `string`.
	     */
	    function createPadding(length, chars) {
	      chars = chars === undefined ? ' ' : (chars + '');

	      var charsLength = chars.length;
	      if (charsLength < 2) {
	        return charsLength ? baseRepeat(chars, length) : chars;
	      }
	      var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
	      return reHasComplexSymbol.test(chars)
	        ? castSlice(stringToArray(result), 0, length).join('')
	        : result.slice(0, length);
	    }

	    /**
	     * Creates a function that wraps `func` to invoke it with the `this` binding
	     * of `thisArg` and `partials` prepended to the arguments it receives.
	     *
	     * @private
	     * @param {Function} func The function to wrap.
	     * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
	     *  for more details.
	     * @param {*} thisArg The `this` binding of `func`.
	     * @param {Array} partials The arguments to prepend to those provided to
	     *  the new function.
	     * @returns {Function} Returns the new wrapped function.
	     */
	    function createPartialWrapper(func, bitmask, thisArg, partials) {
	      var isBind = bitmask & BIND_FLAG,
	          Ctor = createCtorWrapper(func);

	      function wrapper() {
	        var argsIndex = -1,
	            argsLength = arguments.length,
	            leftIndex = -1,
	            leftLength = partials.length,
	            args = Array(leftLength + argsLength),
	            fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;

	        while (++leftIndex < leftLength) {
	          args[leftIndex] = partials[leftIndex];
	        }
	        while (argsLength--) {
	          args[leftIndex++] = arguments[++argsIndex];
	        }
	        return apply(fn, isBind ? thisArg : this, args);
	      }
	      return wrapper;
	    }

	    /**
	     * Creates a `_.range` or `_.rangeRight` function.
	     *
	     * @private
	     * @param {boolean} [fromRight] Specify iterating from right to left.
	     * @returns {Function} Returns the new range function.
	     */
	    function createRange(fromRight) {
	      return function(start, end, step) {
	        if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
	          end = step = undefined;
	        }
	        // Ensure the sign of `-0` is preserved.
	        start = toNumber(start);
	        start = start === start ? start : 0;
	        if (end === undefined) {
	          end = start;
	          start = 0;
	        } else {
	          end = toNumber(end) || 0;
	        }
	        step = step === undefined ? (start < end ? 1 : -1) : (toNumber(step) || 0);
	        return baseRange(start, end, step, fromRight);
	      };
	    }

	    /**
	     * Creates a function that wraps `func` to continue currying.
	     *
	     * @private
	     * @param {Function} func The function to wrap.
	     * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
	     *  for more details.
	     * @param {Function} wrapFunc The function to create the `func` wrapper.
	     * @param {*} placeholder The placeholder value.
	     * @param {*} [thisArg] The `this` binding of `func`.
	     * @param {Array} [partials] The arguments to prepend to those provided to
	     *  the new function.
	     * @param {Array} [holders] The `partials` placeholder indexes.
	     * @param {Array} [argPos] The argument positions of the new function.
	     * @param {number} [ary] The arity cap of `func`.
	     * @param {number} [arity] The arity of `func`.
	     * @returns {Function} Returns the new wrapped function.
	     */
	    function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
	      var isCurry = bitmask & CURRY_FLAG,
	          newHolders = isCurry ? holders : undefined,
	          newHoldersRight = isCurry ? undefined : holders,
	          newPartials = isCurry ? partials : undefined,
	          newPartialsRight = isCurry ? undefined : partials;

	      bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
	      bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);

	      if (!(bitmask & CURRY_BOUND_FLAG)) {
	        bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
	      }
	      var newData = [
	        func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
	        newHoldersRight, argPos, ary, arity
	      ];

	      var result = wrapFunc.apply(undefined, newData);
	      if (isLaziable(func)) {
	        setData(result, newData);
	      }
	      result.placeholder = placeholder;
	      return result;
	    }

	    /**
	     * Creates a function like `_.round`.
	     *
	     * @private
	     * @param {string} methodName The name of the `Math` method to use when rounding.
	     * @returns {Function} Returns the new round function.
	     */
	    function createRound(methodName) {
	      var func = Math[methodName];
	      return function(number, precision) {
	        number = toNumber(number);
	        precision = toInteger(precision);
	        if (precision) {
	          // Shift with exponential notation to avoid floating-point issues.
	          // See [MDN](https://mdn.io/round#Examples) for more details.
	          var pair = (toString(number) + 'e').split('e'),
	              value = func(pair[0] + 'e' + (+pair[1] + precision));

	          pair = (toString(value) + 'e').split('e');
	          return +(pair[0] + 'e' + (+pair[1] - precision));
	        }
	        return func(number);
	      };
	    }

	    /**
	     * Creates a set of `values`.
	     *
	     * @private
	     * @param {Array} values The values to add to the set.
	     * @returns {Object} Returns the new set.
	     */
	    var createSet = !(Set && new Set([1, 2]).size === 2) ? noop : function(values) {
	      return new Set(values);
	    };

	    /**
	     * Creates a function that either curries or invokes `func` with optional
	     * `this` binding and partially applied arguments.
	     *
	     * @private
	     * @param {Function|string} func The function or method name to wrap.
	     * @param {number} bitmask The bitmask of wrapper flags.
	     *  The bitmask may be composed of the following flags:
	     *     1 - `_.bind`
	     *     2 - `_.bindKey`
	     *     4 - `_.curry` or `_.curryRight` of a bound function
	     *     8 - `_.curry`
	     *    16 - `_.curryRight`
	     *    32 - `_.partial`
	     *    64 - `_.partialRight`
	     *   128 - `_.rearg`
	     *   256 - `_.ary`
	     * @param {*} [thisArg] The `this` binding of `func`.
	     * @param {Array} [partials] The arguments to be partially applied.
	     * @param {Array} [holders] The `partials` placeholder indexes.
	     * @param {Array} [argPos] The argument positions of the new function.
	     * @param {number} [ary] The arity cap of `func`.
	     * @param {number} [arity] The arity of `func`.
	     * @returns {Function} Returns the new wrapped function.
	     */
	    function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
	      var isBindKey = bitmask & BIND_KEY_FLAG;
	      if (!isBindKey && typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      var length = partials ? partials.length : 0;
	      if (!length) {
	        bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
	        partials = holders = undefined;
	      }
	      ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
	      arity = arity === undefined ? arity : toInteger(arity);
	      length -= holders ? holders.length : 0;

	      if (bitmask & PARTIAL_RIGHT_FLAG) {
	        var partialsRight = partials,
	            holdersRight = holders;

	        partials = holders = undefined;
	      }
	      var data = isBindKey ? undefined : getData(func);

	      var newData = [
	        func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
	        argPos, ary, arity
	      ];

	      if (data) {
	        mergeData(newData, data);
	      }
	      func = newData[0];
	      bitmask = newData[1];
	      thisArg = newData[2];
	      partials = newData[3];
	      holders = newData[4];
	      arity = newData[9] = newData[9] == null
	        ? (isBindKey ? 0 : func.length)
	        : nativeMax(newData[9] - length, 0);

	      if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) {
	        bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG);
	      }
	      if (!bitmask || bitmask == BIND_FLAG) {
	        var result = createBaseWrapper(func, bitmask, thisArg);
	      } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) {
	        result = createCurryWrapper(func, bitmask, arity);
	      } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) {
	        result = createPartialWrapper(func, bitmask, thisArg, partials);
	      } else {
	        result = createHybridWrapper.apply(undefined, newData);
	      }
	      var setter = data ? baseSetData : setData;
	      return setter(result, newData);
	    }

	    /**
	     * A specialized version of `baseIsEqualDeep` for arrays with support for
	     * partial deep comparisons.
	     *
	     * @private
	     * @param {Array} array The array to compare.
	     * @param {Array} other The other array to compare.
	     * @param {Function} equalFunc The function to determine equivalents of values.
	     * @param {Function} customizer The function to customize comparisons.
	     * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
	     *  for more details.
	     * @param {Object} stack Tracks traversed `array` and `other` objects.
	     * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
	     */
	    function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
	      var index = -1,
	          isPartial = bitmask & PARTIAL_COMPARE_FLAG,
	          isUnordered = bitmask & UNORDERED_COMPARE_FLAG,
	          arrLength = array.length,
	          othLength = other.length;

	      if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
	        return false;
	      }
	      // Assume cyclic values are equal.
	      var stacked = stack.get(array);
	      if (stacked) {
	        return stacked == other;
	      }
	      var result = true;
	      stack.set(array, other);

	      // Ignore non-index properties.
	      while (++index < arrLength) {
	        var arrValue = array[index],
	            othValue = other[index];

	        if (customizer) {
	          var compared = isPartial
	            ? customizer(othValue, arrValue, index, other, array, stack)
	            : customizer(arrValue, othValue, index, array, other, stack);
	        }
	        if (compared !== undefined) {
	          if (compared) {
	            continue;
	          }
	          result = false;
	          break;
	        }
	        // Recursively compare arrays (susceptible to call stack limits).
	        if (isUnordered) {
	          if (!arraySome(other, function(othValue) {
	                return arrValue === othValue ||
	                  equalFunc(arrValue, othValue, customizer, bitmask, stack);
	              })) {
	            result = false;
	            break;
	          }
	        } else if (!(
	              arrValue === othValue ||
	                equalFunc(arrValue, othValue, customizer, bitmask, stack)
	            )) {
	          result = false;
	          break;
	        }
	      }
	      stack['delete'](array);
	      return result;
	    }

	    /**
	     * A specialized version of `baseIsEqualDeep` for comparing objects of
	     * the same `toStringTag`.
	     *
	     * **Note:** This function only supports comparing values with tags of
	     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
	     *
	     * @private
	     * @param {Object} object The object to compare.
	     * @param {Object} other The other object to compare.
	     * @param {string} tag The `toStringTag` of the objects to compare.
	     * @param {Function} equalFunc The function to determine equivalents of values.
	     * @param {Function} customizer The function to customize comparisons.
	     * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
	     *  for more details.
	     * @param {Object} stack Tracks traversed `object` and `other` objects.
	     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
	     */
	    function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {
	      switch (tag) {
	        case dataViewTag:
	          if ((object.byteLength != other.byteLength) ||
	              (object.byteOffset != other.byteOffset)) {
	            return false;
	          }
	          object = object.buffer;
	          other = other.buffer;

	        case arrayBufferTag:
	          if ((object.byteLength != other.byteLength) ||
	              !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
	            return false;
	          }
	          return true;

	        case boolTag:
	        case dateTag:
	          // Coerce dates and booleans to numbers, dates to milliseconds and
	          // booleans to `1` or `0` treating invalid dates coerced to `NaN` as
	          // not equal.
	          return +object == +other;

	        case errorTag:
	          return object.name == other.name && object.message == other.message;

	        case numberTag:
	          // Treat `NaN` vs. `NaN` as equal.
	          return (object != +object) ? other != +other : object == +other;

	        case regexpTag:
	        case stringTag:
	          // Coerce regexes to strings and treat strings, primitives and objects,
	          // as equal. See http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.tostring
	          // for more details.
	          return object == (other + '');

	        case mapTag:
	          var convert = mapToArray;

	        case setTag:
	          var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
	          convert || (convert = setToArray);

	          if (object.size != other.size && !isPartial) {
	            return false;
	          }
	          // Assume cyclic values are equal.
	          var stacked = stack.get(object);
	          if (stacked) {
	            return stacked == other;
	          }
	          bitmask |= UNORDERED_COMPARE_FLAG;
	          stack.set(object, other);

	          // Recursively compare objects (susceptible to call stack limits).
	          return equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);

	        case symbolTag:
	          if (symbolValueOf) {
	            return symbolValueOf.call(object) == symbolValueOf.call(other);
	          }
	      }
	      return false;
	    }

	    /**
	     * A specialized version of `baseIsEqualDeep` for objects with support for
	     * partial deep comparisons.
	     *
	     * @private
	     * @param {Object} object The object to compare.
	     * @param {Object} other The other object to compare.
	     * @param {Function} equalFunc The function to determine equivalents of values.
	     * @param {Function} customizer The function to customize comparisons.
	     * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
	     *  for more details.
	     * @param {Object} stack Tracks traversed `object` and `other` objects.
	     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
	     */
	    function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
	      var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
	          objProps = keys(object),
	          objLength = objProps.length,
	          othProps = keys(other),
	          othLength = othProps.length;

	      if (objLength != othLength && !isPartial) {
	        return false;
	      }
	      var index = objLength;
	      while (index--) {
	        var key = objProps[index];
	        if (!(isPartial ? key in other : baseHas(other, key))) {
	          return false;
	        }
	      }
	      // Assume cyclic values are equal.
	      var stacked = stack.get(object);
	      if (stacked) {
	        return stacked == other;
	      }
	      var result = true;
	      stack.set(object, other);

	      var skipCtor = isPartial;
	      while (++index < objLength) {
	        key = objProps[index];
	        var objValue = object[key],
	            othValue = other[key];

	        if (customizer) {
	          var compared = isPartial
	            ? customizer(othValue, objValue, key, other, object, stack)
	            : customizer(objValue, othValue, key, object, other, stack);
	        }
	        // Recursively compare objects (susceptible to call stack limits).
	        if (!(compared === undefined
	              ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
	              : compared
	            )) {
	          result = false;
	          break;
	        }
	        skipCtor || (skipCtor = key == 'constructor');
	      }
	      if (result && !skipCtor) {
	        var objCtor = object.constructor,
	            othCtor = other.constructor;

	        // Non `Object` object instances with different constructors are not equal.
	        if (objCtor != othCtor &&
	            ('constructor' in object && 'constructor' in other) &&
	            !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
	              typeof othCtor == 'function' && othCtor instanceof othCtor)) {
	          result = false;
	        }
	      }
	      stack['delete'](object);
	      return result;
	    }

	    /**
	     * Creates an array of own enumerable property names and symbols of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property names and symbols.
	     */
	    function getAllKeys(object) {
	      return baseGetAllKeys(object, keys, getSymbols);
	    }

	    /**
	     * Creates an array of own and inherited enumerable property names and
	     * symbols of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property names and symbols.
	     */
	    function getAllKeysIn(object) {
	      return baseGetAllKeys(object, keysIn, getSymbolsIn);
	    }

	    /**
	     * Gets metadata for `func`.
	     *
	     * @private
	     * @param {Function} func The function to query.
	     * @returns {*} Returns the metadata for `func`.
	     */
	    var getData = !metaMap ? noop : function(func) {
	      return metaMap.get(func);
	    };

	    /**
	     * Gets the name of `func`.
	     *
	     * @private
	     * @param {Function} func The function to query.
	     * @returns {string} Returns the function name.
	     */
	    function getFuncName(func) {
	      var result = (func.name + ''),
	          array = realNames[result],
	          length = hasOwnProperty.call(realNames, result) ? array.length : 0;

	      while (length--) {
	        var data = array[length],
	            otherFunc = data.func;
	        if (otherFunc == null || otherFunc == func) {
	          return data.name;
	        }
	      }
	      return result;
	    }

	    /**
	     * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
	     * this function returns the custom method, otherwise it returns `baseIteratee`.
	     * If arguments are provided, the chosen function is invoked with them and
	     * its result is returned.
	     *
	     * @private
	     * @param {*} [value] The value to convert to an iteratee.
	     * @param {number} [arity] The arity of the created iteratee.
	     * @returns {Function} Returns the chosen function or its result.
	     */
	    function getIteratee() {
	      var result = lodash.iteratee || iteratee;
	      result = result === iteratee ? baseIteratee : result;
	      return arguments.length ? result(arguments[0], arguments[1]) : result;
	    }

	    /**
	     * Gets the "length" property value of `object`.
	     *
	     * **Note:** This function is used to avoid a
	     * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects
	     * Safari on at least iOS 8.1-8.3 ARM64.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {*} Returns the "length" value.
	     */
	    var getLength = baseProperty('length');

	    /**
	     * Gets the property names, values, and compare flags of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the match data of `object`.
	     */
	    function getMatchData(object) {
	      var result = toPairs(object),
	          length = result.length;

	      while (length--) {
	        result[length][2] = isStrictComparable(result[length][1]);
	      }
	      return result;
	    }

	    /**
	     * Gets the native function at `key` of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {string} key The key of the method to get.
	     * @returns {*} Returns the function if it's native, else `undefined`.
	     */
	    function getNative(object, key) {
	      var value = object[key];
	      return isNative(value) ? value : undefined;
	    }

	    /**
	     * Gets the argument placeholder value for `func`.
	     *
	     * @private
	     * @param {Function} func The function to inspect.
	     * @returns {*} Returns the placeholder value.
	     */
	    function getPlaceholder(func) {
	      var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
	      return object.placeholder;
	    }

	    /**
	     * Gets the `[[Prototype]]` of `value`.
	     *
	     * @private
	     * @param {*} value The value to query.
	     * @returns {null|Object} Returns the `[[Prototype]]`.
	     */
	    function getPrototype(value) {
	      return nativeGetPrototype(Object(value));
	    }

	    /**
	     * Creates an array of the own enumerable symbol properties of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of symbols.
	     */
	    function getSymbols(object) {
	      // Coerce `object` to an object to avoid non-object errors in V8.
	      // See https://bugs.chromium.org/p/v8/issues/detail?id=3443 for more details.
	      return getOwnPropertySymbols(Object(object));
	    }

	    // Fallback for IE < 11.
	    if (!getOwnPropertySymbols) {
	      getSymbols = function() {
	        return [];
	      };
	    }

	    /**
	     * Creates an array of the own and inherited enumerable symbol properties
	     * of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of symbols.
	     */
	    var getSymbolsIn = !getOwnPropertySymbols ? getSymbols : function(object) {
	      var result = [];
	      while (object) {
	        arrayPush(result, getSymbols(object));
	        object = getPrototype(object);
	      }
	      return result;
	    };

	    /**
	     * Gets the `toStringTag` of `value`.
	     *
	     * @private
	     * @param {*} value The value to query.
	     * @returns {string} Returns the `toStringTag`.
	     */
	    function getTag(value) {
	      return objectToString.call(value);
	    }

	    // Fallback for data views, maps, sets, and weak maps in IE 11,
	    // for data views in Edge, and promises in Node.js.
	    if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
	        (Map && getTag(new Map) != mapTag) ||
	        (Promise && getTag(Promise.resolve()) != promiseTag) ||
	        (Set && getTag(new Set) != setTag) ||
	        (WeakMap && getTag(new WeakMap) != weakMapTag)) {
	      getTag = function(value) {
	        var result = objectToString.call(value),
	            Ctor = result == objectTag ? value.constructor : undefined,
	            ctorString = Ctor ? toSource(Ctor) : undefined;

	        if (ctorString) {
	          switch (ctorString) {
	            case dataViewCtorString: return dataViewTag;
	            case mapCtorString: return mapTag;
	            case promiseCtorString: return promiseTag;
	            case setCtorString: return setTag;
	            case weakMapCtorString: return weakMapTag;
	          }
	        }
	        return result;
	      };
	    }

	    /**
	     * Gets the view, applying any `transforms` to the `start` and `end` positions.
	     *
	     * @private
	     * @param {number} start The start of the view.
	     * @param {number} end The end of the view.
	     * @param {Array} transforms The transformations to apply to the view.
	     * @returns {Object} Returns an object containing the `start` and `end`
	     *  positions of the view.
	     */
	    function getView(start, end, transforms) {
	      var index = -1,
	          length = transforms.length;

	      while (++index < length) {
	        var data = transforms[index],
	            size = data.size;

	        switch (data.type) {
	          case 'drop':      start += size; break;
	          case 'dropRight': end -= size; break;
	          case 'take':      end = nativeMin(end, start + size); break;
	          case 'takeRight': start = nativeMax(start, end - size); break;
	        }
	      }
	      return { 'start': start, 'end': end };
	    }

	    /**
	     * Checks if `path` exists on `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path to check.
	     * @param {Function} hasFunc The function to check properties.
	     * @returns {boolean} Returns `true` if `path` exists, else `false`.
	     */
	    function hasPath(object, path, hasFunc) {
	      path = isKey(path, object) ? [path] : castPath(path);

	      var result,
	          index = -1,
	          length = path.length;

	      while (++index < length) {
	        var key = path[index];
	        if (!(result = object != null && hasFunc(object, key))) {
	          break;
	        }
	        object = object[key];
	      }
	      if (result) {
	        return result;
	      }
	      var length = object ? object.length : 0;
	      return !!length && isLength(length) && isIndex(key, length) &&
	        (isArray(object) || isString(object) || isArguments(object));
	    }

	    /**
	     * Initializes an array clone.
	     *
	     * @private
	     * @param {Array} array The array to clone.
	     * @returns {Array} Returns the initialized clone.
	     */
	    function initCloneArray(array) {
	      var length = array.length,
	          result = array.constructor(length);

	      // Add properties assigned by `RegExp#exec`.
	      if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
	        result.index = array.index;
	        result.input = array.input;
	      }
	      return result;
	    }

	    /**
	     * Initializes an object clone.
	     *
	     * @private
	     * @param {Object} object The object to clone.
	     * @returns {Object} Returns the initialized clone.
	     */
	    function initCloneObject(object) {
	      return (typeof object.constructor == 'function' && !isPrototype(object))
	        ? baseCreate(getPrototype(object))
	        : {};
	    }

	    /**
	     * Initializes an object clone based on its `toStringTag`.
	     *
	     * **Note:** This function only supports cloning values with tags of
	     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
	     *
	     * @private
	     * @param {Object} object The object to clone.
	     * @param {string} tag The `toStringTag` of the object to clone.
	     * @param {Function} cloneFunc The function to clone values.
	     * @param {boolean} [isDeep] Specify a deep clone.
	     * @returns {Object} Returns the initialized clone.
	     */
	    function initCloneByTag(object, tag, cloneFunc, isDeep) {
	      var Ctor = object.constructor;
	      switch (tag) {
	        case arrayBufferTag:
	          return cloneArrayBuffer(object);

	        case boolTag:
	        case dateTag:
	          return new Ctor(+object);

	        case dataViewTag:
	          return cloneDataView(object, isDeep);

	        case float32Tag: case float64Tag:
	        case int8Tag: case int16Tag: case int32Tag:
	        case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
	          return cloneTypedArray(object, isDeep);

	        case mapTag:
	          return cloneMap(object, isDeep, cloneFunc);

	        case numberTag:
	        case stringTag:
	          return new Ctor(object);

	        case regexpTag:
	          return cloneRegExp(object);

	        case setTag:
	          return cloneSet(object, isDeep, cloneFunc);

	        case symbolTag:
	          return cloneSymbol(object);
	      }
	    }

	    /**
	     * Creates an array of index keys for `object` values of arrays,
	     * `arguments` objects, and strings, otherwise `null` is returned.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @returns {Array|null} Returns index keys, else `null`.
	     */
	    function indexKeys(object) {
	      var length = object ? object.length : undefined;
	      if (isLength(length) &&
	          (isArray(object) || isString(object) || isArguments(object))) {
	        return baseTimes(length, String);
	      }
	      return null;
	    }

	    /**
	     * Checks if `value` is a flattenable `arguments` object or array.
	     *
	     * @private
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
	     */
	    function isFlattenable(value) {
	      return isArrayLikeObject(value) && (isArray(value) || isArguments(value));
	    }

	    /**
	     * Checks if `value` is a flattenable array and not a `_.matchesProperty`
	     * iteratee shorthand.
	     *
	     * @private
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
	     */
	    function isFlattenableIteratee(value) {
	      return isArray(value) && !(value.length == 2 && !isFunction(value[0]));
	    }

	    /**
	     * Checks if the given arguments are from an iteratee call.
	     *
	     * @private
	     * @param {*} value The potential iteratee value argument.
	     * @param {*} index The potential iteratee index or key argument.
	     * @param {*} object The potential iteratee object argument.
	     * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
	     *  else `false`.
	     */
	    function isIterateeCall(value, index, object) {
	      if (!isObject(object)) {
	        return false;
	      }
	      var type = typeof index;
	      if (type == 'number'
	            ? (isArrayLike(object) && isIndex(index, object.length))
	            : (type == 'string' && index in object)
	          ) {
	        return eq(object[index], value);
	      }
	      return false;
	    }

	    /**
	     * Checks if `value` is a property name and not a property path.
	     *
	     * @private
	     * @param {*} value The value to check.
	     * @param {Object} [object] The object to query keys on.
	     * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
	     */
	    function isKey(value, object) {
	      var type = typeof value;
	      if (type == 'number' || type == 'symbol') {
	        return true;
	      }
	      return !isArray(value) &&
	        (isSymbol(value) || reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
	          (object != null && value in Object(object)));
	    }

	    /**
	     * Checks if `value` is suitable for use as unique object key.
	     *
	     * @private
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
	     */
	    function isKeyable(value) {
	      var type = typeof value;
	      return type == 'number' || type == 'boolean' ||
	        (type == 'string' && value != '__proto__') || value == null;
	    }

	    /**
	     * Checks if `func` has a lazy counterpart.
	     *
	     * @private
	     * @param {Function} func The function to check.
	     * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
	     *  else `false`.
	     */
	    function isLaziable(func) {
	      var funcName = getFuncName(func),
	          other = lodash[funcName];

	      if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
	        return false;
	      }
	      if (func === other) {
	        return true;
	      }
	      var data = getData(other);
	      return !!data && func === data[0];
	    }

	    /**
	     * Checks if `value` is likely a prototype object.
	     *
	     * @private
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
	     */
	    function isPrototype(value) {
	      var Ctor = value && value.constructor,
	          proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

	      return value === proto;
	    }

	    /**
	     * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
	     *
	     * @private
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` if suitable for strict
	     *  equality comparisons, else `false`.
	     */
	    function isStrictComparable(value) {
	      return value === value && !isObject(value);
	    }

	    /**
	     * A specialized version of `matchesProperty` for source values suitable
	     * for strict equality comparisons, i.e. `===`.
	     *
	     * @private
	     * @param {string} key The key of the property to get.
	     * @param {*} srcValue The value to match.
	     * @returns {Function} Returns the new function.
	     */
	    function matchesStrictComparable(key, srcValue) {
	      return function(object) {
	        if (object == null) {
	          return false;
	        }
	        return object[key] === srcValue &&
	          (srcValue !== undefined || (key in Object(object)));
	      };
	    }

	    /**
	     * Merges the function metadata of `source` into `data`.
	     *
	     * Merging metadata reduces the number of wrappers used to invoke a function.
	     * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
	     * may be applied regardless of execution order. Methods like `_.ary` and
	     * `_.rearg` modify function arguments, making the order in which they are
	     * executed important, preventing the merging of metadata. However, we make
	     * an exception for a safe combined case where curried functions have `_.ary`
	     * and or `_.rearg` applied.
	     *
	     * @private
	     * @param {Array} data The destination metadata.
	     * @param {Array} source The source metadata.
	     * @returns {Array} Returns `data`.
	     */
	    function mergeData(data, source) {
	      var bitmask = data[1],
	          srcBitmask = source[1],
	          newBitmask = bitmask | srcBitmask,
	          isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG);

	      var isCombo =
	        ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) ||
	        ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) ||
	        ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG));

	      // Exit early if metadata can't be merged.
	      if (!(isCommon || isCombo)) {
	        return data;
	      }
	      // Use source `thisArg` if available.
	      if (srcBitmask & BIND_FLAG) {
	        data[2] = source[2];
	        // Set when currying a bound function.
	        newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG;
	      }
	      // Compose partial arguments.
	      var value = source[3];
	      if (value) {
	        var partials = data[3];
	        data[3] = partials ? composeArgs(partials, value, source[4]) : value;
	        data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
	      }
	      // Compose partial right arguments.
	      value = source[5];
	      if (value) {
	        partials = data[5];
	        data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
	        data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
	      }
	      // Use source `argPos` if available.
	      value = source[7];
	      if (value) {
	        data[7] = value;
	      }
	      // Use source `ary` if it's smaller.
	      if (srcBitmask & ARY_FLAG) {
	        data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
	      }
	      // Use source `arity` if one is not provided.
	      if (data[9] == null) {
	        data[9] = source[9];
	      }
	      // Use source `func` and merge bitmasks.
	      data[0] = source[0];
	      data[1] = newBitmask;

	      return data;
	    }

	    /**
	     * Used by `_.defaultsDeep` to customize its `_.merge` use.
	     *
	     * @private
	     * @param {*} objValue The destination value.
	     * @param {*} srcValue The source value.
	     * @param {string} key The key of the property to merge.
	     * @param {Object} object The parent object of `objValue`.
	     * @param {Object} source The parent object of `srcValue`.
	     * @param {Object} [stack] Tracks traversed source values and their merged
	     *  counterparts.
	     * @returns {*} Returns the value to assign.
	     */
	    function mergeDefaults(objValue, srcValue, key, object, source, stack) {
	      if (isObject(objValue) && isObject(srcValue)) {
	        baseMerge(objValue, srcValue, undefined, mergeDefaults, stack.set(srcValue, objValue));
	      }
	      return objValue;
	    }

	    /**
	     * Gets the parent value at `path` of `object`.
	     *
	     * @private
	     * @param {Object} object The object to query.
	     * @param {Array} path The path to get the parent value of.
	     * @returns {*} Returns the parent value.
	     */
	    function parent(object, path) {
	      return path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
	    }

	    /**
	     * Reorder `array` according to the specified indexes where the element at
	     * the first index is assigned as the first element, the element at
	     * the second index is assigned as the second element, and so on.
	     *
	     * @private
	     * @param {Array} array The array to reorder.
	     * @param {Array} indexes The arranged array indexes.
	     * @returns {Array} Returns `array`.
	     */
	    function reorder(array, indexes) {
	      var arrLength = array.length,
	          length = nativeMin(indexes.length, arrLength),
	          oldArray = copyArray(array);

	      while (length--) {
	        var index = indexes[length];
	        array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
	      }
	      return array;
	    }

	    /**
	     * Sets metadata for `func`.
	     *
	     * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
	     * period of time, it will trip its breaker and transition to an identity
	     * function to avoid garbage collection pauses in V8. See
	     * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
	     * for more details.
	     *
	     * @private
	     * @param {Function} func The function to associate metadata with.
	     * @param {*} data The metadata.
	     * @returns {Function} Returns `func`.
	     */
	    var setData = (function() {
	      var count = 0,
	          lastCalled = 0;

	      return function(key, value) {
	        var stamp = now(),
	            remaining = HOT_SPAN - (stamp - lastCalled);

	        lastCalled = stamp;
	        if (remaining > 0) {
	          if (++count >= HOT_COUNT) {
	            return key;
	          }
	        } else {
	          count = 0;
	        }
	        return baseSetData(key, value);
	      };
	    }());

	    /**
	     * Converts `string` to a property path array.
	     *
	     * @private
	     * @param {string} string The string to convert.
	     * @returns {Array} Returns the property path array.
	     */
	    var stringToPath = memoize(function(string) {
	      var result = [];
	      toString(string).replace(rePropName, function(match, number, quote, string) {
	        result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
	      });
	      return result;
	    });

	    /**
	     * Converts `value` to a string key if it's not a string or symbol.
	     *
	     * @private
	     * @param {*} value The value to inspect.
	     * @returns {string|symbol} Returns the key.
	     */
	    function toKey(key) {
	      return (typeof key == 'string' || isSymbol(key)) ? key : (key + '');
	    }

	    /**
	     * Converts `func` to its source code.
	     *
	     * @private
	     * @param {Function} func The function to process.
	     * @returns {string} Returns the source code.
	     */
	    function toSource(func) {
	      if (func != null) {
	        try {
	          return funcToString.call(func);
	        } catch (e) {}
	        try {
	          return (func + '');
	        } catch (e) {}
	      }
	      return '';
	    }

	    /**
	     * Creates a clone of `wrapper`.
	     *
	     * @private
	     * @param {Object} wrapper The wrapper to clone.
	     * @returns {Object} Returns the cloned wrapper.
	     */
	    function wrapperClone(wrapper) {
	      if (wrapper instanceof LazyWrapper) {
	        return wrapper.clone();
	      }
	      var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
	      result.__actions__ = copyArray(wrapper.__actions__);
	      result.__index__  = wrapper.__index__;
	      result.__values__ = wrapper.__values__;
	      return result;
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates an array of elements split into groups the length of `size`.
	     * If `array` can't be split evenly, the final chunk will be the remaining
	     * elements.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to process.
	     * @param {number} [size=1] The length of each chunk
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Array} Returns the new array containing chunks.
	     * @example
	     *
	     * _.chunk(['a', 'b', 'c', 'd'], 2);
	     * // => [['a', 'b'], ['c', 'd']]
	     *
	     * _.chunk(['a', 'b', 'c', 'd'], 3);
	     * // => [['a', 'b', 'c'], ['d']]
	     */
	    function chunk(array, size, guard) {
	      if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
	        size = 1;
	      } else {
	        size = nativeMax(toInteger(size), 0);
	      }
	      var length = array ? array.length : 0;
	      if (!length || size < 1) {
	        return [];
	      }
	      var index = 0,
	          resIndex = 0,
	          result = Array(nativeCeil(length / size));

	      while (index < length) {
	        result[resIndex++] = baseSlice(array, index, (index += size));
	      }
	      return result;
	    }

	    /**
	     * Creates an array with all falsey values removed. The values `false`, `null`,
	     * `0`, `""`, `undefined`, and `NaN` are falsey.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to compact.
	     * @returns {Array} Returns the new array of filtered values.
	     * @example
	     *
	     * _.compact([0, 1, false, 2, '', 3]);
	     * // => [1, 2, 3]
	     */
	    function compact(array) {
	      var index = -1,
	          length = array ? array.length : 0,
	          resIndex = 0,
	          result = [];

	      while (++index < length) {
	        var value = array[index];
	        if (value) {
	          result[resIndex++] = value;
	        }
	      }
	      return result;
	    }

	    /**
	     * Creates a new array concatenating `array` with any additional arrays
	     * and/or values.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to concatenate.
	     * @param {...*} [values] The values to concatenate.
	     * @returns {Array} Returns the new concatenated array.
	     * @example
	     *
	     * var array = [1];
	     * var other = _.concat(array, 2, [3], [[4]]);
	     *
	     * console.log(other);
	     * // => [1, 2, 3, [4]]
	     *
	     * console.log(array);
	     * // => [1]
	     */
	    function concat() {
	      var length = arguments.length,
	          array = castArray(arguments[0]);

	      if (length < 2) {
	        return length ? copyArray(array) : [];
	      }
	      var args = Array(length - 1);
	      while (length--) {
	        args[length - 1] = arguments[length];
	      }
	      return arrayConcat(array, baseFlatten(args, 1));
	    }

	    /**
	     * Creates an array of unique `array` values not included in the other given
	     * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons. The order of result values is determined by the
	     * order they occur in the first array.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @param {...Array} [values] The values to exclude.
	     * @returns {Array} Returns the new array of filtered values.
	     * @example
	     *
	     * _.difference([3, 2, 1], [4, 2]);
	     * // => [3, 1]
	     */
	    var difference = rest(function(array, values) {
	      return isArrayLikeObject(array)
	        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
	        : [];
	    });

	    /**
	     * This method is like `_.difference` except that it accepts `iteratee` which
	     * is invoked for each element of `array` and `values` to generate the criterion
	     * by which they're compared. Result values are chosen from the first array.
	     * The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @param {...Array} [values] The values to exclude.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {Array} Returns the new array of filtered values.
	     * @example
	     *
	     * _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
	     * // => [3.1, 1.3]
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
	     * // => [{ 'x': 2 }]
	     */
	    var differenceBy = rest(function(array, values) {
	      var iteratee = last(values);
	      if (isArrayLikeObject(iteratee)) {
	        iteratee = undefined;
	      }
	      return isArrayLikeObject(array)
	        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee))
	        : [];
	    });

	    /**
	     * This method is like `_.difference` except that it accepts `comparator`
	     * which is invoked to compare elements of `array` to `values`. Result values
	     * are chosen from the first array. The comparator is invoked with two arguments:
	     * (arrVal, othVal).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @param {...Array} [values] The values to exclude.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new array of filtered values.
	     * @example
	     *
	     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
	     *
	     * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
	     * // => [{ 'x': 2, 'y': 1 }]
	     */
	    var differenceWith = rest(function(array, values) {
	      var comparator = last(values);
	      if (isArrayLikeObject(comparator)) {
	        comparator = undefined;
	      }
	      return isArrayLikeObject(array)
	        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
	        : [];
	    });

	    /**
	     * Creates a slice of `array` with `n` elements dropped from the beginning.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.5.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {number} [n=1] The number of elements to drop.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * _.drop([1, 2, 3]);
	     * // => [2, 3]
	     *
	     * _.drop([1, 2, 3], 2);
	     * // => [3]
	     *
	     * _.drop([1, 2, 3], 5);
	     * // => []
	     *
	     * _.drop([1, 2, 3], 0);
	     * // => [1, 2, 3]
	     */
	    function drop(array, n, guard) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return [];
	      }
	      n = (guard || n === undefined) ? 1 : toInteger(n);
	      return baseSlice(array, n < 0 ? 0 : n, length);
	    }

	    /**
	     * Creates a slice of `array` with `n` elements dropped from the end.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {number} [n=1] The number of elements to drop.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * _.dropRight([1, 2, 3]);
	     * // => [1, 2]
	     *
	     * _.dropRight([1, 2, 3], 2);
	     * // => [1]
	     *
	     * _.dropRight([1, 2, 3], 5);
	     * // => []
	     *
	     * _.dropRight([1, 2, 3], 0);
	     * // => [1, 2, 3]
	     */
	    function dropRight(array, n, guard) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return [];
	      }
	      n = (guard || n === undefined) ? 1 : toInteger(n);
	      n = length - n;
	      return baseSlice(array, 0, n < 0 ? 0 : n);
	    }

	    /**
	     * Creates a slice of `array` excluding elements dropped from the end.
	     * Elements are dropped until `predicate` returns falsey. The predicate is
	     * invoked with three arguments: (value, index, array).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'active': true },
	     *   { 'user': 'fred',    'active': false },
	     *   { 'user': 'pebbles', 'active': false }
	     * ];
	     *
	     * _.dropRightWhile(users, function(o) { return !o.active; });
	     * // => objects for ['barney']
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
	     * // => objects for ['barney', 'fred']
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.dropRightWhile(users, ['active', false]);
	     * // => objects for ['barney']
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.dropRightWhile(users, 'active');
	     * // => objects for ['barney', 'fred', 'pebbles']
	     */
	    function dropRightWhile(array, predicate) {
	      return (array && array.length)
	        ? baseWhile(array, getIteratee(predicate, 3), true, true)
	        : [];
	    }

	    /**
	     * Creates a slice of `array` excluding elements dropped from the beginning.
	     * Elements are dropped until `predicate` returns falsey. The predicate is
	     * invoked with three arguments: (value, index, array).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'active': false },
	     *   { 'user': 'fred',    'active': false },
	     *   { 'user': 'pebbles', 'active': true }
	     * ];
	     *
	     * _.dropWhile(users, function(o) { return !o.active; });
	     * // => objects for ['pebbles']
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.dropWhile(users, { 'user': 'barney', 'active': false });
	     * // => objects for ['fred', 'pebbles']
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.dropWhile(users, ['active', false]);
	     * // => objects for ['pebbles']
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.dropWhile(users, 'active');
	     * // => objects for ['barney', 'fred', 'pebbles']
	     */
	    function dropWhile(array, predicate) {
	      return (array && array.length)
	        ? baseWhile(array, getIteratee(predicate, 3), true)
	        : [];
	    }

	    /**
	     * Fills elements of `array` with `value` from `start` up to, but not
	     * including, `end`.
	     *
	     * **Note:** This method mutates `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.2.0
	     * @category Array
	     * @param {Array} array The array to fill.
	     * @param {*} value The value to fill `array` with.
	     * @param {number} [start=0] The start position.
	     * @param {number} [end=array.length] The end position.
	     * @returns {Array} Returns `array`.
	     * @example
	     *
	     * var array = [1, 2, 3];
	     *
	     * _.fill(array, 'a');
	     * console.log(array);
	     * // => ['a', 'a', 'a']
	     *
	     * _.fill(Array(3), 2);
	     * // => [2, 2, 2]
	     *
	     * _.fill([4, 6, 8, 10], '*', 1, 3);
	     * // => [4, '*', '*', 10]
	     */
	    function fill(array, value, start, end) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return [];
	      }
	      if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
	        start = 0;
	        end = length;
	      }
	      return baseFill(array, value, start, end);
	    }

	    /**
	     * This method is like `_.find` except that it returns the index of the first
	     * element `predicate` returns truthy for instead of the element itself.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.1.0
	     * @category Array
	     * @param {Array} array The array to search.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {number} Returns the index of the found element, else `-1`.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'active': false },
	     *   { 'user': 'fred',    'active': false },
	     *   { 'user': 'pebbles', 'active': true }
	     * ];
	     *
	     * _.findIndex(users, function(o) { return o.user == 'barney'; });
	     * // => 0
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.findIndex(users, { 'user': 'fred', 'active': false });
	     * // => 1
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.findIndex(users, ['active', false]);
	     * // => 0
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.findIndex(users, 'active');
	     * // => 2
	     */
	    function findIndex(array, predicate) {
	      return (array && array.length)
	        ? baseFindIndex(array, getIteratee(predicate, 3))
	        : -1;
	    }

	    /**
	     * This method is like `_.findIndex` except that it iterates over elements
	     * of `collection` from right to left.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Array
	     * @param {Array} array The array to search.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {number} Returns the index of the found element, else `-1`.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'active': true },
	     *   { 'user': 'fred',    'active': false },
	     *   { 'user': 'pebbles', 'active': false }
	     * ];
	     *
	     * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
	     * // => 2
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.findLastIndex(users, { 'user': 'barney', 'active': true });
	     * // => 0
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.findLastIndex(users, ['active', false]);
	     * // => 2
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.findLastIndex(users, 'active');
	     * // => 0
	     */
	    function findLastIndex(array, predicate) {
	      return (array && array.length)
	        ? baseFindIndex(array, getIteratee(predicate, 3), true)
	        : -1;
	    }

	    /**
	     * Flattens `array` a single level deep.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to flatten.
	     * @returns {Array} Returns the new flattened array.
	     * @example
	     *
	     * _.flatten([1, [2, [3, [4]], 5]]);
	     * // => [1, 2, [3, [4]], 5]
	     */
	    function flatten(array) {
	      var length = array ? array.length : 0;
	      return length ? baseFlatten(array, 1) : [];
	    }

	    /**
	     * Recursively flattens `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to flatten.
	     * @returns {Array} Returns the new flattened array.
	     * @example
	     *
	     * _.flattenDeep([1, [2, [3, [4]], 5]]);
	     * // => [1, 2, 3, 4, 5]
	     */
	    function flattenDeep(array) {
	      var length = array ? array.length : 0;
	      return length ? baseFlatten(array, INFINITY) : [];
	    }

	    /**
	     * Recursively flatten `array` up to `depth` times.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.4.0
	     * @category Array
	     * @param {Array} array The array to flatten.
	     * @param {number} [depth=1] The maximum recursion depth.
	     * @returns {Array} Returns the new flattened array.
	     * @example
	     *
	     * var array = [1, [2, [3, [4]], 5]];
	     *
	     * _.flattenDepth(array, 1);
	     * // => [1, 2, [3, [4]], 5]
	     *
	     * _.flattenDepth(array, 2);
	     * // => [1, 2, 3, [4], 5]
	     */
	    function flattenDepth(array, depth) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return [];
	      }
	      depth = depth === undefined ? 1 : toInteger(depth);
	      return baseFlatten(array, depth);
	    }

	    /**
	     * The inverse of `_.toPairs`; this method returns an object composed
	     * from key-value `pairs`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} pairs The key-value pairs.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * _.fromPairs([['fred', 30], ['barney', 40]]);
	     * // => { 'fred': 30, 'barney': 40 }
	     */
	    function fromPairs(pairs) {
	      var index = -1,
	          length = pairs ? pairs.length : 0,
	          result = {};

	      while (++index < length) {
	        var pair = pairs[index];
	        result[pair[0]] = pair[1];
	      }
	      return result;
	    }

	    /**
	     * Gets the first element of `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @alias first
	     * @category Array
	     * @param {Array} array The array to query.
	     * @returns {*} Returns the first element of `array`.
	     * @example
	     *
	     * _.head([1, 2, 3]);
	     * // => 1
	     *
	     * _.head([]);
	     * // => undefined
	     */
	    function head(array) {
	      return (array && array.length) ? array[0] : undefined;
	    }

	    /**
	     * Gets the index at which the first occurrence of `value` is found in `array`
	     * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons. If `fromIndex` is negative, it's used as the
	     * offset from the end of `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to search.
	     * @param {*} value The value to search for.
	     * @param {number} [fromIndex=0] The index to search from.
	     * @returns {number} Returns the index of the matched value, else `-1`.
	     * @example
	     *
	     * _.indexOf([1, 2, 1, 2], 2);
	     * // => 1
	     *
	     * // Search from the `fromIndex`.
	     * _.indexOf([1, 2, 1, 2], 2, 2);
	     * // => 3
	     */
	    function indexOf(array, value, fromIndex) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return -1;
	      }
	      fromIndex = toInteger(fromIndex);
	      if (fromIndex < 0) {
	        fromIndex = nativeMax(length + fromIndex, 0);
	      }
	      return baseIndexOf(array, value, fromIndex);
	    }

	    /**
	     * Gets all but the last element of `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * _.initial([1, 2, 3]);
	     * // => [1, 2]
	     */
	    function initial(array) {
	      return dropRight(array, 1);
	    }

	    /**
	     * Creates an array of unique values that are included in all given arrays
	     * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons. The order of result values is determined by the
	     * order they occur in the first array.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @returns {Array} Returns the new array of intersecting values.
	     * @example
	     *
	     * _.intersection([2, 1], [4, 2], [1, 2]);
	     * // => [2]
	     */
	    var intersection = rest(function(arrays) {
	      var mapped = arrayMap(arrays, castArrayLikeObject);
	      return (mapped.length && mapped[0] === arrays[0])
	        ? baseIntersection(mapped)
	        : [];
	    });

	    /**
	     * This method is like `_.intersection` except that it accepts `iteratee`
	     * which is invoked for each element of each `arrays` to generate the criterion
	     * by which they're compared. Result values are chosen from the first array.
	     * The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {Array} Returns the new array of intersecting values.
	     * @example
	     *
	     * _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
	     * // => [2.1]
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
	     * // => [{ 'x': 1 }]
	     */
	    var intersectionBy = rest(function(arrays) {
	      var iteratee = last(arrays),
	          mapped = arrayMap(arrays, castArrayLikeObject);

	      if (iteratee === last(mapped)) {
	        iteratee = undefined;
	      } else {
	        mapped.pop();
	      }
	      return (mapped.length && mapped[0] === arrays[0])
	        ? baseIntersection(mapped, getIteratee(iteratee))
	        : [];
	    });

	    /**
	     * This method is like `_.intersection` except that it accepts `comparator`
	     * which is invoked to compare elements of `arrays`. Result values are chosen
	     * from the first array. The comparator is invoked with two arguments:
	     * (arrVal, othVal).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new array of intersecting values.
	     * @example
	     *
	     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
	     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
	     *
	     * _.intersectionWith(objects, others, _.isEqual);
	     * // => [{ 'x': 1, 'y': 2 }]
	     */
	    var intersectionWith = rest(function(arrays) {
	      var comparator = last(arrays),
	          mapped = arrayMap(arrays, castArrayLikeObject);

	      if (comparator === last(mapped)) {
	        comparator = undefined;
	      } else {
	        mapped.pop();
	      }
	      return (mapped.length && mapped[0] === arrays[0])
	        ? baseIntersection(mapped, undefined, comparator)
	        : [];
	    });

	    /**
	     * Converts all elements in `array` into a string separated by `separator`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to convert.
	     * @param {string} [separator=','] The element separator.
	     * @returns {string} Returns the joined string.
	     * @example
	     *
	     * _.join(['a', 'b', 'c'], '~');
	     * // => 'a~b~c'
	     */
	    function join(array, separator) {
	      return array ? nativeJoin.call(array, separator) : '';
	    }

	    /**
	     * Gets the last element of `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @returns {*} Returns the last element of `array`.
	     * @example
	     *
	     * _.last([1, 2, 3]);
	     * // => 3
	     */
	    function last(array) {
	      var length = array ? array.length : 0;
	      return length ? array[length - 1] : undefined;
	    }

	    /**
	     * This method is like `_.indexOf` except that it iterates over elements of
	     * `array` from right to left.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to search.
	     * @param {*} value The value to search for.
	     * @param {number} [fromIndex=array.length-1] The index to search from.
	     * @returns {number} Returns the index of the matched value, else `-1`.
	     * @example
	     *
	     * _.lastIndexOf([1, 2, 1, 2], 2);
	     * // => 3
	     *
	     * // Search from the `fromIndex`.
	     * _.lastIndexOf([1, 2, 1, 2], 2, 2);
	     * // => 1
	     */
	    function lastIndexOf(array, value, fromIndex) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return -1;
	      }
	      var index = length;
	      if (fromIndex !== undefined) {
	        index = toInteger(fromIndex);
	        index = (
	          index < 0
	            ? nativeMax(length + index, 0)
	            : nativeMin(index, length - 1)
	        ) + 1;
	      }
	      if (value !== value) {
	        return indexOfNaN(array, index, true);
	      }
	      while (index--) {
	        if (array[index] === value) {
	          return index;
	        }
	      }
	      return -1;
	    }

	    /**
	     * Gets the nth element of `array`. If `n` is negative, the nth element
	     * from the end is returned.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.11.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {number} [n=0] The index of the element to return.
	     * @returns {*} Returns the nth element of `array`.
	     * @example
	     *
	     * var array = ['a', 'b', 'c', 'd'];
	     *
	     * _.nth(array, 1);
	     * // => 'b'
	     *
	     * _.nth(array, -2);
	     * // => 'c';
	     */
	    function nth(array, n) {
	      return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
	    }

	    /**
	     * Removes all given values from `array` using
	     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons.
	     *
	     * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
	     * to remove elements from an array by predicate.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Array
	     * @param {Array} array The array to modify.
	     * @param {...*} [values] The values to remove.
	     * @returns {Array} Returns `array`.
	     * @example
	     *
	     * var array = [1, 2, 3, 1, 2, 3];
	     *
	     * _.pull(array, 2, 3);
	     * console.log(array);
	     * // => [1, 1]
	     */
	    var pull = rest(pullAll);

	    /**
	     * This method is like `_.pull` except that it accepts an array of values to remove.
	     *
	     * **Note:** Unlike `_.difference`, this method mutates `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to modify.
	     * @param {Array} values The values to remove.
	     * @returns {Array} Returns `array`.
	     * @example
	     *
	     * var array = [1, 2, 3, 1, 2, 3];
	     *
	     * _.pullAll(array, [2, 3]);
	     * console.log(array);
	     * // => [1, 1]
	     */
	    function pullAll(array, values) {
	      return (array && array.length && values && values.length)
	        ? basePullAll(array, values)
	        : array;
	    }

	    /**
	     * This method is like `_.pullAll` except that it accepts `iteratee` which is
	     * invoked for each element of `array` and `values` to generate the criterion
	     * by which they're compared. The iteratee is invoked with one argument: (value).
	     *
	     * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to modify.
	     * @param {Array} values The values to remove.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {Array} Returns `array`.
	     * @example
	     *
	     * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
	     *
	     * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
	     * console.log(array);
	     * // => [{ 'x': 2 }]
	     */
	    function pullAllBy(array, values, iteratee) {
	      return (array && array.length && values && values.length)
	        ? basePullAll(array, values, getIteratee(iteratee))
	        : array;
	    }

	    /**
	     * This method is like `_.pullAll` except that it accepts `comparator` which
	     * is invoked to compare elements of `array` to `values`. The comparator is
	     * invoked with two arguments: (arrVal, othVal).
	     *
	     * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.6.0
	     * @category Array
	     * @param {Array} array The array to modify.
	     * @param {Array} values The values to remove.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns `array`.
	     * @example
	     *
	     * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
	     *
	     * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
	     * console.log(array);
	     * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
	     */
	    function pullAllWith(array, values, comparator) {
	      return (array && array.length && values && values.length)
	        ? basePullAll(array, values, undefined, comparator)
	        : array;
	    }

	    /**
	     * Removes elements from `array` corresponding to `indexes` and returns an
	     * array of removed elements.
	     *
	     * **Note:** Unlike `_.at`, this method mutates `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to modify.
	     * @param {...(number|number[])} [indexes] The indexes of elements to remove.
	     * @returns {Array} Returns the new array of removed elements.
	     * @example
	     *
	     * var array = [5, 10, 15, 20];
	     * var evens = _.pullAt(array, 1, 3);
	     *
	     * console.log(array);
	     * // => [5, 15]
	     *
	     * console.log(evens);
	     * // => [10, 20]
	     */
	    var pullAt = rest(function(array, indexes) {
	      indexes = arrayMap(baseFlatten(indexes, 1), String);

	      var result = baseAt(array, indexes);
	      basePullAt(array, indexes.sort(compareAscending));
	      return result;
	    });

	    /**
	     * Removes all elements from `array` that `predicate` returns truthy for
	     * and returns an array of the removed elements. The predicate is invoked
	     * with three arguments: (value, index, array).
	     *
	     * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
	     * to pull elements from an array by value.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Array
	     * @param {Array} array The array to modify.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the new array of removed elements.
	     * @example
	     *
	     * var array = [1, 2, 3, 4];
	     * var evens = _.remove(array, function(n) {
	     *   return n % 2 == 0;
	     * });
	     *
	     * console.log(array);
	     * // => [1, 3]
	     *
	     * console.log(evens);
	     * // => [2, 4]
	     */
	    function remove(array, predicate) {
	      var result = [];
	      if (!(array && array.length)) {
	        return result;
	      }
	      var index = -1,
	          indexes = [],
	          length = array.length;

	      predicate = getIteratee(predicate, 3);
	      while (++index < length) {
	        var value = array[index];
	        if (predicate(value, index, array)) {
	          result.push(value);
	          indexes.push(index);
	        }
	      }
	      basePullAt(array, indexes);
	      return result;
	    }

	    /**
	     * Reverses `array` so that the first element becomes the last, the second
	     * element becomes the second to last, and so on.
	     *
	     * **Note:** This method mutates `array` and is based on
	     * [`Array#reverse`](https://mdn.io/Array/reverse).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to modify.
	     * @returns {Array} Returns `array`.
	     * @example
	     *
	     * var array = [1, 2, 3];
	     *
	     * _.reverse(array);
	     * // => [3, 2, 1]
	     *
	     * console.log(array);
	     * // => [3, 2, 1]
	     */
	    function reverse(array) {
	      return array ? nativeReverse.call(array) : array;
	    }

	    /**
	     * Creates a slice of `array` from `start` up to, but not including, `end`.
	     *
	     * **Note:** This method is used instead of
	     * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
	     * returned.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to slice.
	     * @param {number} [start=0] The start position.
	     * @param {number} [end=array.length] The end position.
	     * @returns {Array} Returns the slice of `array`.
	     */
	    function slice(array, start, end) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return [];
	      }
	      if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
	        start = 0;
	        end = length;
	      }
	      else {
	        start = start == null ? 0 : toInteger(start);
	        end = end === undefined ? length : toInteger(end);
	      }
	      return baseSlice(array, start, end);
	    }

	    /**
	     * Uses a binary search to determine the lowest index at which `value`
	     * should be inserted into `array` in order to maintain its sort order.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The sorted array to inspect.
	     * @param {*} value The value to evaluate.
	     * @returns {number} Returns the index at which `value` should be inserted
	     *  into `array`.
	     * @example
	     *
	     * _.sortedIndex([30, 50], 40);
	     * // => 1
	     *
	     * _.sortedIndex([4, 5], 4);
	     * // => 0
	     */
	    function sortedIndex(array, value) {
	      return baseSortedIndex(array, value);
	    }

	    /**
	     * This method is like `_.sortedIndex` except that it accepts `iteratee`
	     * which is invoked for `value` and each element of `array` to compute their
	     * sort ranking. The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The sorted array to inspect.
	     * @param {*} value The value to evaluate.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {number} Returns the index at which `value` should be inserted
	     *  into `array`.
	     * @example
	     *
	     * var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 };
	     *
	     * _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict));
	     * // => 1
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
	     * // => 0
	     */
	    function sortedIndexBy(array, value, iteratee) {
	      return baseSortedIndexBy(array, value, getIteratee(iteratee));
	    }

	    /**
	     * This method is like `_.indexOf` except that it performs a binary
	     * search on a sorted `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to search.
	     * @param {*} value The value to search for.
	     * @returns {number} Returns the index of the matched value, else `-1`.
	     * @example
	     *
	     * _.sortedIndexOf([1, 1, 2, 2], 2);
	     * // => 2
	     */
	    function sortedIndexOf(array, value) {
	      var length = array ? array.length : 0;
	      if (length) {
	        var index = baseSortedIndex(array, value);
	        if (index < length && eq(array[index], value)) {
	          return index;
	        }
	      }
	      return -1;
	    }

	    /**
	     * This method is like `_.sortedIndex` except that it returns the highest
	     * index at which `value` should be inserted into `array` in order to
	     * maintain its sort order.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The sorted array to inspect.
	     * @param {*} value The value to evaluate.
	     * @returns {number} Returns the index at which `value` should be inserted
	     *  into `array`.
	     * @example
	     *
	     * _.sortedLastIndex([4, 5], 4);
	     * // => 1
	     */
	    function sortedLastIndex(array, value) {
	      return baseSortedIndex(array, value, true);
	    }

	    /**
	     * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
	     * which is invoked for `value` and each element of `array` to compute their
	     * sort ranking. The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The sorted array to inspect.
	     * @param {*} value The value to evaluate.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {number} Returns the index at which `value` should be inserted
	     *  into `array`.
	     * @example
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
	     * // => 1
	     */
	    function sortedLastIndexBy(array, value, iteratee) {
	      return baseSortedIndexBy(array, value, getIteratee(iteratee), true);
	    }

	    /**
	     * This method is like `_.lastIndexOf` except that it performs a binary
	     * search on a sorted `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to search.
	     * @param {*} value The value to search for.
	     * @returns {number} Returns the index of the matched value, else `-1`.
	     * @example
	     *
	     * _.sortedLastIndexOf([1, 1, 2, 2], 2);
	     * // => 3
	     */
	    function sortedLastIndexOf(array, value) {
	      var length = array ? array.length : 0;
	      if (length) {
	        var index = baseSortedIndex(array, value, true) - 1;
	        if (eq(array[index], value)) {
	          return index;
	        }
	      }
	      return -1;
	    }

	    /**
	     * This method is like `_.uniq` except that it's designed and optimized
	     * for sorted arrays.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @returns {Array} Returns the new duplicate free array.
	     * @example
	     *
	     * _.sortedUniq([1, 1, 2]);
	     * // => [1, 2]
	     */
	    function sortedUniq(array) {
	      return (array && array.length)
	        ? baseSortedUniq(array)
	        : [];
	    }

	    /**
	     * This method is like `_.uniqBy` except that it's designed and optimized
	     * for sorted arrays.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @param {Function} [iteratee] The iteratee invoked per element.
	     * @returns {Array} Returns the new duplicate free array.
	     * @example
	     *
	     * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
	     * // => [1.1, 2.3]
	     */
	    function sortedUniqBy(array, iteratee) {
	      return (array && array.length)
	        ? baseSortedUniqBy(array, getIteratee(iteratee))
	        : [];
	    }

	    /**
	     * Gets all but the first element of `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * _.tail([1, 2, 3]);
	     * // => [2, 3]
	     */
	    function tail(array) {
	      return drop(array, 1);
	    }

	    /**
	     * Creates a slice of `array` with `n` elements taken from the beginning.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {number} [n=1] The number of elements to take.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * _.take([1, 2, 3]);
	     * // => [1]
	     *
	     * _.take([1, 2, 3], 2);
	     * // => [1, 2]
	     *
	     * _.take([1, 2, 3], 5);
	     * // => [1, 2, 3]
	     *
	     * _.take([1, 2, 3], 0);
	     * // => []
	     */
	    function take(array, n, guard) {
	      if (!(array && array.length)) {
	        return [];
	      }
	      n = (guard || n === undefined) ? 1 : toInteger(n);
	      return baseSlice(array, 0, n < 0 ? 0 : n);
	    }

	    /**
	     * Creates a slice of `array` with `n` elements taken from the end.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {number} [n=1] The number of elements to take.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * _.takeRight([1, 2, 3]);
	     * // => [3]
	     *
	     * _.takeRight([1, 2, 3], 2);
	     * // => [2, 3]
	     *
	     * _.takeRight([1, 2, 3], 5);
	     * // => [1, 2, 3]
	     *
	     * _.takeRight([1, 2, 3], 0);
	     * // => []
	     */
	    function takeRight(array, n, guard) {
	      var length = array ? array.length : 0;
	      if (!length) {
	        return [];
	      }
	      n = (guard || n === undefined) ? 1 : toInteger(n);
	      n = length - n;
	      return baseSlice(array, n < 0 ? 0 : n, length);
	    }

	    /**
	     * Creates a slice of `array` with elements taken from the end. Elements are
	     * taken until `predicate` returns falsey. The predicate is invoked with
	     * three arguments: (value, index, array).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'active': true },
	     *   { 'user': 'fred',    'active': false },
	     *   { 'user': 'pebbles', 'active': false }
	     * ];
	     *
	     * _.takeRightWhile(users, function(o) { return !o.active; });
	     * // => objects for ['fred', 'pebbles']
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
	     * // => objects for ['pebbles']
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.takeRightWhile(users, ['active', false]);
	     * // => objects for ['fred', 'pebbles']
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.takeRightWhile(users, 'active');
	     * // => []
	     */
	    function takeRightWhile(array, predicate) {
	      return (array && array.length)
	        ? baseWhile(array, getIteratee(predicate, 3), false, true)
	        : [];
	    }

	    /**
	     * Creates a slice of `array` with elements taken from the beginning. Elements
	     * are taken until `predicate` returns falsey. The predicate is invoked with
	     * three arguments: (value, index, array).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Array
	     * @param {Array} array The array to query.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the slice of `array`.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'active': false },
	     *   { 'user': 'fred',    'active': false},
	     *   { 'user': 'pebbles', 'active': true }
	     * ];
	     *
	     * _.takeWhile(users, function(o) { return !o.active; });
	     * // => objects for ['barney', 'fred']
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.takeWhile(users, { 'user': 'barney', 'active': false });
	     * // => objects for ['barney']
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.takeWhile(users, ['active', false]);
	     * // => objects for ['barney', 'fred']
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.takeWhile(users, 'active');
	     * // => []
	     */
	    function takeWhile(array, predicate) {
	      return (array && array.length)
	        ? baseWhile(array, getIteratee(predicate, 3))
	        : [];
	    }

	    /**
	     * Creates an array of unique values, in order, from all given arrays using
	     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @returns {Array} Returns the new array of combined values.
	     * @example
	     *
	     * _.union([2, 1], [4, 2], [1, 2]);
	     * // => [2, 1, 4]
	     */
	    var union = rest(function(arrays) {
	      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
	    });

	    /**
	     * This method is like `_.union` except that it accepts `iteratee` which is
	     * invoked for each element of each `arrays` to generate the criterion by
	     * which uniqueness is computed. The iteratee is invoked with one argument:
	     * (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {Array} Returns the new array of combined values.
	     * @example
	     *
	     * _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
	     * // => [2.1, 1.2, 4.3]
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
	     * // => [{ 'x': 1 }, { 'x': 2 }]
	     */
	    var unionBy = rest(function(arrays) {
	      var iteratee = last(arrays);
	      if (isArrayLikeObject(iteratee)) {
	        iteratee = undefined;
	      }
	      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee));
	    });

	    /**
	     * This method is like `_.union` except that it accepts `comparator` which
	     * is invoked to compare elements of `arrays`. The comparator is invoked
	     * with two arguments: (arrVal, othVal).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new array of combined values.
	     * @example
	     *
	     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
	     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
	     *
	     * _.unionWith(objects, others, _.isEqual);
	     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
	     */
	    var unionWith = rest(function(arrays) {
	      var comparator = last(arrays);
	      if (isArrayLikeObject(comparator)) {
	        comparator = undefined;
	      }
	      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
	    });

	    /**
	     * Creates a duplicate-free version of an array, using
	     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons, in which only the first occurrence of each
	     * element is kept.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @returns {Array} Returns the new duplicate free array.
	     * @example
	     *
	     * _.uniq([2, 1, 2]);
	     * // => [2, 1]
	     */
	    function uniq(array) {
	      return (array && array.length)
	        ? baseUniq(array)
	        : [];
	    }

	    /**
	     * This method is like `_.uniq` except that it accepts `iteratee` which is
	     * invoked for each element in `array` to generate the criterion by which
	     * uniqueness is computed. The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {Array} Returns the new duplicate free array.
	     * @example
	     *
	     * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
	     * // => [2.1, 1.2]
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
	     * // => [{ 'x': 1 }, { 'x': 2 }]
	     */
	    function uniqBy(array, iteratee) {
	      return (array && array.length)
	        ? baseUniq(array, getIteratee(iteratee))
	        : [];
	    }

	    /**
	     * This method is like `_.uniq` except that it accepts `comparator` which
	     * is invoked to compare elements of `array`. The comparator is invoked with
	     * two arguments: (arrVal, othVal).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {Array} array The array to inspect.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new duplicate free array.
	     * @example
	     *
	     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 },  { 'x': 1, 'y': 2 }];
	     *
	     * _.uniqWith(objects, _.isEqual);
	     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
	     */
	    function uniqWith(array, comparator) {
	      return (array && array.length)
	        ? baseUniq(array, undefined, comparator)
	        : [];
	    }

	    /**
	     * This method is like `_.zip` except that it accepts an array of grouped
	     * elements and creates an array regrouping the elements to their pre-zip
	     * configuration.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.2.0
	     * @category Array
	     * @param {Array} array The array of grouped elements to process.
	     * @returns {Array} Returns the new array of regrouped elements.
	     * @example
	     *
	     * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
	     * // => [['fred', 30, true], ['barney', 40, false]]
	     *
	     * _.unzip(zipped);
	     * // => [['fred', 'barney'], [30, 40], [true, false]]
	     */
	    function unzip(array) {
	      if (!(array && array.length)) {
	        return [];
	      }
	      var length = 0;
	      array = arrayFilter(array, function(group) {
	        if (isArrayLikeObject(group)) {
	          length = nativeMax(group.length, length);
	          return true;
	        }
	      });
	      return baseTimes(length, function(index) {
	        return arrayMap(array, baseProperty(index));
	      });
	    }

	    /**
	     * This method is like `_.unzip` except that it accepts `iteratee` to specify
	     * how regrouped values should be combined. The iteratee is invoked with the
	     * elements of each group: (...group).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.8.0
	     * @category Array
	     * @param {Array} array The array of grouped elements to process.
	     * @param {Function} [iteratee=_.identity] The function to combine
	     *  regrouped values.
	     * @returns {Array} Returns the new array of regrouped elements.
	     * @example
	     *
	     * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
	     * // => [[1, 10, 100], [2, 20, 200]]
	     *
	     * _.unzipWith(zipped, _.add);
	     * // => [3, 30, 300]
	     */
	    function unzipWith(array, iteratee) {
	      if (!(array && array.length)) {
	        return [];
	      }
	      var result = unzip(array);
	      if (iteratee == null) {
	        return result;
	      }
	      return arrayMap(result, function(group) {
	        return apply(iteratee, undefined, group);
	      });
	    }

	    /**
	     * Creates an array excluding all given values using
	     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * for equality comparisons.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {Array} array The array to filter.
	     * @param {...*} [values] The values to exclude.
	     * @returns {Array} Returns the new array of filtered values.
	     * @example
	     *
	     * _.without([1, 2, 1, 3], 1, 2);
	     * // => [3]
	     */
	    var without = rest(function(array, values) {
	      return isArrayLikeObject(array)
	        ? baseDifference(array, values)
	        : [];
	    });

	    /**
	     * Creates an array of unique values that is the
	     * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
	     * of the given arrays. The order of result values is determined by the order
	     * they occur in the arrays.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.4.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @returns {Array} Returns the new array of values.
	     * @example
	     *
	     * _.xor([2, 1], [4, 2]);
	     * // => [1, 4]
	     */
	    var xor = rest(function(arrays) {
	      return baseXor(arrayFilter(arrays, isArrayLikeObject));
	    });

	    /**
	     * This method is like `_.xor` except that it accepts `iteratee` which is
	     * invoked for each element of each `arrays` to generate the criterion by
	     * which by which they're compared. The iteratee is invoked with one argument:
	     * (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {Array} Returns the new array of values.
	     * @example
	     *
	     * _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor);
	     * // => [1.2, 4.3]
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
	     * // => [{ 'x': 2 }]
	     */
	    var xorBy = rest(function(arrays) {
	      var iteratee = last(arrays);
	      if (isArrayLikeObject(iteratee)) {
	        iteratee = undefined;
	      }
	      return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee));
	    });

	    /**
	     * This method is like `_.xor` except that it accepts `comparator` which is
	     * invoked to compare elements of `arrays`. The comparator is invoked with
	     * two arguments: (arrVal, othVal).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to inspect.
	     * @param {Function} [comparator] The comparator invoked per element.
	     * @returns {Array} Returns the new array of values.
	     * @example
	     *
	     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
	     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
	     *
	     * _.xorWith(objects, others, _.isEqual);
	     * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
	     */
	    var xorWith = rest(function(arrays) {
	      var comparator = last(arrays);
	      if (isArrayLikeObject(comparator)) {
	        comparator = undefined;
	      }
	      return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
	    });

	    /**
	     * Creates an array of grouped elements, the first of which contains the
	     * first elements of the given arrays, the second of which contains the
	     * second elements of the given arrays, and so on.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to process.
	     * @returns {Array} Returns the new array of grouped elements.
	     * @example
	     *
	     * _.zip(['fred', 'barney'], [30, 40], [true, false]);
	     * // => [['fred', 30, true], ['barney', 40, false]]
	     */
	    var zip = rest(unzip);

	    /**
	     * This method is like `_.fromPairs` except that it accepts two arrays,
	     * one of property identifiers and one of corresponding values.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.4.0
	     * @category Array
	     * @param {Array} [props=[]] The property identifiers.
	     * @param {Array} [values=[]] The property values.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * _.zipObject(['a', 'b'], [1, 2]);
	     * // => { 'a': 1, 'b': 2 }
	     */
	    function zipObject(props, values) {
	      return baseZipObject(props || [], values || [], assignValue);
	    }

	    /**
	     * This method is like `_.zipObject` except that it supports property paths.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.1.0
	     * @category Array
	     * @param {Array} [props=[]] The property identifiers.
	     * @param {Array} [values=[]] The property values.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
	     * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
	     */
	    function zipObjectDeep(props, values) {
	      return baseZipObject(props || [], values || [], baseSet);
	    }

	    /**
	     * This method is like `_.zip` except that it accepts `iteratee` to specify
	     * how grouped values should be combined. The iteratee is invoked with the
	     * elements of each group: (...group).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.8.0
	     * @category Array
	     * @param {...Array} [arrays] The arrays to process.
	     * @param {Function} [iteratee=_.identity] The function to combine grouped values.
	     * @returns {Array} Returns the new array of grouped elements.
	     * @example
	     *
	     * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
	     *   return a + b + c;
	     * });
	     * // => [111, 222]
	     */
	    var zipWith = rest(function(arrays) {
	      var length = arrays.length,
	          iteratee = length > 1 ? arrays[length - 1] : undefined;

	      iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
	      return unzipWith(arrays, iteratee);
	    });

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates a `lodash` wrapper instance that wraps `value` with explicit method
	     * chain sequences enabled. The result of such sequences must be unwrapped
	     * with `_#value`.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.3.0
	     * @category Seq
	     * @param {*} value The value to wrap.
	     * @returns {Object} Returns the new `lodash` wrapper instance.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'age': 36 },
	     *   { 'user': 'fred',    'age': 40 },
	     *   { 'user': 'pebbles', 'age': 1 }
	     * ];
	     *
	     * var youngest = _
	     *   .chain(users)
	     *   .sortBy('age')
	     *   .map(function(o) {
	     *     return o.user + ' is ' + o.age;
	     *   })
	     *   .head()
	     *   .value();
	     * // => 'pebbles is 1'
	     */
	    function chain(value) {
	      var result = lodash(value);
	      result.__chain__ = true;
	      return result;
	    }

	    /**
	     * This method invokes `interceptor` and returns `value`. The interceptor
	     * is invoked with one argument; (value). The purpose of this method is to
	     * "tap into" a method chain sequence in order to modify intermediate results.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Seq
	     * @param {*} value The value to provide to `interceptor`.
	     * @param {Function} interceptor The function to invoke.
	     * @returns {*} Returns `value`.
	     * @example
	     *
	     * _([1, 2, 3])
	     *  .tap(function(array) {
	     *    // Mutate input array.
	     *    array.pop();
	     *  })
	     *  .reverse()
	     *  .value();
	     * // => [2, 1]
	     */
	    function tap(value, interceptor) {
	      interceptor(value);
	      return value;
	    }

	    /**
	     * This method is like `_.tap` except that it returns the result of `interceptor`.
	     * The purpose of this method is to "pass thru" values replacing intermediate
	     * results in a method chain sequence.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Seq
	     * @param {*} value The value to provide to `interceptor`.
	     * @param {Function} interceptor The function to invoke.
	     * @returns {*} Returns the result of `interceptor`.
	     * @example
	     *
	     * _('  abc  ')
	     *  .chain()
	     *  .trim()
	     *  .thru(function(value) {
	     *    return [value];
	     *  })
	     *  .value();
	     * // => ['abc']
	     */
	    function thru(value, interceptor) {
	      return interceptor(value);
	    }

	    /**
	     * This method is the wrapper version of `_.at`.
	     *
	     * @name at
	     * @memberOf _
	     * @since 1.0.0
	     * @category Seq
	     * @param {...(string|string[])} [paths] The property paths of elements to pick.
	     * @returns {Object} Returns the new `lodash` wrapper instance.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
	     *
	     * _(object).at(['a[0].b.c', 'a[1]']).value();
	     * // => [3, 4]
	     *
	     * _(['a', 'b', 'c']).at(0, 2).value();
	     * // => ['a', 'c']
	     */
	    var wrapperAt = rest(function(paths) {
	      paths = baseFlatten(paths, 1);
	      var length = paths.length,
	          start = length ? paths[0] : 0,
	          value = this.__wrapped__,
	          interceptor = function(object) { return baseAt(object, paths); };

	      if (length > 1 || this.__actions__.length ||
	          !(value instanceof LazyWrapper) || !isIndex(start)) {
	        return this.thru(interceptor);
	      }
	      value = value.slice(start, +start + (length ? 1 : 0));
	      value.__actions__.push({
	        'func': thru,
	        'args': [interceptor],
	        'thisArg': undefined
	      });
	      return new LodashWrapper(value, this.__chain__).thru(function(array) {
	        if (length && !array.length) {
	          array.push(undefined);
	        }
	        return array;
	      });
	    });

	    /**
	     * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
	     *
	     * @name chain
	     * @memberOf _
	     * @since 0.1.0
	     * @category Seq
	     * @returns {Object} Returns the new `lodash` wrapper instance.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney', 'age': 36 },
	     *   { 'user': 'fred',   'age': 40 }
	     * ];
	     *
	     * // A sequence without explicit chaining.
	     * _(users).head();
	     * // => { 'user': 'barney', 'age': 36 }
	     *
	     * // A sequence with explicit chaining.
	     * _(users)
	     *   .chain()
	     *   .head()
	     *   .pick('user')
	     *   .value();
	     * // => { 'user': 'barney' }
	     */
	    function wrapperChain() {
	      return chain(this);
	    }

	    /**
	     * Executes the chain sequence and returns the wrapped result.
	     *
	     * @name commit
	     * @memberOf _
	     * @since 3.2.0
	     * @category Seq
	     * @returns {Object} Returns the new `lodash` wrapper instance.
	     * @example
	     *
	     * var array = [1, 2];
	     * var wrapped = _(array).push(3);
	     *
	     * console.log(array);
	     * // => [1, 2]
	     *
	     * wrapped = wrapped.commit();
	     * console.log(array);
	     * // => [1, 2, 3]
	     *
	     * wrapped.last();
	     * // => 3
	     *
	     * console.log(array);
	     * // => [1, 2, 3]
	     */
	    function wrapperCommit() {
	      return new LodashWrapper(this.value(), this.__chain__);
	    }

	    /**
	     * Gets the next value on a wrapped object following the
	     * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
	     *
	     * @name next
	     * @memberOf _
	     * @since 4.0.0
	     * @category Seq
	     * @returns {Object} Returns the next iterator value.
	     * @example
	     *
	     * var wrapped = _([1, 2]);
	     *
	     * wrapped.next();
	     * // => { 'done': false, 'value': 1 }
	     *
	     * wrapped.next();
	     * // => { 'done': false, 'value': 2 }
	     *
	     * wrapped.next();
	     * // => { 'done': true, 'value': undefined }
	     */
	    function wrapperNext() {
	      if (this.__values__ === undefined) {
	        this.__values__ = toArray(this.value());
	      }
	      var done = this.__index__ >= this.__values__.length,
	          value = done ? undefined : this.__values__[this.__index__++];

	      return { 'done': done, 'value': value };
	    }

	    /**
	     * Enables the wrapper to be iterable.
	     *
	     * @name Symbol.iterator
	     * @memberOf _
	     * @since 4.0.0
	     * @category Seq
	     * @returns {Object} Returns the wrapper object.
	     * @example
	     *
	     * var wrapped = _([1, 2]);
	     *
	     * wrapped[Symbol.iterator]() === wrapped;
	     * // => true
	     *
	     * Array.from(wrapped);
	     * // => [1, 2]
	     */
	    function wrapperToIterator() {
	      return this;
	    }

	    /**
	     * Creates a clone of the chain sequence planting `value` as the wrapped value.
	     *
	     * @name plant
	     * @memberOf _
	     * @since 3.2.0
	     * @category Seq
	     * @param {*} value The value to plant.
	     * @returns {Object} Returns the new `lodash` wrapper instance.
	     * @example
	     *
	     * function square(n) {
	     *   return n * n;
	     * }
	     *
	     * var wrapped = _([1, 2]).map(square);
	     * var other = wrapped.plant([3, 4]);
	     *
	     * other.value();
	     * // => [9, 16]
	     *
	     * wrapped.value();
	     * // => [1, 4]
	     */
	    function wrapperPlant(value) {
	      var result,
	          parent = this;

	      while (parent instanceof baseLodash) {
	        var clone = wrapperClone(parent);
	        clone.__index__ = 0;
	        clone.__values__ = undefined;
	        if (result) {
	          previous.__wrapped__ = clone;
	        } else {
	          result = clone;
	        }
	        var previous = clone;
	        parent = parent.__wrapped__;
	      }
	      previous.__wrapped__ = value;
	      return result;
	    }

	    /**
	     * This method is the wrapper version of `_.reverse`.
	     *
	     * **Note:** This method mutates the wrapped array.
	     *
	     * @name reverse
	     * @memberOf _
	     * @since 0.1.0
	     * @category Seq
	     * @returns {Object} Returns the new `lodash` wrapper instance.
	     * @example
	     *
	     * var array = [1, 2, 3];
	     *
	     * _(array).reverse().value()
	     * // => [3, 2, 1]
	     *
	     * console.log(array);
	     * // => [3, 2, 1]
	     */
	    function wrapperReverse() {
	      var value = this.__wrapped__;
	      if (value instanceof LazyWrapper) {
	        var wrapped = value;
	        if (this.__actions__.length) {
	          wrapped = new LazyWrapper(this);
	        }
	        wrapped = wrapped.reverse();
	        wrapped.__actions__.push({
	          'func': thru,
	          'args': [reverse],
	          'thisArg': undefined
	        });
	        return new LodashWrapper(wrapped, this.__chain__);
	      }
	      return this.thru(reverse);
	    }

	    /**
	     * Executes the chain sequence to resolve the unwrapped value.
	     *
	     * @name value
	     * @memberOf _
	     * @since 0.1.0
	     * @alias toJSON, valueOf
	     * @category Seq
	     * @returns {*} Returns the resolved unwrapped value.
	     * @example
	     *
	     * _([1, 2, 3]).value();
	     * // => [1, 2, 3]
	     */
	    function wrapperValue() {
	      return baseWrapperValue(this.__wrapped__, this.__actions__);
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Creates an object composed of keys generated from the results of running
	     * each element of `collection` thru `iteratee`. The corresponding value of
	     * each key is the number of times the key was returned by `iteratee`. The
	     * iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.5.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee to transform keys.
	     * @returns {Object} Returns the composed aggregate object.
	     * @example
	     *
	     * _.countBy([6.1, 4.2, 6.3], Math.floor);
	     * // => { '4': 1, '6': 2 }
	     *
	     * _.countBy(['one', 'two', 'three'], 'length');
	     * // => { '3': 2, '5': 1 }
	     */
	    var countBy = createAggregator(function(result, value, key) {
	      hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
	    });

	    /**
	     * Checks if `predicate` returns truthy for **all** elements of `collection`.
	     * Iteration is stopped once `predicate` returns falsey. The predicate is
	     * invoked with three arguments: (value, index|key, collection).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {boolean} Returns `true` if all elements pass the predicate check,
	     *  else `false`.
	     * @example
	     *
	     * _.every([true, 1, null, 'yes'], Boolean);
	     * // => false
	     *
	     * var users = [
	     *   { 'user': 'barney', 'age': 36, 'active': false },
	     *   { 'user': 'fred',   'age': 40, 'active': false }
	     * ];
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.every(users, { 'user': 'barney', 'active': false });
	     * // => false
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.every(users, ['active', false]);
	     * // => true
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.every(users, 'active');
	     * // => false
	     */
	    function every(collection, predicate, guard) {
	      var func = isArray(collection) ? arrayEvery : baseEvery;
	      if (guard && isIterateeCall(collection, predicate, guard)) {
	        predicate = undefined;
	      }
	      return func(collection, getIteratee(predicate, 3));
	    }

	    /**
	     * Iterates over elements of `collection`, returning an array of all elements
	     * `predicate` returns truthy for. The predicate is invoked with three
	     * arguments: (value, index|key, collection).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the new filtered array.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney', 'age': 36, 'active': true },
	     *   { 'user': 'fred',   'age': 40, 'active': false }
	     * ];
	     *
	     * _.filter(users, function(o) { return !o.active; });
	     * // => objects for ['fred']
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.filter(users, { 'age': 36, 'active': true });
	     * // => objects for ['barney']
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.filter(users, ['active', false]);
	     * // => objects for ['fred']
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.filter(users, 'active');
	     * // => objects for ['barney']
	     */
	    function filter(collection, predicate) {
	      var func = isArray(collection) ? arrayFilter : baseFilter;
	      return func(collection, getIteratee(predicate, 3));
	    }

	    /**
	     * Iterates over elements of `collection`, returning the first element
	     * `predicate` returns truthy for. The predicate is invoked with three
	     * arguments: (value, index|key, collection).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to search.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {*} Returns the matched element, else `undefined`.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'age': 36, 'active': true },
	     *   { 'user': 'fred',    'age': 40, 'active': false },
	     *   { 'user': 'pebbles', 'age': 1,  'active': true }
	     * ];
	     *
	     * _.find(users, function(o) { return o.age < 40; });
	     * // => object for 'barney'
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.find(users, { 'age': 1, 'active': true });
	     * // => object for 'pebbles'
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.find(users, ['active', false]);
	     * // => object for 'fred'
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.find(users, 'active');
	     * // => object for 'barney'
	     */
	    function find(collection, predicate) {
	      predicate = getIteratee(predicate, 3);
	      if (isArray(collection)) {
	        var index = baseFindIndex(collection, predicate);
	        return index > -1 ? collection[index] : undefined;
	      }
	      return baseFind(collection, predicate, baseEach);
	    }

	    /**
	     * This method is like `_.find` except that it iterates over elements of
	     * `collection` from right to left.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to search.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {*} Returns the matched element, else `undefined`.
	     * @example
	     *
	     * _.findLast([1, 2, 3, 4], function(n) {
	     *   return n % 2 == 1;
	     * });
	     * // => 3
	     */
	    function findLast(collection, predicate) {
	      predicate = getIteratee(predicate, 3);
	      if (isArray(collection)) {
	        var index = baseFindIndex(collection, predicate, true);
	        return index > -1 ? collection[index] : undefined;
	      }
	      return baseFind(collection, predicate, baseEachRight);
	    }

	    /**
	     * Creates a flattened array of values by running each element in `collection`
	     * thru `iteratee` and flattening the mapped results. The iteratee is invoked
	     * with three arguments: (value, index|key, collection).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the new flattened array.
	     * @example
	     *
	     * function duplicate(n) {
	     *   return [n, n];
	     * }
	     *
	     * _.flatMap([1, 2], duplicate);
	     * // => [1, 1, 2, 2]
	     */
	    function flatMap(collection, iteratee) {
	      return baseFlatten(map(collection, iteratee), 1);
	    }

	    /**
	     * This method is like `_.flatMap` except that it recursively flattens the
	     * mapped results.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.7.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the new flattened array.
	     * @example
	     *
	     * function duplicate(n) {
	     *   return [[[n, n]]];
	     * }
	     *
	     * _.flatMapDeep([1, 2], duplicate);
	     * // => [1, 1, 2, 2]
	     */
	    function flatMapDeep(collection, iteratee) {
	      return baseFlatten(map(collection, iteratee), INFINITY);
	    }

	    /**
	     * This method is like `_.flatMap` except that it recursively flattens the
	     * mapped results up to `depth` times.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.7.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The function invoked per iteration.
	     * @param {number} [depth=1] The maximum recursion depth.
	     * @returns {Array} Returns the new flattened array.
	     * @example
	     *
	     * function duplicate(n) {
	     *   return [[[n, n]]];
	     * }
	     *
	     * _.flatMapDepth([1, 2], duplicate, 2);
	     * // => [[1, 1], [2, 2]]
	     */
	    function flatMapDepth(collection, iteratee, depth) {
	      depth = depth === undefined ? 1 : toInteger(depth);
	      return baseFlatten(map(collection, iteratee), depth);
	    }

	    /**
	     * Iterates over elements of `collection` and invokes `iteratee` for each element.
	     * The iteratee is invoked with three arguments: (value, index|key, collection).
	     * Iteratee functions may exit iteration early by explicitly returning `false`.
	     *
	     * **Note:** As with other "Collections" methods, objects with a "length"
	     * property are iterated like arrays. To avoid this behavior use `_.forIn`
	     * or `_.forOwn` for object iteration.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @alias each
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @returns {Array|Object} Returns `collection`.
	     * @example
	     *
	     * _([1, 2]).forEach(function(value) {
	     *   console.log(value);
	     * });
	     * // => Logs `1` then `2`.
	     *
	     * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
	     *   console.log(key);
	     * });
	     * // => Logs 'a' then 'b' (iteration order is not guaranteed).
	     */
	    function forEach(collection, iteratee) {
	      return (typeof iteratee == 'function' && isArray(collection))
	        ? arrayEach(collection, iteratee)
	        : baseEach(collection, getIteratee(iteratee));
	    }

	    /**
	     * This method is like `_.forEach` except that it iterates over elements of
	     * `collection` from right to left.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @alias eachRight
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @returns {Array|Object} Returns `collection`.
	     * @example
	     *
	     * _.forEachRight([1, 2], function(value) {
	     *   console.log(value);
	     * });
	     * // => Logs `2` then `1`.
	     */
	    function forEachRight(collection, iteratee) {
	      return (typeof iteratee == 'function' && isArray(collection))
	        ? arrayEachRight(collection, iteratee)
	        : baseEachRight(collection, getIteratee(iteratee));
	    }

	    /**
	     * Creates an object composed of keys generated from the results of running
	     * each element of `collection` thru `iteratee`. The order of grouped values
	     * is determined by the order they occur in `collection`. The corresponding
	     * value of each key is an array of elements responsible for generating the
	     * key. The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee to transform keys.
	     * @returns {Object} Returns the composed aggregate object.
	     * @example
	     *
	     * _.groupBy([6.1, 4.2, 6.3], Math.floor);
	     * // => { '4': [4.2], '6': [6.1, 6.3] }
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.groupBy(['one', 'two', 'three'], 'length');
	     * // => { '3': ['one', 'two'], '5': ['three'] }
	     */
	    var groupBy = createAggregator(function(result, value, key) {
	      if (hasOwnProperty.call(result, key)) {
	        result[key].push(value);
	      } else {
	        result[key] = [value];
	      }
	    });

	    /**
	     * Checks if `value` is in `collection`. If `collection` is a string, it's
	     * checked for a substring of `value`, otherwise
	     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * is used for equality comparisons. If `fromIndex` is negative, it's used as
	     * the offset from the end of `collection`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object|string} collection The collection to search.
	     * @param {*} value The value to search for.
	     * @param {number} [fromIndex=0] The index to search from.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
	     * @returns {boolean} Returns `true` if `value` is found, else `false`.
	     * @example
	     *
	     * _.includes([1, 2, 3], 1);
	     * // => true
	     *
	     * _.includes([1, 2, 3], 1, 2);
	     * // => false
	     *
	     * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
	     * // => true
	     *
	     * _.includes('pebbles', 'eb');
	     * // => true
	     */
	    function includes(collection, value, fromIndex, guard) {
	      collection = isArrayLike(collection) ? collection : values(collection);
	      fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;

	      var length = collection.length;
	      if (fromIndex < 0) {
	        fromIndex = nativeMax(length + fromIndex, 0);
	      }
	      return isString(collection)
	        ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
	        : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
	    }

	    /**
	     * Invokes the method at `path` of each element in `collection`, returning
	     * an array of the results of each invoked method. Any additional arguments
	     * are provided to each invoked method. If `methodName` is a function, it's
	     * invoked for and `this` bound to, each element in `collection`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|string} path The path of the method to invoke or
	     *  the function invoked per iteration.
	     * @param {...*} [args] The arguments to invoke each method with.
	     * @returns {Array} Returns the array of results.
	     * @example
	     *
	     * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
	     * // => [[1, 5, 7], [1, 2, 3]]
	     *
	     * _.invokeMap([123, 456], String.prototype.split, '');
	     * // => [['1', '2', '3'], ['4', '5', '6']]
	     */
	    var invokeMap = rest(function(collection, path, args) {
	      var index = -1,
	          isFunc = typeof path == 'function',
	          isProp = isKey(path),
	          result = isArrayLike(collection) ? Array(collection.length) : [];

	      baseEach(collection, function(value) {
	        var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);
	        result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args);
	      });
	      return result;
	    });

	    /**
	     * Creates an object composed of keys generated from the results of running
	     * each element of `collection` thru `iteratee`. The corresponding value of
	     * each key is the last element responsible for generating the key. The
	     * iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee to transform keys.
	     * @returns {Object} Returns the composed aggregate object.
	     * @example
	     *
	     * var array = [
	     *   { 'dir': 'left', 'code': 97 },
	     *   { 'dir': 'right', 'code': 100 }
	     * ];
	     *
	     * _.keyBy(array, function(o) {
	     *   return String.fromCharCode(o.code);
	     * });
	     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
	     *
	     * _.keyBy(array, 'dir');
	     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
	     */
	    var keyBy = createAggregator(function(result, value, key) {
	      result[key] = value;
	    });

	    /**
	     * Creates an array of values by running each element in `collection` thru
	     * `iteratee`. The iteratee is invoked with three arguments:
	     * (value, index|key, collection).
	     *
	     * Many lodash methods are guarded to work as iteratees for methods like
	     * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
	     *
	     * The guarded methods are:
	     * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
	     * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
	     * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
	     * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the new mapped array.
	     * @example
	     *
	     * function square(n) {
	     *   return n * n;
	     * }
	     *
	     * _.map([4, 8], square);
	     * // => [16, 64]
	     *
	     * _.map({ 'a': 4, 'b': 8 }, square);
	     * // => [16, 64] (iteration order is not guaranteed)
	     *
	     * var users = [
	     *   { 'user': 'barney' },
	     *   { 'user': 'fred' }
	     * ];
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.map(users, 'user');
	     * // => ['barney', 'fred']
	     */
	    function map(collection, iteratee) {
	      var func = isArray(collection) ? arrayMap : baseMap;
	      return func(collection, getIteratee(iteratee, 3));
	    }

	    /**
	     * This method is like `_.sortBy` except that it allows specifying the sort
	     * orders of the iteratees to sort by. If `orders` is unspecified, all values
	     * are sorted in ascending order. Otherwise, specify an order of "desc" for
	     * descending or "asc" for ascending sort order of corresponding values.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
	     *  The iteratees to sort by.
	     * @param {string[]} [orders] The sort orders of `iteratees`.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
	     * @returns {Array} Returns the new sorted array.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'fred',   'age': 48 },
	     *   { 'user': 'barney', 'age': 34 },
	     *   { 'user': 'fred',   'age': 40 },
	     *   { 'user': 'barney', 'age': 36 }
	     * ];
	     *
	     * // Sort by `user` in ascending order and by `age` in descending order.
	     * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
	     * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
	     */
	    function orderBy(collection, iteratees, orders, guard) {
	      if (collection == null) {
	        return [];
	      }
	      if (!isArray(iteratees)) {
	        iteratees = iteratees == null ? [] : [iteratees];
	      }
	      orders = guard ? undefined : orders;
	      if (!isArray(orders)) {
	        orders = orders == null ? [] : [orders];
	      }
	      return baseOrderBy(collection, iteratees, orders);
	    }

	    /**
	     * Creates an array of elements split into two groups, the first of which
	     * contains elements `predicate` returns truthy for, the second of which
	     * contains elements `predicate` returns falsey for. The predicate is
	     * invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the array of grouped elements.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney',  'age': 36, 'active': false },
	     *   { 'user': 'fred',    'age': 40, 'active': true },
	     *   { 'user': 'pebbles', 'age': 1,  'active': false }
	     * ];
	     *
	     * _.partition(users, function(o) { return o.active; });
	     * // => objects for [['fred'], ['barney', 'pebbles']]
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.partition(users, { 'age': 1, 'active': false });
	     * // => objects for [['pebbles'], ['barney', 'fred']]
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.partition(users, ['active', false]);
	     * // => objects for [['barney', 'pebbles'], ['fred']]
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.partition(users, 'active');
	     * // => objects for [['fred'], ['barney', 'pebbles']]
	     */
	    var partition = createAggregator(function(result, value, key) {
	      result[key ? 0 : 1].push(value);
	    }, function() { return [[], []]; });

	    /**
	     * Reduces `collection` to a value which is the accumulated result of running
	     * each element in `collection` thru `iteratee`, where each successive
	     * invocation is supplied the return value of the previous. If `accumulator`
	     * is not given, the first element of `collection` is used as the initial
	     * value. The iteratee is invoked with four arguments:
	     * (accumulator, value, index|key, collection).
	     *
	     * Many lodash methods are guarded to work as iteratees for methods like
	     * `_.reduce`, `_.reduceRight`, and `_.transform`.
	     *
	     * The guarded methods are:
	     * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
	     * and `sortBy`
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @param {*} [accumulator] The initial value.
	     * @returns {*} Returns the accumulated value.
	     * @example
	     *
	     * _.reduce([1, 2], function(sum, n) {
	     *   return sum + n;
	     * }, 0);
	     * // => 3
	     *
	     * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
	     *   (result[value] || (result[value] = [])).push(key);
	     *   return result;
	     * }, {});
	     * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
	     */
	    function reduce(collection, iteratee, accumulator) {
	      var func = isArray(collection) ? arrayReduce : baseReduce,
	          initAccum = arguments.length < 3;

	      return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
	    }

	    /**
	     * This method is like `_.reduce` except that it iterates over elements of
	     * `collection` from right to left.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @param {*} [accumulator] The initial value.
	     * @returns {*} Returns the accumulated value.
	     * @example
	     *
	     * var array = [[0, 1], [2, 3], [4, 5]];
	     *
	     * _.reduceRight(array, function(flattened, other) {
	     *   return flattened.concat(other);
	     * }, []);
	     * // => [4, 5, 2, 3, 0, 1]
	     */
	    function reduceRight(collection, iteratee, accumulator) {
	      var func = isArray(collection) ? arrayReduceRight : baseReduce,
	          initAccum = arguments.length < 3;

	      return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
	    }

	    /**
	     * The opposite of `_.filter`; this method returns the elements of `collection`
	     * that `predicate` does **not** return truthy for.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Array} Returns the new filtered array.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney', 'age': 36, 'active': false },
	     *   { 'user': 'fred',   'age': 40, 'active': true }
	     * ];
	     *
	     * _.reject(users, function(o) { return !o.active; });
	     * // => objects for ['fred']
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.reject(users, { 'age': 40, 'active': true });
	     * // => objects for ['barney']
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.reject(users, ['active', false]);
	     * // => objects for ['fred']
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.reject(users, 'active');
	     * // => objects for ['barney']
	     */
	    function reject(collection, predicate) {
	      var func = isArray(collection) ? arrayFilter : baseFilter;
	      predicate = getIteratee(predicate, 3);
	      return func(collection, function(value, index, collection) {
	        return !predicate(value, index, collection);
	      });
	    }

	    /**
	     * Gets a random element from `collection`.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to sample.
	     * @returns {*} Returns the random element.
	     * @example
	     *
	     * _.sample([1, 2, 3, 4]);
	     * // => 2
	     */
	    function sample(collection) {
	      var array = isArrayLike(collection) ? collection : values(collection),
	          length = array.length;

	      return length > 0 ? array[baseRandom(0, length - 1)] : undefined;
	    }

	    /**
	     * Gets `n` random elements at unique keys from `collection` up to the
	     * size of `collection`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to sample.
	     * @param {number} [n=1] The number of elements to sample.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Array} Returns the random elements.
	     * @example
	     *
	     * _.sampleSize([1, 2, 3], 2);
	     * // => [3, 1]
	     *
	     * _.sampleSize([1, 2, 3], 4);
	     * // => [2, 3, 1]
	     */
	    function sampleSize(collection, n, guard) {
	      var index = -1,
	          result = toArray(collection),
	          length = result.length,
	          lastIndex = length - 1;

	      if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
	        n = 1;
	      } else {
	        n = baseClamp(toInteger(n), 0, length);
	      }
	      while (++index < n) {
	        var rand = baseRandom(index, lastIndex),
	            value = result[rand];

	        result[rand] = result[index];
	        result[index] = value;
	      }
	      result.length = n;
	      return result;
	    }

	    /**
	     * Creates an array of shuffled values, using a version of the
	     * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to shuffle.
	     * @returns {Array} Returns the new shuffled array.
	     * @example
	     *
	     * _.shuffle([1, 2, 3, 4]);
	     * // => [4, 1, 3, 2]
	     */
	    function shuffle(collection) {
	      return sampleSize(collection, MAX_ARRAY_LENGTH);
	    }

	    /**
	     * Gets the size of `collection` by returning its length for array-like
	     * values or the number of own enumerable string keyed properties for objects.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to inspect.
	     * @returns {number} Returns the collection size.
	     * @example
	     *
	     * _.size([1, 2, 3]);
	     * // => 3
	     *
	     * _.size({ 'a': 1, 'b': 2 });
	     * // => 2
	     *
	     * _.size('pebbles');
	     * // => 7
	     */
	    function size(collection) {
	      if (collection == null) {
	        return 0;
	      }
	      if (isArrayLike(collection)) {
	        var result = collection.length;
	        return (result && isString(collection)) ? stringSize(collection) : result;
	      }
	      if (isObjectLike(collection)) {
	        var tag = getTag(collection);
	        if (tag == mapTag || tag == setTag) {
	          return collection.size;
	        }
	      }
	      return keys(collection).length;
	    }

	    /**
	     * Checks if `predicate` returns truthy for **any** element of `collection`.
	     * Iteration is stopped once `predicate` returns truthy. The predicate is
	     * invoked with three arguments: (value, index|key, collection).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {boolean} Returns `true` if any element passes the predicate check,
	     *  else `false`.
	     * @example
	     *
	     * _.some([null, 0, 'yes', false], Boolean);
	     * // => true
	     *
	     * var users = [
	     *   { 'user': 'barney', 'active': true },
	     *   { 'user': 'fred',   'active': false }
	     * ];
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.some(users, { 'user': 'barney', 'active': false });
	     * // => false
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.some(users, ['active', false]);
	     * // => true
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.some(users, 'active');
	     * // => true
	     */
	    function some(collection, predicate, guard) {
	      var func = isArray(collection) ? arraySome : baseSome;
	      if (guard && isIterateeCall(collection, predicate, guard)) {
	        predicate = undefined;
	      }
	      return func(collection, getIteratee(predicate, 3));
	    }

	    /**
	     * Creates an array of elements, sorted in ascending order by the results of
	     * running each element in a collection thru each iteratee. This method
	     * performs a stable sort, that is, it preserves the original sort order of
	     * equal elements. The iteratees are invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Collection
	     * @param {Array|Object} collection The collection to iterate over.
	     * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])}
	     *  [iteratees=[_.identity]] The iteratees to sort by.
	     * @returns {Array} Returns the new sorted array.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'fred',   'age': 48 },
	     *   { 'user': 'barney', 'age': 36 },
	     *   { 'user': 'fred',   'age': 40 },
	     *   { 'user': 'barney', 'age': 34 }
	     * ];
	     *
	     * _.sortBy(users, function(o) { return o.user; });
	     * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
	     *
	     * _.sortBy(users, ['user', 'age']);
	     * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
	     *
	     * _.sortBy(users, 'user', function(o) {
	     *   return Math.floor(o.age / 10);
	     * });
	     * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
	     */
	    var sortBy = rest(function(collection, iteratees) {
	      if (collection == null) {
	        return [];
	      }
	      var length = iteratees.length;
	      if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
	        iteratees = [];
	      } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
	        iteratees = [iteratees[0]];
	      }
	      iteratees = (iteratees.length == 1 && isArray(iteratees[0]))
	        ? iteratees[0]
	        : baseFlatten(iteratees, 1, isFlattenableIteratee);

	      return baseOrderBy(collection, iteratees, []);
	    });

	    /*------------------------------------------------------------------------*/

	    /**
	     * Gets the timestamp of the number of milliseconds that have elapsed since
	     * the Unix epoch (1 January 1970 00:00:00 UTC).
	     *
	     * @static
	     * @memberOf _
	     * @since 2.4.0
	     * @type {Function}
	     * @category Date
	     * @returns {number} Returns the timestamp.
	     * @example
	     *
	     * _.defer(function(stamp) {
	     *   console.log(_.now() - stamp);
	     * }, _.now());
	     * // => Logs the number of milliseconds it took for the deferred function to be invoked.
	     */
	    var now = Date.now;

	    /*------------------------------------------------------------------------*/

	    /**
	     * The opposite of `_.before`; this method creates a function that invokes
	     * `func` once it's called `n` or more times.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {number} n The number of calls before `func` is invoked.
	     * @param {Function} func The function to restrict.
	     * @returns {Function} Returns the new restricted function.
	     * @example
	     *
	     * var saves = ['profile', 'settings'];
	     *
	     * var done = _.after(saves.length, function() {
	     *   console.log('done saving!');
	     * });
	     *
	     * _.forEach(saves, function(type) {
	     *   asyncSave({ 'type': type, 'complete': done });
	     * });
	     * // => Logs 'done saving!' after the two async saves have completed.
	     */
	    function after(n, func) {
	      if (typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      n = toInteger(n);
	      return function() {
	        if (--n < 1) {
	          return func.apply(this, arguments);
	        }
	      };
	    }

	    /**
	     * Creates a function that invokes `func`, with up to `n` arguments,
	     * ignoring any additional arguments.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Function
	     * @param {Function} func The function to cap arguments for.
	     * @param {number} [n=func.length] The arity cap.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * _.map(['6', '8', '10'], _.ary(parseInt, 1));
	     * // => [6, 8, 10]
	     */
	    function ary(func, n, guard) {
	      n = guard ? undefined : n;
	      n = (func && n == null) ? func.length : n;
	      return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n);
	    }

	    /**
	     * Creates a function that invokes `func`, with the `this` binding and arguments
	     * of the created function, while it's called less than `n` times. Subsequent
	     * calls to the created function return the result of the last `func` invocation.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Function
	     * @param {number} n The number of calls at which `func` is no longer invoked.
	     * @param {Function} func The function to restrict.
	     * @returns {Function} Returns the new restricted function.
	     * @example
	     *
	     * jQuery(element).on('click', _.before(5, addContactToList));
	     * // => allows adding up to 4 contacts to the list
	     */
	    function before(n, func) {
	      var result;
	      if (typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      n = toInteger(n);
	      return function() {
	        if (--n > 0) {
	          result = func.apply(this, arguments);
	        }
	        if (n <= 1) {
	          func = undefined;
	        }
	        return result;
	      };
	    }

	    /**
	     * Creates a function that invokes `func` with the `this` binding of `thisArg`
	     * and `partials` prepended to the arguments it receives.
	     *
	     * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
	     * may be used as a placeholder for partially applied arguments.
	     *
	     * **Note:** Unlike native `Function#bind` this method doesn't set the "length"
	     * property of bound functions.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {Function} func The function to bind.
	     * @param {*} thisArg The `this` binding of `func`.
	     * @param {...*} [partials] The arguments to be partially applied.
	     * @returns {Function} Returns the new bound function.
	     * @example
	     *
	     * var greet = function(greeting, punctuation) {
	     *   return greeting + ' ' + this.user + punctuation;
	     * };
	     *
	     * var object = { 'user': 'fred' };
	     *
	     * var bound = _.bind(greet, object, 'hi');
	     * bound('!');
	     * // => 'hi fred!'
	     *
	     * // Bound with placeholders.
	     * var bound = _.bind(greet, object, _, '!');
	     * bound('hi');
	     * // => 'hi fred!'
	     */
	    var bind = rest(function(func, thisArg, partials) {
	      var bitmask = BIND_FLAG;
	      if (partials.length) {
	        var holders = replaceHolders(partials, getPlaceholder(bind));
	        bitmask |= PARTIAL_FLAG;
	      }
	      return createWrapper(func, bitmask, thisArg, partials, holders);
	    });

	    /**
	     * Creates a function that invokes the method at `object[key]` with `partials`
	     * prepended to the arguments it receives.
	     *
	     * This method differs from `_.bind` by allowing bound functions to reference
	     * methods that may be redefined or don't yet exist. See
	     * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
	     * for more details.
	     *
	     * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
	     * builds, may be used as a placeholder for partially applied arguments.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.10.0
	     * @category Function
	     * @param {Object} object The object to invoke the method on.
	     * @param {string} key The key of the method.
	     * @param {...*} [partials] The arguments to be partially applied.
	     * @returns {Function} Returns the new bound function.
	     * @example
	     *
	     * var object = {
	     *   'user': 'fred',
	     *   'greet': function(greeting, punctuation) {
	     *     return greeting + ' ' + this.user + punctuation;
	     *   }
	     * };
	     *
	     * var bound = _.bindKey(object, 'greet', 'hi');
	     * bound('!');
	     * // => 'hi fred!'
	     *
	     * object.greet = function(greeting, punctuation) {
	     *   return greeting + 'ya ' + this.user + punctuation;
	     * };
	     *
	     * bound('!');
	     * // => 'hiya fred!'
	     *
	     * // Bound with placeholders.
	     * var bound = _.bindKey(object, 'greet', _, '!');
	     * bound('hi');
	     * // => 'hiya fred!'
	     */
	    var bindKey = rest(function(object, key, partials) {
	      var bitmask = BIND_FLAG | BIND_KEY_FLAG;
	      if (partials.length) {
	        var holders = replaceHolders(partials, getPlaceholder(bindKey));
	        bitmask |= PARTIAL_FLAG;
	      }
	      return createWrapper(key, bitmask, object, partials, holders);
	    });

	    /**
	     * Creates a function that accepts arguments of `func` and either invokes
	     * `func` returning its result, if at least `arity` number of arguments have
	     * been provided, or returns a function that accepts the remaining `func`
	     * arguments, and so on. The arity of `func` may be specified if `func.length`
	     * is not sufficient.
	     *
	     * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
	     * may be used as a placeholder for provided arguments.
	     *
	     * **Note:** This method doesn't set the "length" property of curried functions.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Function
	     * @param {Function} func The function to curry.
	     * @param {number} [arity=func.length] The arity of `func`.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Function} Returns the new curried function.
	     * @example
	     *
	     * var abc = function(a, b, c) {
	     *   return [a, b, c];
	     * };
	     *
	     * var curried = _.curry(abc);
	     *
	     * curried(1)(2)(3);
	     * // => [1, 2, 3]
	     *
	     * curried(1, 2)(3);
	     * // => [1, 2, 3]
	     *
	     * curried(1, 2, 3);
	     * // => [1, 2, 3]
	     *
	     * // Curried with placeholders.
	     * curried(1)(_, 3)(2);
	     * // => [1, 2, 3]
	     */
	    function curry(func, arity, guard) {
	      arity = guard ? undefined : arity;
	      var result = createWrapper(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
	      result.placeholder = curry.placeholder;
	      return result;
	    }

	    /**
	     * This method is like `_.curry` except that arguments are applied to `func`
	     * in the manner of `_.partialRight` instead of `_.partial`.
	     *
	     * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
	     * builds, may be used as a placeholder for provided arguments.
	     *
	     * **Note:** This method doesn't set the "length" property of curried functions.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Function
	     * @param {Function} func The function to curry.
	     * @param {number} [arity=func.length] The arity of `func`.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Function} Returns the new curried function.
	     * @example
	     *
	     * var abc = function(a, b, c) {
	     *   return [a, b, c];
	     * };
	     *
	     * var curried = _.curryRight(abc);
	     *
	     * curried(3)(2)(1);
	     * // => [1, 2, 3]
	     *
	     * curried(2, 3)(1);
	     * // => [1, 2, 3]
	     *
	     * curried(1, 2, 3);
	     * // => [1, 2, 3]
	     *
	     * // Curried with placeholders.
	     * curried(3)(1, _)(2);
	     * // => [1, 2, 3]
	     */
	    function curryRight(func, arity, guard) {
	      arity = guard ? undefined : arity;
	      var result = createWrapper(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
	      result.placeholder = curryRight.placeholder;
	      return result;
	    }

	    /**
	     * Creates a debounced function that delays invoking `func` until after `wait`
	     * milliseconds have elapsed since the last time the debounced function was
	     * invoked. The debounced function comes with a `cancel` method to cancel
	     * delayed `func` invocations and a `flush` method to immediately invoke them.
	     * Provide an options object to indicate whether `func` should be invoked on
	     * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked
	     * with the last arguments provided to the debounced function. Subsequent calls
	     * to the debounced function return the result of the last `func` invocation.
	     *
	     * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
	     * on the trailing edge of the timeout only if the debounced function is
	     * invoked more than once during the `wait` timeout.
	     *
	     * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
	     * for details over the differences between `_.debounce` and `_.throttle`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {Function} func The function to debounce.
	     * @param {number} [wait=0] The number of milliseconds to delay.
	     * @param {Object} [options={}] The options object.
	     * @param {boolean} [options.leading=false]
	     *  Specify invoking on the leading edge of the timeout.
	     * @param {number} [options.maxWait]
	     *  The maximum time `func` is allowed to be delayed before it's invoked.
	     * @param {boolean} [options.trailing=true]
	     *  Specify invoking on the trailing edge of the timeout.
	     * @returns {Function} Returns the new debounced function.
	     * @example
	     *
	     * // Avoid costly calculations while the window size is in flux.
	     * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
	     *
	     * // Invoke `sendMail` when clicked, debouncing subsequent calls.
	     * jQuery(element).on('click', _.debounce(sendMail, 300, {
	     *   'leading': true,
	     *   'trailing': false
	     * }));
	     *
	     * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
	     * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
	     * var source = new EventSource('/stream');
	     * jQuery(source).on('message', debounced);
	     *
	     * // Cancel the trailing debounced invocation.
	     * jQuery(window).on('popstate', debounced.cancel);
	     */
	    function debounce(func, wait, options) {
	      var lastArgs,
	          lastThis,
	          maxWait,
	          result,
	          timerId,
	          lastCallTime = 0,
	          lastInvokeTime = 0,
	          leading = false,
	          maxing = false,
	          trailing = true;

	      if (typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      wait = toNumber(wait) || 0;
	      if (isObject(options)) {
	        leading = !!options.leading;
	        maxing = 'maxWait' in options;
	        maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
	        trailing = 'trailing' in options ? !!options.trailing : trailing;
	      }

	      function invokeFunc(time) {
	        var args = lastArgs,
	            thisArg = lastThis;

	        lastArgs = lastThis = undefined;
	        lastInvokeTime = time;
	        result = func.apply(thisArg, args);
	        return result;
	      }

	      function leadingEdge(time) {
	        // Reset any `maxWait` timer.
	        lastInvokeTime = time;
	        // Start the timer for the trailing edge.
	        timerId = setTimeout(timerExpired, wait);
	        // Invoke the leading edge.
	        return leading ? invokeFunc(time) : result;
	      }

	      function remainingWait(time) {
	        var timeSinceLastCall = time - lastCallTime,
	            timeSinceLastInvoke = time - lastInvokeTime,
	            result = wait - timeSinceLastCall;

	        return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
	      }

	      function shouldInvoke(time) {
	        var timeSinceLastCall = time - lastCallTime,
	            timeSinceLastInvoke = time - lastInvokeTime;

	        // Either this is the first call, activity has stopped and we're at the
	        // trailing edge, the system time has gone backwards and we're treating
	        // it as the trailing edge, or we've hit the `maxWait` limit.
	        return (!lastCallTime || (timeSinceLastCall >= wait) ||
	          (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
	      }

	      function timerExpired() {
	        var time = now();
	        if (shouldInvoke(time)) {
	          return trailingEdge(time);
	        }
	        // Restart the timer.
	        timerId = setTimeout(timerExpired, remainingWait(time));
	      }

	      function trailingEdge(time) {
	        clearTimeout(timerId);
	        timerId = undefined;

	        // Only invoke if we have `lastArgs` which means `func` has been
	        // debounced at least once.
	        if (trailing && lastArgs) {
	          return invokeFunc(time);
	        }
	        lastArgs = lastThis = undefined;
	        return result;
	      }

	      function cancel() {
	        if (timerId !== undefined) {
	          clearTimeout(timerId);
	        }
	        lastCallTime = lastInvokeTime = 0;
	        lastArgs = lastThis = timerId = undefined;
	      }

	      function flush() {
	        return timerId === undefined ? result : trailingEdge(now());
	      }

	      function debounced() {
	        var time = now(),
	            isInvoking = shouldInvoke(time);

	        lastArgs = arguments;
	        lastThis = this;
	        lastCallTime = time;

	        if (isInvoking) {
	          if (timerId === undefined) {
	            return leadingEdge(lastCallTime);
	          }
	          if (maxing) {
	            // Handle invocations in a tight loop.
	            clearTimeout(timerId);
	            timerId = setTimeout(timerExpired, wait);
	            return invokeFunc(lastCallTime);
	          }
	        }
	        if (timerId === undefined) {
	          timerId = setTimeout(timerExpired, wait);
	        }
	        return result;
	      }
	      debounced.cancel = cancel;
	      debounced.flush = flush;
	      return debounced;
	    }

	    /**
	     * Defers invoking the `func` until the current call stack has cleared. Any
	     * additional arguments are provided to `func` when it's invoked.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {Function} func The function to defer.
	     * @param {...*} [args] The arguments to invoke `func` with.
	     * @returns {number} Returns the timer id.
	     * @example
	     *
	     * _.defer(function(text) {
	     *   console.log(text);
	     * }, 'deferred');
	     * // => Logs 'deferred' after one or more milliseconds.
	     */
	    var defer = rest(function(func, args) {
	      return baseDelay(func, 1, args);
	    });

	    /**
	     * Invokes `func` after `wait` milliseconds. Any additional arguments are
	     * provided to `func` when it's invoked.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {Function} func The function to delay.
	     * @param {number} wait The number of milliseconds to delay invocation.
	     * @param {...*} [args] The arguments to invoke `func` with.
	     * @returns {number} Returns the timer id.
	     * @example
	     *
	     * _.delay(function(text) {
	     *   console.log(text);
	     * }, 1000, 'later');
	     * // => Logs 'later' after one second.
	     */
	    var delay = rest(function(func, wait, args) {
	      return baseDelay(func, toNumber(wait) || 0, args);
	    });

	    /**
	     * Creates a function that invokes `func` with arguments reversed.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Function
	     * @param {Function} func The function to flip arguments for.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var flipped = _.flip(function() {
	     *   return _.toArray(arguments);
	     * });
	     *
	     * flipped('a', 'b', 'c', 'd');
	     * // => ['d', 'c', 'b', 'a']
	     */
	    function flip(func) {
	      return createWrapper(func, FLIP_FLAG);
	    }

	    /**
	     * Creates a function that memoizes the result of `func`. If `resolver` is
	     * provided, it determines the cache key for storing the result based on the
	     * arguments provided to the memoized function. By default, the first argument
	     * provided to the memoized function is used as the map cache key. The `func`
	     * is invoked with the `this` binding of the memoized function.
	     *
	     * **Note:** The cache is exposed as the `cache` property on the memoized
	     * function. Its creation may be customized by replacing the `_.memoize.Cache`
	     * constructor with one whose instances implement the
	     * [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object)
	     * method interface of `delete`, `get`, `has`, and `set`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {Function} func The function to have its output memoized.
	     * @param {Function} [resolver] The function to resolve the cache key.
	     * @returns {Function} Returns the new memoizing function.
	     * @example
	     *
	     * var object = { 'a': 1, 'b': 2 };
	     * var other = { 'c': 3, 'd': 4 };
	     *
	     * var values = _.memoize(_.values);
	     * values(object);
	     * // => [1, 2]
	     *
	     * values(other);
	     * // => [3, 4]
	     *
	     * object.a = 2;
	     * values(object);
	     * // => [1, 2]
	     *
	     * // Modify the result cache.
	     * values.cache.set(object, ['a', 'b']);
	     * values(object);
	     * // => ['a', 'b']
	     *
	     * // Replace `_.memoize.Cache`.
	     * _.memoize.Cache = WeakMap;
	     */
	    function memoize(func, resolver) {
	      if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      var memoized = function() {
	        var args = arguments,
	            key = resolver ? resolver.apply(this, args) : args[0],
	            cache = memoized.cache;

	        if (cache.has(key)) {
	          return cache.get(key);
	        }
	        var result = func.apply(this, args);
	        memoized.cache = cache.set(key, result);
	        return result;
	      };
	      memoized.cache = new (memoize.Cache || MapCache);
	      return memoized;
	    }

	    // Assign cache to `_.memoize`.
	    memoize.Cache = MapCache;

	    /**
	     * Creates a function that negates the result of the predicate `func`. The
	     * `func` predicate is invoked with the `this` binding and arguments of the
	     * created function.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Function
	     * @param {Function} predicate The predicate to negate.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * function isEven(n) {
	     *   return n % 2 == 0;
	     * }
	     *
	     * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
	     * // => [1, 3, 5]
	     */
	    function negate(predicate) {
	      if (typeof predicate != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      return function() {
	        return !predicate.apply(this, arguments);
	      };
	    }

	    /**
	     * Creates a function that is restricted to invoking `func` once. Repeat calls
	     * to the function return the value of the first invocation. The `func` is
	     * invoked with the `this` binding and arguments of the created function.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {Function} func The function to restrict.
	     * @returns {Function} Returns the new restricted function.
	     * @example
	     *
	     * var initialize = _.once(createApplication);
	     * initialize();
	     * initialize();
	     * // `initialize` invokes `createApplication` once
	     */
	    function once(func) {
	      return before(2, func);
	    }

	    /**
	     * Creates a function that invokes `func` with arguments transformed by
	     * corresponding `transforms`.
	     *
	     * @static
	     * @since 4.0.0
	     * @memberOf _
	     * @category Function
	     * @param {Function} func The function to wrap.
	     * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])}
	     *  [transforms[_.identity]] The functions to transform.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * function doubled(n) {
	     *   return n * 2;
	     * }
	     *
	     * function square(n) {
	     *   return n * n;
	     * }
	     *
	     * var func = _.overArgs(function(x, y) {
	     *   return [x, y];
	     * }, square, doubled);
	     *
	     * func(9, 3);
	     * // => [81, 6]
	     *
	     * func(10, 5);
	     * // => [100, 10]
	     */
	    var overArgs = rest(function(func, transforms) {
	      transforms = (transforms.length == 1 && isArray(transforms[0]))
	        ? arrayMap(transforms[0], baseUnary(getIteratee()))
	        : arrayMap(baseFlatten(transforms, 1, isFlattenableIteratee), baseUnary(getIteratee()));

	      var funcsLength = transforms.length;
	      return rest(function(args) {
	        var index = -1,
	            length = nativeMin(args.length, funcsLength);

	        while (++index < length) {
	          args[index] = transforms[index].call(this, args[index]);
	        }
	        return apply(func, this, args);
	      });
	    });

	    /**
	     * Creates a function that invokes `func` with `partials` prepended to the
	     * arguments it receives. This method is like `_.bind` except it does **not**
	     * alter the `this` binding.
	     *
	     * The `_.partial.placeholder` value, which defaults to `_` in monolithic
	     * builds, may be used as a placeholder for partially applied arguments.
	     *
	     * **Note:** This method doesn't set the "length" property of partially
	     * applied functions.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.2.0
	     * @category Function
	     * @param {Function} func The function to partially apply arguments to.
	     * @param {...*} [partials] The arguments to be partially applied.
	     * @returns {Function} Returns the new partially applied function.
	     * @example
	     *
	     * var greet = function(greeting, name) {
	     *   return greeting + ' ' + name;
	     * };
	     *
	     * var sayHelloTo = _.partial(greet, 'hello');
	     * sayHelloTo('fred');
	     * // => 'hello fred'
	     *
	     * // Partially applied with placeholders.
	     * var greetFred = _.partial(greet, _, 'fred');
	     * greetFred('hi');
	     * // => 'hi fred'
	     */
	    var partial = rest(function(func, partials) {
	      var holders = replaceHolders(partials, getPlaceholder(partial));
	      return createWrapper(func, PARTIAL_FLAG, undefined, partials, holders);
	    });

	    /**
	     * This method is like `_.partial` except that partially applied arguments
	     * are appended to the arguments it receives.
	     *
	     * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
	     * builds, may be used as a placeholder for partially applied arguments.
	     *
	     * **Note:** This method doesn't set the "length" property of partially
	     * applied functions.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.0.0
	     * @category Function
	     * @param {Function} func The function to partially apply arguments to.
	     * @param {...*} [partials] The arguments to be partially applied.
	     * @returns {Function} Returns the new partially applied function.
	     * @example
	     *
	     * var greet = function(greeting, name) {
	     *   return greeting + ' ' + name;
	     * };
	     *
	     * var greetFred = _.partialRight(greet, 'fred');
	     * greetFred('hi');
	     * // => 'hi fred'
	     *
	     * // Partially applied with placeholders.
	     * var sayHelloTo = _.partialRight(greet, 'hello', _);
	     * sayHelloTo('fred');
	     * // => 'hello fred'
	     */
	    var partialRight = rest(function(func, partials) {
	      var holders = replaceHolders(partials, getPlaceholder(partialRight));
	      return createWrapper(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders);
	    });

	    /**
	     * Creates a function that invokes `func` with arguments arranged according
	     * to the specified `indexes` where the argument value at the first index is
	     * provided as the first argument, the argument value at the second index is
	     * provided as the second argument, and so on.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Function
	     * @param {Function} func The function to rearrange arguments for.
	     * @param {...(number|number[])} indexes The arranged argument indexes.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var rearged = _.rearg(function(a, b, c) {
	     *   return [a, b, c];
	     * }, 2, 0, 1);
	     *
	     * rearged('b', 'c', 'a')
	     * // => ['a', 'b', 'c']
	     */
	    var rearg = rest(function(func, indexes) {
	      return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1));
	    });

	    /**
	     * Creates a function that invokes `func` with the `this` binding of the
	     * created function and arguments from `start` and beyond provided as
	     * an array.
	     *
	     * **Note:** This method is based on the
	     * [rest parameter](https://mdn.io/rest_parameters).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Function
	     * @param {Function} func The function to apply a rest parameter to.
	     * @param {number} [start=func.length-1] The start position of the rest parameter.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var say = _.rest(function(what, names) {
	     *   return what + ' ' + _.initial(names).join(', ') +
	     *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
	     * });
	     *
	     * say('hello', 'fred', 'barney', 'pebbles');
	     * // => 'hello fred, barney, & pebbles'
	     */
	    function rest(func, start) {
	      if (typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0);
	      return function() {
	        var args = arguments,
	            index = -1,
	            length = nativeMax(args.length - start, 0),
	            array = Array(length);

	        while (++index < length) {
	          array[index] = args[start + index];
	        }
	        switch (start) {
	          case 0: return func.call(this, array);
	          case 1: return func.call(this, args[0], array);
	          case 2: return func.call(this, args[0], args[1], array);
	        }
	        var otherArgs = Array(start + 1);
	        index = -1;
	        while (++index < start) {
	          otherArgs[index] = args[index];
	        }
	        otherArgs[start] = array;
	        return apply(func, this, otherArgs);
	      };
	    }

	    /**
	     * Creates a function that invokes `func` with the `this` binding of the
	     * create function and an array of arguments much like
	     * [`Function#apply`](http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.apply).
	     *
	     * **Note:** This method is based on the
	     * [spread operator](https://mdn.io/spread_operator).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.2.0
	     * @category Function
	     * @param {Function} func The function to spread arguments over.
	     * @param {number} [start=0] The start position of the spread.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var say = _.spread(function(who, what) {
	     *   return who + ' says ' + what;
	     * });
	     *
	     * say(['fred', 'hello']);
	     * // => 'fred says hello'
	     *
	     * var numbers = Promise.all([
	     *   Promise.resolve(40),
	     *   Promise.resolve(36)
	     * ]);
	     *
	     * numbers.then(_.spread(function(x, y) {
	     *   return x + y;
	     * }));
	     * // => a Promise of 76
	     */
	    function spread(func, start) {
	      if (typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
	      return rest(function(args) {
	        var array = args[start],
	            otherArgs = castSlice(args, 0, start);

	        if (array) {
	          arrayPush(otherArgs, array);
	        }
	        return apply(func, this, otherArgs);
	      });
	    }

	    /**
	     * Creates a throttled function that only invokes `func` at most once per
	     * every `wait` milliseconds. The throttled function comes with a `cancel`
	     * method to cancel delayed `func` invocations and a `flush` method to
	     * immediately invoke them. Provide an options object to indicate whether
	     * `func` should be invoked on the leading and/or trailing edge of the `wait`
	     * timeout. The `func` is invoked with the last arguments provided to the
	     * throttled function. Subsequent calls to the throttled function return the
	     * result of the last `func` invocation.
	     *
	     * **Note:** If `leading` and `trailing` options are `true`, `func` is
	     * invoked on the trailing edge of the timeout only if the throttled function
	     * is invoked more than once during the `wait` timeout.
	     *
	     * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
	     * for details over the differences between `_.throttle` and `_.debounce`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {Function} func The function to throttle.
	     * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
	     * @param {Object} [options={}] The options object.
	     * @param {boolean} [options.leading=true]
	     *  Specify invoking on the leading edge of the timeout.
	     * @param {boolean} [options.trailing=true]
	     *  Specify invoking on the trailing edge of the timeout.
	     * @returns {Function} Returns the new throttled function.
	     * @example
	     *
	     * // Avoid excessively updating the position while scrolling.
	     * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
	     *
	     * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
	     * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
	     * jQuery(element).on('click', throttled);
	     *
	     * // Cancel the trailing throttled invocation.
	     * jQuery(window).on('popstate', throttled.cancel);
	     */
	    function throttle(func, wait, options) {
	      var leading = true,
	          trailing = true;

	      if (typeof func != 'function') {
	        throw new TypeError(FUNC_ERROR_TEXT);
	      }
	      if (isObject(options)) {
	        leading = 'leading' in options ? !!options.leading : leading;
	        trailing = 'trailing' in options ? !!options.trailing : trailing;
	      }
	      return debounce(func, wait, {
	        'leading': leading,
	        'maxWait': wait,
	        'trailing': trailing
	      });
	    }

	    /**
	     * Creates a function that accepts up to one argument, ignoring any
	     * additional arguments.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Function
	     * @param {Function} func The function to cap arguments for.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * _.map(['6', '8', '10'], _.unary(parseInt));
	     * // => [6, 8, 10]
	     */
	    function unary(func) {
	      return ary(func, 1);
	    }

	    /**
	     * Creates a function that provides `value` to the wrapper function as its
	     * first argument. Any additional arguments provided to the function are
	     * appended to those provided to the wrapper function. The wrapper is invoked
	     * with the `this` binding of the created function.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Function
	     * @param {*} value The value to wrap.
	     * @param {Function} [wrapper=identity] The wrapper function.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var p = _.wrap(_.escape, function(func, text) {
	     *   return '<p>' + func(text) + '</p>';
	     * });
	     *
	     * p('fred, barney, & pebbles');
	     * // => '<p>fred, barney, &amp; pebbles</p>'
	     */
	    function wrap(value, wrapper) {
	      wrapper = wrapper == null ? identity : wrapper;
	      return partial(wrapper, value);
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Casts `value` as an array if it's not one.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.4.0
	     * @category Lang
	     * @param {*} value The value to inspect.
	     * @returns {Array} Returns the cast array.
	     * @example
	     *
	     * _.castArray(1);
	     * // => [1]
	     *
	     * _.castArray({ 'a': 1 });
	     * // => [{ 'a': 1 }]
	     *
	     * _.castArray('abc');
	     * // => ['abc']
	     *
	     * _.castArray(null);
	     * // => [null]
	     *
	     * _.castArray(undefined);
	     * // => [undefined]
	     *
	     * _.castArray();
	     * // => []
	     *
	     * var array = [1, 2, 3];
	     * console.log(_.castArray(array) === array);
	     * // => true
	     */
	    function castArray() {
	      if (!arguments.length) {
	        return [];
	      }
	      var value = arguments[0];
	      return isArray(value) ? value : [value];
	    }

	    /**
	     * Creates a shallow clone of `value`.
	     *
	     * **Note:** This method is loosely based on the
	     * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
	     * and supports cloning arrays, array buffers, booleans, date objects, maps,
	     * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
	     * arrays. The own enumerable properties of `arguments` objects are cloned
	     * as plain objects. An empty object is returned for uncloneable values such
	     * as error objects, functions, DOM nodes, and WeakMaps.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to clone.
	     * @returns {*} Returns the cloned value.
	     * @example
	     *
	     * var objects = [{ 'a': 1 }, { 'b': 2 }];
	     *
	     * var shallow = _.clone(objects);
	     * console.log(shallow[0] === objects[0]);
	     * // => true
	     */
	    function clone(value) {
	      return baseClone(value, false, true);
	    }

	    /**
	     * This method is like `_.clone` except that it accepts `customizer` which
	     * is invoked to produce the cloned value. If `customizer` returns `undefined`,
	     * cloning is handled by the method instead. The `customizer` is invoked with
	     * up to four arguments; (value [, index|key, object, stack]).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to clone.
	     * @param {Function} [customizer] The function to customize cloning.
	     * @returns {*} Returns the cloned value.
	     * @example
	     *
	     * function customizer(value) {
	     *   if (_.isElement(value)) {
	     *     return value.cloneNode(false);
	     *   }
	     * }
	     *
	     * var el = _.cloneWith(document.body, customizer);
	     *
	     * console.log(el === document.body);
	     * // => false
	     * console.log(el.nodeName);
	     * // => 'BODY'
	     * console.log(el.childNodes.length);
	     * // => 0
	     */
	    function cloneWith(value, customizer) {
	      return baseClone(value, false, true, customizer);
	    }

	    /**
	     * This method is like `_.clone` except that it recursively clones `value`.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.0.0
	     * @category Lang
	     * @param {*} value The value to recursively clone.
	     * @returns {*} Returns the deep cloned value.
	     * @example
	     *
	     * var objects = [{ 'a': 1 }, { 'b': 2 }];
	     *
	     * var deep = _.cloneDeep(objects);
	     * console.log(deep[0] === objects[0]);
	     * // => false
	     */
	    function cloneDeep(value) {
	      return baseClone(value, true, true);
	    }

	    /**
	     * This method is like `_.cloneWith` except that it recursively clones `value`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to recursively clone.
	     * @param {Function} [customizer] The function to customize cloning.
	     * @returns {*} Returns the deep cloned value.
	     * @example
	     *
	     * function customizer(value) {
	     *   if (_.isElement(value)) {
	     *     return value.cloneNode(true);
	     *   }
	     * }
	     *
	     * var el = _.cloneDeepWith(document.body, customizer);
	     *
	     * console.log(el === document.body);
	     * // => false
	     * console.log(el.nodeName);
	     * // => 'BODY'
	     * console.log(el.childNodes.length);
	     * // => 20
	     */
	    function cloneDeepWith(value, customizer) {
	      return baseClone(value, true, true, customizer);
	    }

	    /**
	     * Performs a
	     * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
	     * comparison between two values to determine if they are equivalent.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
	     * @example
	     *
	     * var object = { 'user': 'fred' };
	     * var other = { 'user': 'fred' };
	     *
	     * _.eq(object, object);
	     * // => true
	     *
	     * _.eq(object, other);
	     * // => false
	     *
	     * _.eq('a', 'a');
	     * // => true
	     *
	     * _.eq('a', Object('a'));
	     * // => false
	     *
	     * _.eq(NaN, NaN);
	     * // => true
	     */
	    function eq(value, other) {
	      return value === other || (value !== value && other !== other);
	    }

	    /**
	     * Checks if `value` is greater than `other`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.9.0
	     * @category Lang
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @returns {boolean} Returns `true` if `value` is greater than `other`,
	     *  else `false`.
	     * @example
	     *
	     * _.gt(3, 1);
	     * // => true
	     *
	     * _.gt(3, 3);
	     * // => false
	     *
	     * _.gt(1, 3);
	     * // => false
	     */
	    function gt(value, other) {
	      return value > other;
	    }

	    /**
	     * Checks if `value` is greater than or equal to `other`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.9.0
	     * @category Lang
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @returns {boolean} Returns `true` if `value` is greater than or equal to
	     *  `other`, else `false`.
	     * @example
	     *
	     * _.gte(3, 1);
	     * // => true
	     *
	     * _.gte(3, 3);
	     * // => true
	     *
	     * _.gte(1, 3);
	     * // => false
	     */
	    function gte(value, other) {
	      return value >= other;
	    }

	    /**
	     * Checks if `value` is likely an `arguments` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isArguments(function() { return arguments; }());
	     * // => true
	     *
	     * _.isArguments([1, 2, 3]);
	     * // => false
	     */
	    function isArguments(value) {
	      // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode.
	      return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
	        (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
	    }

	    /**
	     * Checks if `value` is classified as an `Array` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @type {Function}
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isArray([1, 2, 3]);
	     * // => true
	     *
	     * _.isArray(document.body.children);
	     * // => false
	     *
	     * _.isArray('abc');
	     * // => false
	     *
	     * _.isArray(_.noop);
	     * // => false
	     */
	    var isArray = Array.isArray;

	    /**
	     * Checks if `value` is classified as an `ArrayBuffer` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.3.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isArrayBuffer(new ArrayBuffer(2));
	     * // => true
	     *
	     * _.isArrayBuffer(new Array(2));
	     * // => false
	     */
	    function isArrayBuffer(value) {
	      return isObjectLike(value) && objectToString.call(value) == arrayBufferTag;
	    }

	    /**
	     * Checks if `value` is array-like. A value is considered array-like if it's
	     * not a function and has a `value.length` that's an integer greater than or
	     * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
	     * @example
	     *
	     * _.isArrayLike([1, 2, 3]);
	     * // => true
	     *
	     * _.isArrayLike(document.body.children);
	     * // => true
	     *
	     * _.isArrayLike('abc');
	     * // => true
	     *
	     * _.isArrayLike(_.noop);
	     * // => false
	     */
	    function isArrayLike(value) {
	      return value != null && isLength(getLength(value)) && !isFunction(value);
	    }

	    /**
	     * This method is like `_.isArrayLike` except that it also checks if `value`
	     * is an object.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is an array-like object,
	     *  else `false`.
	     * @example
	     *
	     * _.isArrayLikeObject([1, 2, 3]);
	     * // => true
	     *
	     * _.isArrayLikeObject(document.body.children);
	     * // => true
	     *
	     * _.isArrayLikeObject('abc');
	     * // => false
	     *
	     * _.isArrayLikeObject(_.noop);
	     * // => false
	     */
	    function isArrayLikeObject(value) {
	      return isObjectLike(value) && isArrayLike(value);
	    }

	    /**
	     * Checks if `value` is classified as a boolean primitive or object.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isBoolean(false);
	     * // => true
	     *
	     * _.isBoolean(null);
	     * // => false
	     */
	    function isBoolean(value) {
	      return value === true || value === false ||
	        (isObjectLike(value) && objectToString.call(value) == boolTag);
	    }

	    /**
	     * Checks if `value` is a buffer.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.3.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
	     * @example
	     *
	     * _.isBuffer(new Buffer(2));
	     * // => true
	     *
	     * _.isBuffer(new Uint8Array(2));
	     * // => false
	     */
	    var isBuffer = !Buffer ? constant(false) : function(value) {
	      return value instanceof Buffer;
	    };

	    /**
	     * Checks if `value` is classified as a `Date` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isDate(new Date);
	     * // => true
	     *
	     * _.isDate('Mon April 23 2012');
	     * // => false
	     */
	    function isDate(value) {
	      return isObjectLike(value) && objectToString.call(value) == dateTag;
	    }

	    /**
	     * Checks if `value` is likely a DOM element.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a DOM element,
	     *  else `false`.
	     * @example
	     *
	     * _.isElement(document.body);
	     * // => true
	     *
	     * _.isElement('<body>');
	     * // => false
	     */
	    function isElement(value) {
	      return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
	    }

	    /**
	     * Checks if `value` is an empty object, collection, map, or set.
	     *
	     * Objects are considered empty if they have no own enumerable string keyed
	     * properties.
	     *
	     * Array-like values such as `arguments` objects, arrays, buffers, strings, or
	     * jQuery-like collections are considered empty if they have a `length` of `0`.
	     * Similarly, maps and sets are considered empty if they have a `size` of `0`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is empty, else `false`.
	     * @example
	     *
	     * _.isEmpty(null);
	     * // => true
	     *
	     * _.isEmpty(true);
	     * // => true
	     *
	     * _.isEmpty(1);
	     * // => true
	     *
	     * _.isEmpty([1, 2, 3]);
	     * // => false
	     *
	     * _.isEmpty({ 'a': 1 });
	     * // => false
	     */
	    function isEmpty(value) {
	      if (isArrayLike(value) &&
	          (isArray(value) || isString(value) || isFunction(value.splice) ||
	            isArguments(value) || isBuffer(value))) {
	        return !value.length;
	      }
	      if (isObjectLike(value)) {
	        var tag = getTag(value);
	        if (tag == mapTag || tag == setTag) {
	          return !value.size;
	        }
	      }
	      for (var key in value) {
	        if (hasOwnProperty.call(value, key)) {
	          return false;
	        }
	      }
	      return !(nonEnumShadows && keys(value).length);
	    }

	    /**
	     * Performs a deep comparison between two values to determine if they are
	     * equivalent.
	     *
	     * **Note:** This method supports comparing arrays, array buffers, booleans,
	     * date objects, error objects, maps, numbers, `Object` objects, regexes,
	     * sets, strings, symbols, and typed arrays. `Object` objects are compared
	     * by their own, not inherited, enumerable properties. Functions and DOM
	     * nodes are **not** supported.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @returns {boolean} Returns `true` if the values are equivalent,
	     *  else `false`.
	     * @example
	     *
	     * var object = { 'user': 'fred' };
	     * var other = { 'user': 'fred' };
	     *
	     * _.isEqual(object, other);
	     * // => true
	     *
	     * object === other;
	     * // => false
	     */
	    function isEqual(value, other) {
	      return baseIsEqual(value, other);
	    }

	    /**
	     * This method is like `_.isEqual` except that it accepts `customizer` which
	     * is invoked to compare values. If `customizer` returns `undefined`, comparisons
	     * are handled by the method instead. The `customizer` is invoked with up to
	     * six arguments: (objValue, othValue [, index|key, object, other, stack]).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @param {Function} [customizer] The function to customize comparisons.
	     * @returns {boolean} Returns `true` if the values are equivalent,
	     *  else `false`.
	     * @example
	     *
	     * function isGreeting(value) {
	     *   return /^h(?:i|ello)$/.test(value);
	     * }
	     *
	     * function customizer(objValue, othValue) {
	     *   if (isGreeting(objValue) && isGreeting(othValue)) {
	     *     return true;
	     *   }
	     * }
	     *
	     * var array = ['hello', 'goodbye'];
	     * var other = ['hi', 'goodbye'];
	     *
	     * _.isEqualWith(array, other, customizer);
	     * // => true
	     */
	    function isEqualWith(value, other, customizer) {
	      customizer = typeof customizer == 'function' ? customizer : undefined;
	      var result = customizer ? customizer(value, other) : undefined;
	      return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
	    }

	    /**
	     * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
	     * `SyntaxError`, `TypeError`, or `URIError` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is an error object,
	     *  else `false`.
	     * @example
	     *
	     * _.isError(new Error);
	     * // => true
	     *
	     * _.isError(Error);
	     * // => false
	     */
	    function isError(value) {
	      if (!isObjectLike(value)) {
	        return false;
	      }
	      return (objectToString.call(value) == errorTag) ||
	        (typeof value.message == 'string' && typeof value.name == 'string');
	    }

	    /**
	     * Checks if `value` is a finite primitive number.
	     *
	     * **Note:** This method is based on
	     * [`Number.isFinite`](https://mdn.io/Number/isFinite).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a finite number,
	     *  else `false`.
	     * @example
	     *
	     * _.isFinite(3);
	     * // => true
	     *
	     * _.isFinite(Number.MAX_VALUE);
	     * // => true
	     *
	     * _.isFinite(3.14);
	     * // => true
	     *
	     * _.isFinite(Infinity);
	     * // => false
	     */
	    function isFinite(value) {
	      return typeof value == 'number' && nativeIsFinite(value);
	    }

	    /**
	     * Checks if `value` is classified as a `Function` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isFunction(_);
	     * // => true
	     *
	     * _.isFunction(/abc/);
	     * // => false
	     */
	    function isFunction(value) {
	      // The use of `Object#toString` avoids issues with the `typeof` operator
	      // in Safari 8 which returns 'object' for typed array and weak map constructors,
	      // and PhantomJS 1.9 which returns 'function' for `NodeList` instances.
	      var tag = isObject(value) ? objectToString.call(value) : '';
	      return tag == funcTag || tag == genTag;
	    }

	    /**
	     * Checks if `value` is an integer.
	     *
	     * **Note:** This method is based on
	     * [`Number.isInteger`](https://mdn.io/Number/isInteger).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
	     * @example
	     *
	     * _.isInteger(3);
	     * // => true
	     *
	     * _.isInteger(Number.MIN_VALUE);
	     * // => false
	     *
	     * _.isInteger(Infinity);
	     * // => false
	     *
	     * _.isInteger('3');
	     * // => false
	     */
	    function isInteger(value) {
	      return typeof value == 'number' && value == toInteger(value);
	    }

	    /**
	     * Checks if `value` is a valid array-like length.
	     *
	     * **Note:** This function is loosely based on
	     * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a valid length,
	     *  else `false`.
	     * @example
	     *
	     * _.isLength(3);
	     * // => true
	     *
	     * _.isLength(Number.MIN_VALUE);
	     * // => false
	     *
	     * _.isLength(Infinity);
	     * // => false
	     *
	     * _.isLength('3');
	     * // => false
	     */
	    function isLength(value) {
	      return typeof value == 'number' &&
	        value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
	    }

	    /**
	     * Checks if `value` is the
	     * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types)
	     * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is an object, else `false`.
	     * @example
	     *
	     * _.isObject({});
	     * // => true
	     *
	     * _.isObject([1, 2, 3]);
	     * // => true
	     *
	     * _.isObject(_.noop);
	     * // => true
	     *
	     * _.isObject(null);
	     * // => false
	     */
	    function isObject(value) {
	      var type = typeof value;
	      return !!value && (type == 'object' || type == 'function');
	    }

	    /**
	     * Checks if `value` is object-like. A value is object-like if it's not `null`
	     * and has a `typeof` result of "object".
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
	     * @example
	     *
	     * _.isObjectLike({});
	     * // => true
	     *
	     * _.isObjectLike([1, 2, 3]);
	     * // => true
	     *
	     * _.isObjectLike(_.noop);
	     * // => false
	     *
	     * _.isObjectLike(null);
	     * // => false
	     */
	    function isObjectLike(value) {
	      return !!value && typeof value == 'object';
	    }

	    /**
	     * Checks if `value` is classified as a `Map` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.3.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isMap(new Map);
	     * // => true
	     *
	     * _.isMap(new WeakMap);
	     * // => false
	     */
	    function isMap(value) {
	      return isObjectLike(value) && getTag(value) == mapTag;
	    }

	    /**
	     * Performs a partial deep comparison between `object` and `source` to
	     * determine if `object` contains equivalent property values. This method is
	     * equivalent to a `_.matches` function when `source` is partially applied.
	     *
	     * **Note:** This method supports comparing the same values as `_.isEqual`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Lang
	     * @param {Object} object The object to inspect.
	     * @param {Object} source The object of property values to match.
	     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
	     * @example
	     *
	     * var object = { 'user': 'fred', 'age': 40 };
	     *
	     * _.isMatch(object, { 'age': 40 });
	     * // => true
	     *
	     * _.isMatch(object, { 'age': 36 });
	     * // => false
	     */
	    function isMatch(object, source) {
	      return object === source || baseIsMatch(object, source, getMatchData(source));
	    }

	    /**
	     * This method is like `_.isMatch` except that it accepts `customizer` which
	     * is invoked to compare values. If `customizer` returns `undefined`, comparisons
	     * are handled by the method instead. The `customizer` is invoked with five
	     * arguments: (objValue, srcValue, index|key, object, source).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {Object} object The object to inspect.
	     * @param {Object} source The object of property values to match.
	     * @param {Function} [customizer] The function to customize comparisons.
	     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
	     * @example
	     *
	     * function isGreeting(value) {
	     *   return /^h(?:i|ello)$/.test(value);
	     * }
	     *
	     * function customizer(objValue, srcValue) {
	     *   if (isGreeting(objValue) && isGreeting(srcValue)) {
	     *     return true;
	     *   }
	     * }
	     *
	     * var object = { 'greeting': 'hello' };
	     * var source = { 'greeting': 'hi' };
	     *
	     * _.isMatchWith(object, source, customizer);
	     * // => true
	     */
	    function isMatchWith(object, source, customizer) {
	      customizer = typeof customizer == 'function' ? customizer : undefined;
	      return baseIsMatch(object, source, getMatchData(source), customizer);
	    }

	    /**
	     * Checks if `value` is `NaN`.
	     *
	     * **Note:** This method is based on
	     * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
	     * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
	     * `undefined` and other non-number values.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
	     * @example
	     *
	     * _.isNaN(NaN);
	     * // => true
	     *
	     * _.isNaN(new Number(NaN));
	     * // => true
	     *
	     * isNaN(undefined);
	     * // => true
	     *
	     * _.isNaN(undefined);
	     * // => false
	     */
	    function isNaN(value) {
	      // An `NaN` primitive is the only value that is not equal to itself.
	      // Perform the `toStringTag` check first to avoid errors with some
	      // ActiveX objects in IE.
	      return isNumber(value) && value != +value;
	    }

	    /**
	     * Checks if `value` is a native function.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a native function,
	     *  else `false`.
	     * @example
	     *
	     * _.isNative(Array.prototype.push);
	     * // => true
	     *
	     * _.isNative(_);
	     * // => false
	     */
	    function isNative(value) {
	      if (!isObject(value)) {
	        return false;
	      }
	      var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
	      return pattern.test(toSource(value));
	    }

	    /**
	     * Checks if `value` is `null`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
	     * @example
	     *
	     * _.isNull(null);
	     * // => true
	     *
	     * _.isNull(void 0);
	     * // => false
	     */
	    function isNull(value) {
	      return value === null;
	    }

	    /**
	     * Checks if `value` is `null` or `undefined`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
	     * @example
	     *
	     * _.isNil(null);
	     * // => true
	     *
	     * _.isNil(void 0);
	     * // => true
	     *
	     * _.isNil(NaN);
	     * // => false
	     */
	    function isNil(value) {
	      return value == null;
	    }

	    /**
	     * Checks if `value` is classified as a `Number` primitive or object.
	     *
	     * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
	     * classified as numbers, use the `_.isFinite` method.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isNumber(3);
	     * // => true
	     *
	     * _.isNumber(Number.MIN_VALUE);
	     * // => true
	     *
	     * _.isNumber(Infinity);
	     * // => true
	     *
	     * _.isNumber('3');
	     * // => false
	     */
	    function isNumber(value) {
	      return typeof value == 'number' ||
	        (isObjectLike(value) && objectToString.call(value) == numberTag);
	    }

	    /**
	     * Checks if `value` is a plain object, that is, an object created by the
	     * `Object` constructor or one with a `[[Prototype]]` of `null`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.8.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a plain object,
	     *  else `false`.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     * }
	     *
	     * _.isPlainObject(new Foo);
	     * // => false
	     *
	     * _.isPlainObject([1, 2, 3]);
	     * // => false
	     *
	     * _.isPlainObject({ 'x': 0, 'y': 0 });
	     * // => true
	     *
	     * _.isPlainObject(Object.create(null));
	     * // => true
	     */
	    function isPlainObject(value) {
	      if (!isObjectLike(value) ||
	          objectToString.call(value) != objectTag || isHostObject(value)) {
	        return false;
	      }
	      var proto = getPrototype(value);
	      if (proto === null) {
	        return true;
	      }
	      var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
	      return (typeof Ctor == 'function' &&
	        Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
	    }

	    /**
	     * Checks if `value` is classified as a `RegExp` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.1.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isRegExp(/abc/);
	     * // => true
	     *
	     * _.isRegExp('/abc/');
	     * // => false
	     */
	    function isRegExp(value) {
	      return isObject(value) && objectToString.call(value) == regexpTag;
	    }

	    /**
	     * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
	     * double precision number which isn't the result of a rounded unsafe integer.
	     *
	     * **Note:** This method is based on
	     * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is a safe integer,
	     *  else `false`.
	     * @example
	     *
	     * _.isSafeInteger(3);
	     * // => true
	     *
	     * _.isSafeInteger(Number.MIN_VALUE);
	     * // => false
	     *
	     * _.isSafeInteger(Infinity);
	     * // => false
	     *
	     * _.isSafeInteger('3');
	     * // => false
	     */
	    function isSafeInteger(value) {
	      return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
	    }

	    /**
	     * Checks if `value` is classified as a `Set` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.3.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isSet(new Set);
	     * // => true
	     *
	     * _.isSet(new WeakSet);
	     * // => false
	     */
	    function isSet(value) {
	      return isObjectLike(value) && getTag(value) == setTag;
	    }

	    /**
	     * Checks if `value` is classified as a `String` primitive or object.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isString('abc');
	     * // => true
	     *
	     * _.isString(1);
	     * // => false
	     */
	    function isString(value) {
	      return typeof value == 'string' ||
	        (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
	    }

	    /**
	     * Checks if `value` is classified as a `Symbol` primitive or object.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isSymbol(Symbol.iterator);
	     * // => true
	     *
	     * _.isSymbol('abc');
	     * // => false
	     */
	    function isSymbol(value) {
	      return typeof value == 'symbol' ||
	        (isObjectLike(value) && objectToString.call(value) == symbolTag);
	    }

	    /**
	     * Checks if `value` is classified as a typed array.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isTypedArray(new Uint8Array);
	     * // => true
	     *
	     * _.isTypedArray([]);
	     * // => false
	     */
	    function isTypedArray(value) {
	      return isObjectLike(value) &&
	        isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
	    }

	    /**
	     * Checks if `value` is `undefined`.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
	     * @example
	     *
	     * _.isUndefined(void 0);
	     * // => true
	     *
	     * _.isUndefined(null);
	     * // => false
	     */
	    function isUndefined(value) {
	      return value === undefined;
	    }

	    /**
	     * Checks if `value` is classified as a `WeakMap` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.3.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isWeakMap(new WeakMap);
	     * // => true
	     *
	     * _.isWeakMap(new Map);
	     * // => false
	     */
	    function isWeakMap(value) {
	      return isObjectLike(value) && getTag(value) == weakMapTag;
	    }

	    /**
	     * Checks if `value` is classified as a `WeakSet` object.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.3.0
	     * @category Lang
	     * @param {*} value The value to check.
	     * @returns {boolean} Returns `true` if `value` is correctly classified,
	     *  else `false`.
	     * @example
	     *
	     * _.isWeakSet(new WeakSet);
	     * // => true
	     *
	     * _.isWeakSet(new Set);
	     * // => false
	     */
	    function isWeakSet(value) {
	      return isObjectLike(value) && objectToString.call(value) == weakSetTag;
	    }

	    /**
	     * Checks if `value` is less than `other`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.9.0
	     * @category Lang
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @returns {boolean} Returns `true` if `value` is less than `other`,
	     *  else `false`.
	     * @example
	     *
	     * _.lt(1, 3);
	     * // => true
	     *
	     * _.lt(3, 3);
	     * // => false
	     *
	     * _.lt(3, 1);
	     * // => false
	     */
	    function lt(value, other) {
	      return value < other;
	    }

	    /**
	     * Checks if `value` is less than or equal to `other`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.9.0
	     * @category Lang
	     * @param {*} value The value to compare.
	     * @param {*} other The other value to compare.
	     * @returns {boolean} Returns `true` if `value` is less than or equal to
	     *  `other`, else `false`.
	     * @example
	     *
	     * _.lte(1, 3);
	     * // => true
	     *
	     * _.lte(3, 3);
	     * // => true
	     *
	     * _.lte(3, 1);
	     * // => false
	     */
	    function lte(value, other) {
	      return value <= other;
	    }

	    /**
	     * Converts `value` to an array.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Lang
	     * @param {*} value The value to convert.
	     * @returns {Array} Returns the converted array.
	     * @example
	     *
	     * _.toArray({ 'a': 1, 'b': 2 });
	     * // => [1, 2]
	     *
	     * _.toArray('abc');
	     * // => ['a', 'b', 'c']
	     *
	     * _.toArray(1);
	     * // => []
	     *
	     * _.toArray(null);
	     * // => []
	     */
	    function toArray(value) {
	      if (!value) {
	        return [];
	      }
	      if (isArrayLike(value)) {
	        return isString(value) ? stringToArray(value) : copyArray(value);
	      }
	      if (iteratorSymbol && value[iteratorSymbol]) {
	        return iteratorToArray(value[iteratorSymbol]());
	      }
	      var tag = getTag(value),
	          func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);

	      return func(value);
	    }

	    /**
	     * Converts `value` to an integer.
	     *
	     * **Note:** This function is loosely based on
	     * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to convert.
	     * @returns {number} Returns the converted integer.
	     * @example
	     *
	     * _.toInteger(3);
	     * // => 3
	     *
	     * _.toInteger(Number.MIN_VALUE);
	     * // => 0
	     *
	     * _.toInteger(Infinity);
	     * // => 1.7976931348623157e+308
	     *
	     * _.toInteger('3');
	     * // => 3
	     */
	    function toInteger(value) {
	      if (!value) {
	        return value === 0 ? value : 0;
	      }
	      value = toNumber(value);
	      if (value === INFINITY || value === -INFINITY) {
	        var sign = (value < 0 ? -1 : 1);
	        return sign * MAX_INTEGER;
	      }
	      var remainder = value % 1;
	      return value === value ? (remainder ? value - remainder : value) : 0;
	    }

	    /**
	     * Converts `value` to an integer suitable for use as the length of an
	     * array-like object.
	     *
	     * **Note:** This method is based on
	     * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to convert.
	     * @returns {number} Returns the converted integer.
	     * @example
	     *
	     * _.toLength(3);
	     * // => 3
	     *
	     * _.toLength(Number.MIN_VALUE);
	     * // => 0
	     *
	     * _.toLength(Infinity);
	     * // => 4294967295
	     *
	     * _.toLength('3');
	     * // => 3
	     */
	    function toLength(value) {
	      return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
	    }

	    /**
	     * Converts `value` to a number.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to process.
	     * @returns {number} Returns the number.
	     * @example
	     *
	     * _.toNumber(3);
	     * // => 3
	     *
	     * _.toNumber(Number.MIN_VALUE);
	     * // => 5e-324
	     *
	     * _.toNumber(Infinity);
	     * // => Infinity
	     *
	     * _.toNumber('3');
	     * // => 3
	     */
	    function toNumber(value) {
	      if (typeof value == 'number') {
	        return value;
	      }
	      if (isSymbol(value)) {
	        return NAN;
	      }
	      if (isObject(value)) {
	        var other = isFunction(value.valueOf) ? value.valueOf() : value;
	        value = isObject(other) ? (other + '') : other;
	      }
	      if (typeof value != 'string') {
	        return value === 0 ? value : +value;
	      }
	      value = value.replace(reTrim, '');
	      var isBinary = reIsBinary.test(value);
	      return (isBinary || reIsOctal.test(value))
	        ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
	        : (reIsBadHex.test(value) ? NAN : +value);
	    }

	    /**
	     * Converts `value` to a plain object flattening inherited enumerable string
	     * keyed properties of `value` to own properties of the plain object.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Lang
	     * @param {*} value The value to convert.
	     * @returns {Object} Returns the converted plain object.
	     * @example
	     *
	     * function Foo() {
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.assign({ 'a': 1 }, new Foo);
	     * // => { 'a': 1, 'b': 2 }
	     *
	     * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
	     * // => { 'a': 1, 'b': 2, 'c': 3 }
	     */
	    function toPlainObject(value) {
	      return copyObject(value, keysIn(value));
	    }

	    /**
	     * Converts `value` to a safe integer. A safe integer can be compared and
	     * represented correctly.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to convert.
	     * @returns {number} Returns the converted integer.
	     * @example
	     *
	     * _.toSafeInteger(3);
	     * // => 3
	     *
	     * _.toSafeInteger(Number.MIN_VALUE);
	     * // => 0
	     *
	     * _.toSafeInteger(Infinity);
	     * // => 9007199254740991
	     *
	     * _.toSafeInteger('3');
	     * // => 3
	     */
	    function toSafeInteger(value) {
	      return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);
	    }

	    /**
	     * Converts `value` to a string. An empty string is returned for `null`
	     * and `undefined` values. The sign of `-0` is preserved.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Lang
	     * @param {*} value The value to process.
	     * @returns {string} Returns the string.
	     * @example
	     *
	     * _.toString(null);
	     * // => ''
	     *
	     * _.toString(-0);
	     * // => '-0'
	     *
	     * _.toString([1, 2, 3]);
	     * // => '1,2,3'
	     */
	    function toString(value) {
	      // Exit early for strings to avoid a performance hit in some environments.
	      if (typeof value == 'string') {
	        return value;
	      }
	      if (value == null) {
	        return '';
	      }
	      if (isSymbol(value)) {
	        return symbolToString ? symbolToString.call(value) : '';
	      }
	      var result = (value + '');
	      return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Assigns own enumerable string keyed properties of source objects to the
	     * destination object. Source objects are applied from left to right.
	     * Subsequent sources overwrite property assignments of previous sources.
	     *
	     * **Note:** This method mutates `object` and is loosely based on
	     * [`Object.assign`](https://mdn.io/Object/assign).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.10.0
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} [sources] The source objects.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function Foo() {
	     *   this.c = 3;
	     * }
	     *
	     * function Bar() {
	     *   this.e = 5;
	     * }
	     *
	     * Foo.prototype.d = 4;
	     * Bar.prototype.f = 6;
	     *
	     * _.assign({ 'a': 1 }, new Foo, new Bar);
	     * // => { 'a': 1, 'c': 3, 'e': 5 }
	     */
	    var assign = createAssigner(function(object, source) {
	      if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) {
	        copyObject(source, keys(source), object);
	        return;
	      }
	      for (var key in source) {
	        if (hasOwnProperty.call(source, key)) {
	          assignValue(object, key, source[key]);
	        }
	      }
	    });

	    /**
	     * This method is like `_.assign` except that it iterates over own and
	     * inherited source properties.
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @alias extend
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} [sources] The source objects.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function Foo() {
	     *   this.b = 2;
	     * }
	     *
	     * function Bar() {
	     *   this.d = 4;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     * Bar.prototype.e = 5;
	     *
	     * _.assignIn({ 'a': 1 }, new Foo, new Bar);
	     * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 }
	     */
	    var assignIn = createAssigner(function(object, source) {
	      if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) {
	        copyObject(source, keysIn(source), object);
	        return;
	      }
	      for (var key in source) {
	        assignValue(object, key, source[key]);
	      }
	    });

	    /**
	     * This method is like `_.assignIn` except that it accepts `customizer`
	     * which is invoked to produce the assigned values. If `customizer` returns
	     * `undefined`, assignment is handled by the method instead. The `customizer`
	     * is invoked with five arguments: (objValue, srcValue, key, object, source).
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @alias extendWith
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} sources The source objects.
	     * @param {Function} [customizer] The function to customize assigned values.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function customizer(objValue, srcValue) {
	     *   return _.isUndefined(objValue) ? srcValue : objValue;
	     * }
	     *
	     * var defaults = _.partialRight(_.assignInWith, customizer);
	     *
	     * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
	     * // => { 'a': 1, 'b': 2 }
	     */
	    var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
	      copyObject(source, keysIn(source), object, customizer);
	    });

	    /**
	     * This method is like `_.assign` except that it accepts `customizer`
	     * which is invoked to produce the assigned values. If `customizer` returns
	     * `undefined`, assignment is handled by the method instead. The `customizer`
	     * is invoked with five arguments: (objValue, srcValue, key, object, source).
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} sources The source objects.
	     * @param {Function} [customizer] The function to customize assigned values.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function customizer(objValue, srcValue) {
	     *   return _.isUndefined(objValue) ? srcValue : objValue;
	     * }
	     *
	     * var defaults = _.partialRight(_.assignWith, customizer);
	     *
	     * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
	     * // => { 'a': 1, 'b': 2 }
	     */
	    var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
	      copyObject(source, keys(source), object, customizer);
	    });

	    /**
	     * Creates an array of values corresponding to `paths` of `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.0.0
	     * @category Object
	     * @param {Object} object The object to iterate over.
	     * @param {...(string|string[])} [paths] The property paths of elements to pick.
	     * @returns {Array} Returns the new array of picked elements.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
	     *
	     * _.at(object, ['a[0].b.c', 'a[1]']);
	     * // => [3, 4]
	     *
	     * _.at(['a', 'b', 'c'], 0, 2);
	     * // => ['a', 'c']
	     */
	    var at = rest(function(object, paths) {
	      return baseAt(object, baseFlatten(paths, 1));
	    });

	    /**
	     * Creates an object that inherits from the `prototype` object. If a
	     * `properties` object is given, its own enumerable string keyed properties
	     * are assigned to the created object.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.3.0
	     * @category Object
	     * @param {Object} prototype The object to inherit from.
	     * @param {Object} [properties] The properties to assign to the object.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * function Shape() {
	     *   this.x = 0;
	     *   this.y = 0;
	     * }
	     *
	     * function Circle() {
	     *   Shape.call(this);
	     * }
	     *
	     * Circle.prototype = _.create(Shape.prototype, {
	     *   'constructor': Circle
	     * });
	     *
	     * var circle = new Circle;
	     * circle instanceof Circle;
	     * // => true
	     *
	     * circle instanceof Shape;
	     * // => true
	     */
	    function create(prototype, properties) {
	      var result = baseCreate(prototype);
	      return properties ? baseAssign(result, properties) : result;
	    }

	    /**
	     * Assigns own and inherited enumerable string keyed properties of source
	     * objects to the destination object for all destination properties that
	     * resolve to `undefined`. Source objects are applied from left to right.
	     * Once a property is set, additional values of the same property are ignored.
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} [sources] The source objects.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
	     * // => { 'user': 'barney', 'age': 36 }
	     */
	    var defaults = rest(function(args) {
	      args.push(undefined, assignInDefaults);
	      return apply(assignInWith, undefined, args);
	    });

	    /**
	     * This method is like `_.defaults` except that it recursively assigns
	     * default properties.
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.10.0
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} [sources] The source objects.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
	     * // => { 'user': { 'name': 'barney', 'age': 36 } }
	     *
	     */
	    var defaultsDeep = rest(function(args) {
	      args.push(undefined, mergeDefaults);
	      return apply(mergeWith, undefined, args);
	    });

	    /**
	     * This method is like `_.find` except that it returns the key of the first
	     * element `predicate` returns truthy for instead of the element itself.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.1.0
	     * @category Object
	     * @param {Object} object The object to search.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {string|undefined} Returns the key of the matched element,
	     *  else `undefined`.
	     * @example
	     *
	     * var users = {
	     *   'barney':  { 'age': 36, 'active': true },
	     *   'fred':    { 'age': 40, 'active': false },
	     *   'pebbles': { 'age': 1,  'active': true }
	     * };
	     *
	     * _.findKey(users, function(o) { return o.age < 40; });
	     * // => 'barney' (iteration order is not guaranteed)
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.findKey(users, { 'age': 1, 'active': true });
	     * // => 'pebbles'
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.findKey(users, ['active', false]);
	     * // => 'fred'
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.findKey(users, 'active');
	     * // => 'barney'
	     */
	    function findKey(object, predicate) {
	      return baseFind(object, getIteratee(predicate, 3), baseForOwn, true);
	    }

	    /**
	     * This method is like `_.findKey` except that it iterates over elements of
	     * a collection in the opposite order.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Object
	     * @param {Object} object The object to search.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per iteration.
	     * @returns {string|undefined} Returns the key of the matched element,
	     *  else `undefined`.
	     * @example
	     *
	     * var users = {
	     *   'barney':  { 'age': 36, 'active': true },
	     *   'fred':    { 'age': 40, 'active': false },
	     *   'pebbles': { 'age': 1,  'active': true }
	     * };
	     *
	     * _.findLastKey(users, function(o) { return o.age < 40; });
	     * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.findLastKey(users, { 'age': 36, 'active': true });
	     * // => 'barney'
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.findLastKey(users, ['active', false]);
	     * // => 'fred'
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.findLastKey(users, 'active');
	     * // => 'pebbles'
	     */
	    function findLastKey(object, predicate) {
	      return baseFind(object, getIteratee(predicate, 3), baseForOwnRight, true);
	    }

	    /**
	     * Iterates over own and inherited enumerable string keyed properties of an
	     * object and invokes `iteratee` for each property. The iteratee is invoked
	     * with three arguments: (value, key, object). Iteratee functions may exit
	     * iteration early by explicitly returning `false`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.3.0
	     * @category Object
	     * @param {Object} object The object to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.forIn(new Foo, function(value, key) {
	     *   console.log(key);
	     * });
	     * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
	     */
	    function forIn(object, iteratee) {
	      return object == null
	        ? object
	        : baseFor(object, getIteratee(iteratee), keysIn);
	    }

	    /**
	     * This method is like `_.forIn` except that it iterates over properties of
	     * `object` in the opposite order.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Object
	     * @param {Object} object The object to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.forInRight(new Foo, function(value, key) {
	     *   console.log(key);
	     * });
	     * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
	     */
	    function forInRight(object, iteratee) {
	      return object == null
	        ? object
	        : baseForRight(object, getIteratee(iteratee), keysIn);
	    }

	    /**
	     * Iterates over own enumerable string keyed properties of an object and
	     * invokes `iteratee` for each property. The iteratee is invoked with three
	     * arguments: (value, key, object). Iteratee functions may exit iteration
	     * early by explicitly returning `false`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.3.0
	     * @category Object
	     * @param {Object} object The object to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.forOwn(new Foo, function(value, key) {
	     *   console.log(key);
	     * });
	     * // => Logs 'a' then 'b' (iteration order is not guaranteed).
	     */
	    function forOwn(object, iteratee) {
	      return object && baseForOwn(object, getIteratee(iteratee));
	    }

	    /**
	     * This method is like `_.forOwn` except that it iterates over properties of
	     * `object` in the opposite order.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.0.0
	     * @category Object
	     * @param {Object} object The object to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.forOwnRight(new Foo, function(value, key) {
	     *   console.log(key);
	     * });
	     * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
	     */
	    function forOwnRight(object, iteratee) {
	      return object && baseForOwnRight(object, getIteratee(iteratee));
	    }

	    /**
	     * Creates an array of function property names from own enumerable properties
	     * of `object`.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The object to inspect.
	     * @returns {Array} Returns the new array of property names.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = _.constant('a');
	     *   this.b = _.constant('b');
	     * }
	     *
	     * Foo.prototype.c = _.constant('c');
	     *
	     * _.functions(new Foo);
	     * // => ['a', 'b']
	     */
	    function functions(object) {
	      return object == null ? [] : baseFunctions(object, keys(object));
	    }

	    /**
	     * Creates an array of function property names from own and inherited
	     * enumerable properties of `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The object to inspect.
	     * @returns {Array} Returns the new array of property names.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = _.constant('a');
	     *   this.b = _.constant('b');
	     * }
	     *
	     * Foo.prototype.c = _.constant('c');
	     *
	     * _.functionsIn(new Foo);
	     * // => ['a', 'b', 'c']
	     */
	    function functionsIn(object) {
	      return object == null ? [] : baseFunctions(object, keysIn(object));
	    }

	    /**
	     * Gets the value at `path` of `object`. If the resolved value is
	     * `undefined`, the `defaultValue` is used in its place.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.7.0
	     * @category Object
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path of the property to get.
	     * @param {*} [defaultValue] The value returned for `undefined` resolved values.
	     * @returns {*} Returns the resolved value.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
	     *
	     * _.get(object, 'a[0].b.c');
	     * // => 3
	     *
	     * _.get(object, ['a', '0', 'b', 'c']);
	     * // => 3
	     *
	     * _.get(object, 'a.b.c', 'default');
	     * // => 'default'
	     */
	    function get(object, path, defaultValue) {
	      var result = object == null ? undefined : baseGet(object, path);
	      return result === undefined ? defaultValue : result;
	    }

	    /**
	     * Checks if `path` is a direct property of `object`.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path to check.
	     * @returns {boolean} Returns `true` if `path` exists, else `false`.
	     * @example
	     *
	     * var object = { 'a': { 'b': 2 } };
	     * var other = _.create({ 'a': _.create({ 'b': 2 }) });
	     *
	     * _.has(object, 'a');
	     * // => true
	     *
	     * _.has(object, 'a.b');
	     * // => true
	     *
	     * _.has(object, ['a', 'b']);
	     * // => true
	     *
	     * _.has(other, 'a');
	     * // => false
	     */
	    function has(object, path) {
	      return object != null && hasPath(object, path, baseHas);
	    }

	    /**
	     * Checks if `path` is a direct or inherited property of `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path to check.
	     * @returns {boolean} Returns `true` if `path` exists, else `false`.
	     * @example
	     *
	     * var object = _.create({ 'a': _.create({ 'b': 2 }) });
	     *
	     * _.hasIn(object, 'a');
	     * // => true
	     *
	     * _.hasIn(object, 'a.b');
	     * // => true
	     *
	     * _.hasIn(object, ['a', 'b']);
	     * // => true
	     *
	     * _.hasIn(object, 'b');
	     * // => false
	     */
	    function hasIn(object, path) {
	      return object != null && hasPath(object, path, baseHasIn);
	    }

	    /**
	     * Creates an object composed of the inverted keys and values of `object`.
	     * If `object` contains duplicate values, subsequent values overwrite
	     * property assignments of previous values.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.7.0
	     * @category Object
	     * @param {Object} object The object to invert.
	     * @returns {Object} Returns the new inverted object.
	     * @example
	     *
	     * var object = { 'a': 1, 'b': 2, 'c': 1 };
	     *
	     * _.invert(object);
	     * // => { '1': 'c', '2': 'b' }
	     */
	    var invert = createInverter(function(result, value, key) {
	      result[value] = key;
	    }, constant(identity));

	    /**
	     * This method is like `_.invert` except that the inverted object is generated
	     * from the results of running each element of `object` thru `iteratee`. The
	     * corresponding inverted value of each inverted key is an array of keys
	     * responsible for generating the inverted value. The iteratee is invoked
	     * with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.1.0
	     * @category Object
	     * @param {Object} object The object to invert.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {Object} Returns the new inverted object.
	     * @example
	     *
	     * var object = { 'a': 1, 'b': 2, 'c': 1 };
	     *
	     * _.invertBy(object);
	     * // => { '1': ['a', 'c'], '2': ['b'] }
	     *
	     * _.invertBy(object, function(value) {
	     *   return 'group' + value;
	     * });
	     * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
	     */
	    var invertBy = createInverter(function(result, value, key) {
	      if (hasOwnProperty.call(result, value)) {
	        result[value].push(key);
	      } else {
	        result[value] = [key];
	      }
	    }, getIteratee);

	    /**
	     * Invokes the method at `path` of `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path of the method to invoke.
	     * @param {...*} [args] The arguments to invoke the method with.
	     * @returns {*} Returns the result of the invoked method.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
	     *
	     * _.invoke(object, 'a[0].b.c.slice', 1, 3);
	     * // => [2, 3]
	     */
	    var invoke = rest(baseInvoke);

	    /**
	     * Creates an array of the own enumerable property names of `object`.
	     *
	     * **Note:** Non-object values are coerced to objects. See the
	     * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
	     * for more details.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property names.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.keys(new Foo);
	     * // => ['a', 'b'] (iteration order is not guaranteed)
	     *
	     * _.keys('hi');
	     * // => ['0', '1']
	     */
	    function keys(object) {
	      var isProto = isPrototype(object);
	      if (!(isProto || isArrayLike(object))) {
	        return baseKeys(object);
	      }
	      var indexes = indexKeys(object),
	          skipIndexes = !!indexes,
	          result = indexes || [],
	          length = result.length;

	      for (var key in object) {
	        if (baseHas(object, key) &&
	            !(skipIndexes && (key == 'length' || isIndex(key, length))) &&
	            !(isProto && key == 'constructor')) {
	          result.push(key);
	        }
	      }
	      return result;
	    }

	    /**
	     * Creates an array of the own and inherited enumerable property names of `object`.
	     *
	     * **Note:** Non-object values are coerced to objects.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Object
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property names.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.keysIn(new Foo);
	     * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
	     */
	    function keysIn(object) {
	      var index = -1,
	          isProto = isPrototype(object),
	          props = baseKeysIn(object),
	          propsLength = props.length,
	          indexes = indexKeys(object),
	          skipIndexes = !!indexes,
	          result = indexes || [],
	          length = result.length;

	      while (++index < propsLength) {
	        var key = props[index];
	        if (!(skipIndexes && (key == 'length' || isIndex(key, length))) &&
	            !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
	          result.push(key);
	        }
	      }
	      return result;
	    }

	    /**
	     * The opposite of `_.mapValues`; this method creates an object with the
	     * same values as `object` and keys generated by running each own enumerable
	     * string keyed property of `object` thru `iteratee`. The iteratee is invoked
	     * with three arguments: (value, key, object).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.8.0
	     * @category Object
	     * @param {Object} object The object to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Object} Returns the new mapped object.
	     * @example
	     *
	     * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
	     *   return key + value;
	     * });
	     * // => { 'a1': 1, 'b2': 2 }
	     */
	    function mapKeys(object, iteratee) {
	      var result = {};
	      iteratee = getIteratee(iteratee, 3);

	      baseForOwn(object, function(value, key, object) {
	        result[iteratee(value, key, object)] = value;
	      });
	      return result;
	    }

	    /**
	     * Creates an object with the same keys as `object` and values generated
	     * by running each own enumerable string keyed property of `object` thru
	     * `iteratee`. The iteratee is invoked with three arguments:
	     * (value, key, object).
	     *
	     * @static
	     * @memberOf _
	     * @since 2.4.0
	     * @category Object
	     * @param {Object} object The object to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The function invoked per iteration.
	     * @returns {Object} Returns the new mapped object.
	     * @example
	     *
	     * var users = {
	     *   'fred':    { 'user': 'fred',    'age': 40 },
	     *   'pebbles': { 'user': 'pebbles', 'age': 1 }
	     * };
	     *
	     * _.mapValues(users, function(o) { return o.age; });
	     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.mapValues(users, 'age');
	     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
	     */
	    function mapValues(object, iteratee) {
	      var result = {};
	      iteratee = getIteratee(iteratee, 3);

	      baseForOwn(object, function(value, key, object) {
	        result[key] = iteratee(value, key, object);
	      });
	      return result;
	    }

	    /**
	     * This method is like `_.assign` except that it recursively merges own and
	     * inherited enumerable string keyed properties of source objects into the
	     * destination object. Source properties that resolve to `undefined` are
	     * skipped if a destination value exists. Array and plain object properties
	     * are merged recursively.Other objects and value types are overridden by
	     * assignment. Source objects are applied from left to right. Subsequent
	     * sources overwrite property assignments of previous sources.
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.5.0
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} [sources] The source objects.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * var users = {
	     *   'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
	     * };
	     *
	     * var ages = {
	     *   'data': [{ 'age': 36 }, { 'age': 40 }]
	     * };
	     *
	     * _.merge(users, ages);
	     * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
	     */
	    var merge = createAssigner(function(object, source, srcIndex) {
	      baseMerge(object, source, srcIndex);
	    });

	    /**
	     * This method is like `_.merge` except that it accepts `customizer` which
	     * is invoked to produce the merged values of the destination and source
	     * properties. If `customizer` returns `undefined`, merging is handled by the
	     * method instead. The `customizer` is invoked with seven arguments:
	     * (objValue, srcValue, key, object, source, stack).
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The destination object.
	     * @param {...Object} sources The source objects.
	     * @param {Function} customizer The function to customize assigned values.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * function customizer(objValue, srcValue) {
	     *   if (_.isArray(objValue)) {
	     *     return objValue.concat(srcValue);
	     *   }
	     * }
	     *
	     * var object = {
	     *   'fruits': ['apple'],
	     *   'vegetables': ['beet']
	     * };
	     *
	     * var other = {
	     *   'fruits': ['banana'],
	     *   'vegetables': ['carrot']
	     * };
	     *
	     * _.mergeWith(object, other, customizer);
	     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
	     */
	    var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
	      baseMerge(object, source, srcIndex, customizer);
	    });

	    /**
	     * The opposite of `_.pick`; this method creates an object composed of the
	     * own and inherited enumerable string keyed properties of `object` that are
	     * not omitted.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The source object.
	     * @param {...(string|string[])} [props] The property identifiers to omit.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * var object = { 'a': 1, 'b': '2', 'c': 3 };
	     *
	     * _.omit(object, ['a', 'c']);
	     * // => { 'b': '2' }
	     */
	    var omit = rest(function(object, props) {
	      if (object == null) {
	        return {};
	      }
	      props = arrayMap(baseFlatten(props, 1), toKey);
	      return basePick(object, baseDifference(getAllKeysIn(object), props));
	    });

	    /**
	     * The opposite of `_.pickBy`; this method creates an object composed of
	     * the own and inherited enumerable string keyed properties of `object` that
	     * `predicate` doesn't return truthy for. The predicate is invoked with two
	     * arguments: (value, key).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The source object.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per property.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * var object = { 'a': 1, 'b': '2', 'c': 3 };
	     *
	     * _.omitBy(object, _.isNumber);
	     * // => { 'b': '2' }
	     */
	    function omitBy(object, predicate) {
	      predicate = getIteratee(predicate);
	      return basePickBy(object, function(value, key) {
	        return !predicate(value, key);
	      });
	    }

	    /**
	     * Creates an object composed of the picked `object` properties.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The source object.
	     * @param {...(string|string[])} [props] The property identifiers to pick.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * var object = { 'a': 1, 'b': '2', 'c': 3 };
	     *
	     * _.pick(object, ['a', 'c']);
	     * // => { 'a': 1, 'c': 3 }
	     */
	    var pick = rest(function(object, props) {
	      return object == null ? {} : basePick(object, baseFlatten(props, 1));
	    });

	    /**
	     * Creates an object composed of the `object` properties `predicate` returns
	     * truthy for. The predicate is invoked with two arguments: (value, key).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The source object.
	     * @param {Array|Function|Object|string} [predicate=_.identity]
	     *  The function invoked per property.
	     * @returns {Object} Returns the new object.
	     * @example
	     *
	     * var object = { 'a': 1, 'b': '2', 'c': 3 };
	     *
	     * _.pickBy(object, _.isNumber);
	     * // => { 'a': 1, 'c': 3 }
	     */
	    function pickBy(object, predicate) {
	      return object == null ? {} : basePickBy(object, getIteratee(predicate));
	    }

	    /**
	     * This method is like `_.get` except that if the resolved value is a
	     * function it's invoked with the `this` binding of its parent object and
	     * its result is returned.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The object to query.
	     * @param {Array|string} path The path of the property to resolve.
	     * @param {*} [defaultValue] The value returned for `undefined` resolved values.
	     * @returns {*} Returns the resolved value.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
	     *
	     * _.result(object, 'a[0].b.c1');
	     * // => 3
	     *
	     * _.result(object, 'a[0].b.c2');
	     * // => 4
	     *
	     * _.result(object, 'a[0].b.c3', 'default');
	     * // => 'default'
	     *
	     * _.result(object, 'a[0].b.c3', _.constant('default'));
	     * // => 'default'
	     */
	    function result(object, path, defaultValue) {
	      path = isKey(path, object) ? [path] : castPath(path);

	      var index = -1,
	          length = path.length;

	      // Ensure the loop is entered when path is empty.
	      if (!length) {
	        object = undefined;
	        length = 1;
	      }
	      while (++index < length) {
	        var value = object == null ? undefined : object[path[index]];
	        if (value === undefined) {
	          index = length;
	          value = defaultValue;
	        }
	        object = isFunction(value) ? value.call(object) : value;
	      }
	      return object;
	    }

	    /**
	     * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
	     * it's created. Arrays are created for missing index properties while objects
	     * are created for all other missing properties. Use `_.setWith` to customize
	     * `path` creation.
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.7.0
	     * @category Object
	     * @param {Object} object The object to modify.
	     * @param {Array|string} path The path of the property to set.
	     * @param {*} value The value to set.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
	     *
	     * _.set(object, 'a[0].b.c', 4);
	     * console.log(object.a[0].b.c);
	     * // => 4
	     *
	     * _.set(object, ['x', '0', 'y', 'z'], 5);
	     * console.log(object.x[0].y.z);
	     * // => 5
	     */
	    function set(object, path, value) {
	      return object == null ? object : baseSet(object, path, value);
	    }

	    /**
	     * This method is like `_.set` except that it accepts `customizer` which is
	     * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
	     * path creation is handled by the method instead. The `customizer` is invoked
	     * with three arguments: (nsValue, key, nsObject).
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The object to modify.
	     * @param {Array|string} path The path of the property to set.
	     * @param {*} value The value to set.
	     * @param {Function} [customizer] The function to customize assigned values.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * var object = {};
	     *
	     * _.setWith(object, '[0][1]', 'a', Object);
	     * // => { '0': { '1': 'a' } }
	     */
	    function setWith(object, path, value, customizer) {
	      customizer = typeof customizer == 'function' ? customizer : undefined;
	      return object == null ? object : baseSet(object, path, value, customizer);
	    }

	    /**
	     * Creates an array of own enumerable string keyed-value pairs for `object`
	     * which can be consumed by `_.fromPairs`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @alias entries
	     * @category Object
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the new array of key-value pairs.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.toPairs(new Foo);
	     * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
	     */
	    function toPairs(object) {
	      return baseToPairs(object, keys(object));
	    }

	    /**
	     * Creates an array of own and inherited enumerable string keyed-value pairs
	     * for `object` which can be consumed by `_.fromPairs`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @alias entriesIn
	     * @category Object
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the new array of key-value pairs.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.toPairsIn(new Foo);
	     * // => [['a', 1], ['b', 2], ['c', 1]] (iteration order is not guaranteed)
	     */
	    function toPairsIn(object) {
	      return baseToPairs(object, keysIn(object));
	    }

	    /**
	     * An alternative to `_.reduce`; this method transforms `object` to a new
	     * `accumulator` object which is the result of running each of its own
	     * enumerable string keyed properties thru `iteratee`, with each invocation
	     * potentially mutating the `accumulator` object. The iteratee is invoked
	     * with four arguments: (accumulator, value, key, object). Iteratee functions
	     * may exit iteration early by explicitly returning `false`.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.3.0
	     * @category Object
	     * @param {Array|Object} object The object to iterate over.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @param {*} [accumulator] The custom accumulator value.
	     * @returns {*} Returns the accumulated value.
	     * @example
	     *
	     * _.transform([2, 3, 4], function(result, n) {
	     *   result.push(n *= n);
	     *   return n % 2 == 0;
	     * }, []);
	     * // => [4, 9]
	     *
	     * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
	     *   (result[value] || (result[value] = [])).push(key);
	     * }, {});
	     * // => { '1': ['a', 'c'], '2': ['b'] }
	     */
	    function transform(object, iteratee, accumulator) {
	      var isArr = isArray(object) || isTypedArray(object);
	      iteratee = getIteratee(iteratee, 4);

	      if (accumulator == null) {
	        if (isArr || isObject(object)) {
	          var Ctor = object.constructor;
	          if (isArr) {
	            accumulator = isArray(object) ? new Ctor : [];
	          } else {
	            accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
	          }
	        } else {
	          accumulator = {};
	        }
	      }
	      (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
	        return iteratee(accumulator, value, index, object);
	      });
	      return accumulator;
	    }

	    /**
	     * Removes the property at `path` of `object`.
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Object
	     * @param {Object} object The object to modify.
	     * @param {Array|string} path The path of the property to unset.
	     * @returns {boolean} Returns `true` if the property is deleted, else `false`.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c': 7 } }] };
	     * _.unset(object, 'a[0].b.c');
	     * // => true
	     *
	     * console.log(object);
	     * // => { 'a': [{ 'b': {} }] };
	     *
	     * _.unset(object, ['a', '0', 'b', 'c']);
	     * // => true
	     *
	     * console.log(object);
	     * // => { 'a': [{ 'b': {} }] };
	     */
	    function unset(object, path) {
	      return object == null ? true : baseUnset(object, path);
	    }

	    /**
	     * This method is like `_.set` except that accepts `updater` to produce the
	     * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
	     * is invoked with one argument: (value).
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.6.0
	     * @category Object
	     * @param {Object} object The object to modify.
	     * @param {Array|string} path The path of the property to set.
	     * @param {Function} updater The function to produce the updated value.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
	     *
	     * _.update(object, 'a[0].b.c', function(n) { return n * n; });
	     * console.log(object.a[0].b.c);
	     * // => 9
	     *
	     * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
	     * console.log(object.x[0].y.z);
	     * // => 0
	     */
	    function update(object, path, updater) {
	      return object == null ? object : baseUpdate(object, path, castFunction(updater));
	    }

	    /**
	     * This method is like `_.update` except that it accepts `customizer` which is
	     * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
	     * path creation is handled by the method instead. The `customizer` is invoked
	     * with three arguments: (nsValue, key, nsObject).
	     *
	     * **Note:** This method mutates `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.6.0
	     * @category Object
	     * @param {Object} object The object to modify.
	     * @param {Array|string} path The path of the property to set.
	     * @param {Function} updater The function to produce the updated value.
	     * @param {Function} [customizer] The function to customize assigned values.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * var object = {};
	     *
	     * _.updateWith(object, '[0][1]', _.constant('a'), Object);
	     * // => { '0': { '1': 'a' } }
	     */
	    function updateWith(object, path, updater, customizer) {
	      customizer = typeof customizer == 'function' ? customizer : undefined;
	      return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
	    }

	    /**
	     * Creates an array of the own enumerable string keyed property values of `object`.
	     *
	     * **Note:** Non-object values are coerced to objects.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Object
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property values.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.values(new Foo);
	     * // => [1, 2] (iteration order is not guaranteed)
	     *
	     * _.values('hi');
	     * // => ['h', 'i']
	     */
	    function values(object) {
	      return object ? baseValues(object, keys(object)) : [];
	    }

	    /**
	     * Creates an array of the own and inherited enumerable string keyed property
	     * values of `object`.
	     *
	     * **Note:** Non-object values are coerced to objects.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Object
	     * @param {Object} object The object to query.
	     * @returns {Array} Returns the array of property values.
	     * @example
	     *
	     * function Foo() {
	     *   this.a = 1;
	     *   this.b = 2;
	     * }
	     *
	     * Foo.prototype.c = 3;
	     *
	     * _.valuesIn(new Foo);
	     * // => [1, 2, 3] (iteration order is not guaranteed)
	     */
	    function valuesIn(object) {
	      return object == null ? [] : baseValues(object, keysIn(object));
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Clamps `number` within the inclusive `lower` and `upper` bounds.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Number
	     * @param {number} number The number to clamp.
	     * @param {number} [lower] The lower bound.
	     * @param {number} upper The upper bound.
	     * @returns {number} Returns the clamped number.
	     * @example
	     *
	     * _.clamp(-10, -5, 5);
	     * // => -5
	     *
	     * _.clamp(10, -5, 5);
	     * // => 5
	     */
	    function clamp(number, lower, upper) {
	      if (upper === undefined) {
	        upper = lower;
	        lower = undefined;
	      }
	      if (upper !== undefined) {
	        upper = toNumber(upper);
	        upper = upper === upper ? upper : 0;
	      }
	      if (lower !== undefined) {
	        lower = toNumber(lower);
	        lower = lower === lower ? lower : 0;
	      }
	      return baseClamp(toNumber(number), lower, upper);
	    }

	    /**
	     * Checks if `n` is between `start` and up to but not including, `end`. If
	     * `end` is not specified, it's set to `start` with `start` then set to `0`.
	     * If `start` is greater than `end` the params are swapped to support
	     * negative ranges.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.3.0
	     * @category Number
	     * @param {number} number The number to check.
	     * @param {number} [start=0] The start of the range.
	     * @param {number} end The end of the range.
	     * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
	     * @example
	     *
	     * _.inRange(3, 2, 4);
	     * // => true
	     *
	     * _.inRange(4, 8);
	     * // => true
	     *
	     * _.inRange(4, 2);
	     * // => false
	     *
	     * _.inRange(2, 2);
	     * // => false
	     *
	     * _.inRange(1.2, 2);
	     * // => true
	     *
	     * _.inRange(5.2, 4);
	     * // => false
	     *
	     * _.inRange(-3, -2, -6);
	     * // => true
	     */
	    function inRange(number, start, end) {
	      start = toNumber(start) || 0;
	      if (end === undefined) {
	        end = start;
	        start = 0;
	      } else {
	        end = toNumber(end) || 0;
	      }
	      number = toNumber(number);
	      return baseInRange(number, start, end);
	    }

	    /**
	     * Produces a random number between the inclusive `lower` and `upper` bounds.
	     * If only one argument is provided a number between `0` and the given number
	     * is returned. If `floating` is `true`, or either `lower` or `upper` are
	     * floats, a floating-point number is returned instead of an integer.
	     *
	     * **Note:** JavaScript follows the IEEE-754 standard for resolving
	     * floating-point values which can produce unexpected results.
	     *
	     * @static
	     * @memberOf _
	     * @since 0.7.0
	     * @category Number
	     * @param {number} [lower=0] The lower bound.
	     * @param {number} [upper=1] The upper bound.
	     * @param {boolean} [floating] Specify returning a floating-point number.
	     * @returns {number} Returns the random number.
	     * @example
	     *
	     * _.random(0, 5);
	     * // => an integer between 0 and 5
	     *
	     * _.random(5);
	     * // => also an integer between 0 and 5
	     *
	     * _.random(5, true);
	     * // => a floating-point number between 0 and 5
	     *
	     * _.random(1.2, 5.2);
	     * // => a floating-point number between 1.2 and 5.2
	     */
	    function random(lower, upper, floating) {
	      if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
	        upper = floating = undefined;
	      }
	      if (floating === undefined) {
	        if (typeof upper == 'boolean') {
	          floating = upper;
	          upper = undefined;
	        }
	        else if (typeof lower == 'boolean') {
	          floating = lower;
	          lower = undefined;
	        }
	      }
	      if (lower === undefined && upper === undefined) {
	        lower = 0;
	        upper = 1;
	      }
	      else {
	        lower = toNumber(lower) || 0;
	        if (upper === undefined) {
	          upper = lower;
	          lower = 0;
	        } else {
	          upper = toNumber(upper) || 0;
	        }
	      }
	      if (lower > upper) {
	        var temp = lower;
	        lower = upper;
	        upper = temp;
	      }
	      if (floating || lower % 1 || upper % 1) {
	        var rand = nativeRandom();
	        return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
	      }
	      return baseRandom(lower, upper);
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the camel cased string.
	     * @example
	     *
	     * _.camelCase('Foo Bar');
	     * // => 'fooBar'
	     *
	     * _.camelCase('--foo-bar--');
	     * // => 'fooBar'
	     *
	     * _.camelCase('__FOO_BAR__');
	     * // => 'fooBar'
	     */
	    var camelCase = createCompounder(function(result, word, index) {
	      word = word.toLowerCase();
	      return result + (index ? capitalize(word) : word);
	    });

	    /**
	     * Converts the first character of `string` to upper case and the remaining
	     * to lower case.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to capitalize.
	     * @returns {string} Returns the capitalized string.
	     * @example
	     *
	     * _.capitalize('FRED');
	     * // => 'Fred'
	     */
	    function capitalize(string) {
	      return upperFirst(toString(string).toLowerCase());
	    }

	    /**
	     * Deburrs `string` by converting
	     * [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
	     * to basic latin letters and removing
	     * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to deburr.
	     * @returns {string} Returns the deburred string.
	     * @example
	     *
	     * _.deburr('déjà vu');
	     * // => 'deja vu'
	     */
	    function deburr(string) {
	      string = toString(string);
	      return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');
	    }

	    /**
	     * Checks if `string` ends with the given target string.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to search.
	     * @param {string} [target] The string to search for.
	     * @param {number} [position=string.length] The position to search from.
	     * @returns {boolean} Returns `true` if `string` ends with `target`,
	     *  else `false`.
	     * @example
	     *
	     * _.endsWith('abc', 'c');
	     * // => true
	     *
	     * _.endsWith('abc', 'b');
	     * // => false
	     *
	     * _.endsWith('abc', 'b', 2);
	     * // => true
	     */
	    function endsWith(string, target, position) {
	      string = toString(string);
	      target = typeof target == 'string' ? target : (target + '');

	      var length = string.length;
	      position = position === undefined
	        ? length
	        : baseClamp(toInteger(position), 0, length);

	      position -= target.length;
	      return position >= 0 && string.indexOf(target, position) == position;
	    }

	    /**
	     * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to
	     * their corresponding HTML entities.
	     *
	     * **Note:** No other characters are escaped. To escape additional
	     * characters use a third-party library like [_he_](https://mths.be/he).
	     *
	     * Though the ">" character is escaped for symmetry, characters like
	     * ">" and "/" don't need escaping in HTML and have no special meaning
	     * unless they're part of a tag or unquoted attribute value. See
	     * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
	     * (under "semi-related fun fact") for more details.
	     *
	     * Backticks are escaped because in IE < 9, they can break out of
	     * attribute values or HTML comments. See [#59](https://html5sec.org/#59),
	     * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and
	     * [#133](https://html5sec.org/#133) of the
	     * [HTML5 Security Cheatsheet](https://html5sec.org/) for more details.
	     *
	     * When working with HTML you should always
	     * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
	     * XSS vectors.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category String
	     * @param {string} [string=''] The string to escape.
	     * @returns {string} Returns the escaped string.
	     * @example
	     *
	     * _.escape('fred, barney, & pebbles');
	     * // => 'fred, barney, &amp; pebbles'
	     */
	    function escape(string) {
	      string = toString(string);
	      return (string && reHasUnescapedHtml.test(string))
	        ? string.replace(reUnescapedHtml, escapeHtmlChar)
	        : string;
	    }

	    /**
	     * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
	     * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to escape.
	     * @returns {string} Returns the escaped string.
	     * @example
	     *
	     * _.escapeRegExp('[lodash](https://lodash.com/)');
	     * // => '\[lodash\]\(https://lodash\.com/\)'
	     */
	    function escapeRegExp(string) {
	      string = toString(string);
	      return (string && reHasRegExpChar.test(string))
	        ? string.replace(reRegExpChar, '\\$&')
	        : string;
	    }

	    /**
	     * Converts `string` to
	     * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the kebab cased string.
	     * @example
	     *
	     * _.kebabCase('Foo Bar');
	     * // => 'foo-bar'
	     *
	     * _.kebabCase('fooBar');
	     * // => 'foo-bar'
	     *
	     * _.kebabCase('__FOO_BAR__');
	     * // => 'foo-bar'
	     */
	    var kebabCase = createCompounder(function(result, word, index) {
	      return result + (index ? '-' : '') + word.toLowerCase();
	    });

	    /**
	     * Converts `string`, as space separated words, to lower case.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the lower cased string.
	     * @example
	     *
	     * _.lowerCase('--Foo-Bar--');
	     * // => 'foo bar'
	     *
	     * _.lowerCase('fooBar');
	     * // => 'foo bar'
	     *
	     * _.lowerCase('__FOO_BAR__');
	     * // => 'foo bar'
	     */
	    var lowerCase = createCompounder(function(result, word, index) {
	      return result + (index ? ' ' : '') + word.toLowerCase();
	    });

	    /**
	     * Converts the first character of `string` to lower case.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the converted string.
	     * @example
	     *
	     * _.lowerFirst('Fred');
	     * // => 'fred'
	     *
	     * _.lowerFirst('FRED');
	     * // => 'fRED'
	     */
	    var lowerFirst = createCaseFirst('toLowerCase');

	    /**
	     * Pads `string` on the left and right sides if it's shorter than `length`.
	     * Padding characters are truncated if they can't be evenly divided by `length`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to pad.
	     * @param {number} [length=0] The padding length.
	     * @param {string} [chars=' '] The string used as padding.
	     * @returns {string} Returns the padded string.
	     * @example
	     *
	     * _.pad('abc', 8);
	     * // => '  abc   '
	     *
	     * _.pad('abc', 8, '_-');
	     * // => '_-abc_-_'
	     *
	     * _.pad('abc', 3);
	     * // => 'abc'
	     */
	    function pad(string, length, chars) {
	      string = toString(string);
	      length = toInteger(length);

	      var strLength = length ? stringSize(string) : 0;
	      if (!length || strLength >= length) {
	        return string;
	      }
	      var mid = (length - strLength) / 2;
	      return (
	        createPadding(nativeFloor(mid), chars) +
	        string +
	        createPadding(nativeCeil(mid), chars)
	      );
	    }

	    /**
	     * Pads `string` on the right side if it's shorter than `length`. Padding
	     * characters are truncated if they exceed `length`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to pad.
	     * @param {number} [length=0] The padding length.
	     * @param {string} [chars=' '] The string used as padding.
	     * @returns {string} Returns the padded string.
	     * @example
	     *
	     * _.padEnd('abc', 6);
	     * // => 'abc   '
	     *
	     * _.padEnd('abc', 6, '_-');
	     * // => 'abc_-_'
	     *
	     * _.padEnd('abc', 3);
	     * // => 'abc'
	     */
	    function padEnd(string, length, chars) {
	      string = toString(string);
	      length = toInteger(length);

	      var strLength = length ? stringSize(string) : 0;
	      return (length && strLength < length)
	        ? (string + createPadding(length - strLength, chars))
	        : string;
	    }

	    /**
	     * Pads `string` on the left side if it's shorter than `length`. Padding
	     * characters are truncated if they exceed `length`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to pad.
	     * @param {number} [length=0] The padding length.
	     * @param {string} [chars=' '] The string used as padding.
	     * @returns {string} Returns the padded string.
	     * @example
	     *
	     * _.padStart('abc', 6);
	     * // => '   abc'
	     *
	     * _.padStart('abc', 6, '_-');
	     * // => '_-_abc'
	     *
	     * _.padStart('abc', 3);
	     * // => 'abc'
	     */
	    function padStart(string, length, chars) {
	      string = toString(string);
	      length = toInteger(length);

	      var strLength = length ? stringSize(string) : 0;
	      return (length && strLength < length)
	        ? (createPadding(length - strLength, chars) + string)
	        : string;
	    }

	    /**
	     * Converts `string` to an integer of the specified radix. If `radix` is
	     * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
	     * hexadecimal, in which case a `radix` of `16` is used.
	     *
	     * **Note:** This method aligns with the
	     * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
	     *
	     * @static
	     * @memberOf _
	     * @since 1.1.0
	     * @category String
	     * @param {string} string The string to convert.
	     * @param {number} [radix=10] The radix to interpret `value` by.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {number} Returns the converted integer.
	     * @example
	     *
	     * _.parseInt('08');
	     * // => 8
	     *
	     * _.map(['6', '08', '10'], _.parseInt);
	     * // => [6, 8, 10]
	     */
	    function parseInt(string, radix, guard) {
	      // Chrome fails to trim leading <BOM> whitespace characters.
	      // See https://bugs.chromium.org/p/v8/issues/detail?id=3109 for more details.
	      if (guard || radix == null) {
	        radix = 0;
	      } else if (radix) {
	        radix = +radix;
	      }
	      string = toString(string).replace(reTrim, '');
	      return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));
	    }

	    /**
	     * Repeats the given string `n` times.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to repeat.
	     * @param {number} [n=1] The number of times to repeat the string.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {string} Returns the repeated string.
	     * @example
	     *
	     * _.repeat('*', 3);
	     * // => '***'
	     *
	     * _.repeat('abc', 2);
	     * // => 'abcabc'
	     *
	     * _.repeat('abc', 0);
	     * // => ''
	     */
	    function repeat(string, n, guard) {
	      if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
	        n = 1;
	      } else {
	        n = toInteger(n);
	      }
	      return baseRepeat(toString(string), n);
	    }

	    /**
	     * Replaces matches for `pattern` in `string` with `replacement`.
	     *
	     * **Note:** This method is based on
	     * [`String#replace`](https://mdn.io/String/replace).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to modify.
	     * @param {RegExp|string} pattern The pattern to replace.
	     * @param {Function|string} replacement The match replacement.
	     * @returns {string} Returns the modified string.
	     * @example
	     *
	     * _.replace('Hi Fred', 'Fred', 'Barney');
	     * // => 'Hi Barney'
	     */
	    function replace() {
	      var args = arguments,
	          string = toString(args[0]);

	      return args.length < 3 ? string : nativeReplace.call(string, args[1], args[2]);
	    }

	    /**
	     * Converts `string` to
	     * [snake case](https://en.wikipedia.org/wiki/Snake_case).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the snake cased string.
	     * @example
	     *
	     * _.snakeCase('Foo Bar');
	     * // => 'foo_bar'
	     *
	     * _.snakeCase('fooBar');
	     * // => 'foo_bar'
	     *
	     * _.snakeCase('--FOO-BAR--');
	     * // => 'foo_bar'
	     */
	    var snakeCase = createCompounder(function(result, word, index) {
	      return result + (index ? '_' : '') + word.toLowerCase();
	    });

	    /**
	     * Splits `string` by `separator`.
	     *
	     * **Note:** This method is based on
	     * [`String#split`](https://mdn.io/String/split).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to split.
	     * @param {RegExp|string} separator The separator pattern to split by.
	     * @param {number} [limit] The length to truncate results to.
	     * @returns {Array} Returns the new array of string segments.
	     * @example
	     *
	     * _.split('a-b-c', '-', 2);
	     * // => ['a', 'b']
	     */
	    function split(string, separator, limit) {
	      if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
	        separator = limit = undefined;
	      }
	      limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
	      if (!limit) {
	        return [];
	      }
	      string = toString(string);
	      if (string && (
	            typeof separator == 'string' ||
	            (separator != null && !isRegExp(separator))
	          )) {
	        separator += '';
	        if (separator == '' && reHasComplexSymbol.test(string)) {
	          return castSlice(stringToArray(string), 0, limit);
	        }
	      }
	      return nativeSplit.call(string, separator, limit);
	    }

	    /**
	     * Converts `string` to
	     * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
	     *
	     * @static
	     * @memberOf _
	     * @since 3.1.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the start cased string.
	     * @example
	     *
	     * _.startCase('--foo-bar--');
	     * // => 'Foo Bar'
	     *
	     * _.startCase('fooBar');
	     * // => 'Foo Bar'
	     *
	     * _.startCase('__FOO_BAR__');
	     * // => 'FOO BAR'
	     */
	    var startCase = createCompounder(function(result, word, index) {
	      return result + (index ? ' ' : '') + upperFirst(word);
	    });

	    /**
	     * Checks if `string` starts with the given target string.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to search.
	     * @param {string} [target] The string to search for.
	     * @param {number} [position=0] The position to search from.
	     * @returns {boolean} Returns `true` if `string` starts with `target`,
	     *  else `false`.
	     * @example
	     *
	     * _.startsWith('abc', 'a');
	     * // => true
	     *
	     * _.startsWith('abc', 'b');
	     * // => false
	     *
	     * _.startsWith('abc', 'b', 1);
	     * // => true
	     */
	    function startsWith(string, target, position) {
	      string = toString(string);
	      position = baseClamp(toInteger(position), 0, string.length);
	      return string.lastIndexOf(target, position) == position;
	    }

	    /**
	     * Creates a compiled template function that can interpolate data properties
	     * in "interpolate" delimiters, HTML-escape interpolated data properties in
	     * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
	     * properties may be accessed as free variables in the template. If a setting
	     * object is given, it takes precedence over `_.templateSettings` values.
	     *
	     * **Note:** In the development build `_.template` utilizes
	     * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
	     * for easier debugging.
	     *
	     * For more information on precompiling templates see
	     * [lodash's custom builds documentation](https://lodash.com/custom-builds).
	     *
	     * For more information on Chrome extension sandboxes see
	     * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category String
	     * @param {string} [string=''] The template string.
	     * @param {Object} [options={}] The options object.
	     * @param {RegExp} [options.escape=_.templateSettings.escape]
	     *  The HTML "escape" delimiter.
	     * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
	     *  The "evaluate" delimiter.
	     * @param {Object} [options.imports=_.templateSettings.imports]
	     *  An object to import into the template as free variables.
	     * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
	     *  The "interpolate" delimiter.
	     * @param {string} [options.sourceURL='lodash.templateSources[n]']
	     *  The sourceURL of the compiled template.
	     * @param {string} [options.variable='obj']
	     *  The data object variable name.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Function} Returns the compiled template function.
	     * @example
	     *
	     * // Use the "interpolate" delimiter to create a compiled template.
	     * var compiled = _.template('hello <%= user %>!');
	     * compiled({ 'user': 'fred' });
	     * // => 'hello fred!'
	     *
	     * // Use the HTML "escape" delimiter to escape data property values.
	     * var compiled = _.template('<b><%- value %></b>');
	     * compiled({ 'value': '<script>' });
	     * // => '<b>&lt;script&gt;</b>'
	     *
	     * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
	     * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
	     * compiled({ 'users': ['fred', 'barney'] });
	     * // => '<li>fred</li><li>barney</li>'
	     *
	     * // Use the internal `print` function in "evaluate" delimiters.
	     * var compiled = _.template('<% print("hello " + user); %>!');
	     * compiled({ 'user': 'barney' });
	     * // => 'hello barney!'
	     *
	     * // Use the ES delimiter as an alternative to the default "interpolate" delimiter.
	     * var compiled = _.template('hello ${ user }!');
	     * compiled({ 'user': 'pebbles' });
	     * // => 'hello pebbles!'
	     *
	     * // Use custom template delimiters.
	     * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
	     * var compiled = _.template('hello {{ user }}!');
	     * compiled({ 'user': 'mustache' });
	     * // => 'hello mustache!'
	     *
	     * // Use backslashes to treat delimiters as plain text.
	     * var compiled = _.template('<%= "\\<%- value %\\>" %>');
	     * compiled({ 'value': 'ignored' });
	     * // => '<%- value %>'
	     *
	     * // Use the `imports` option to import `jQuery` as `jq`.
	     * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
	     * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
	     * compiled({ 'users': ['fred', 'barney'] });
	     * // => '<li>fred</li><li>barney</li>'
	     *
	     * // Use the `sourceURL` option to specify a custom sourceURL for the template.
	     * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
	     * compiled(data);
	     * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
	     *
	     * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
	     * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
	     * compiled.source;
	     * // => function(data) {
	     * //   var __t, __p = '';
	     * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
	     * //   return __p;
	     * // }
	     *
	     * // Use the `source` property to inline compiled templates for meaningful
	     * // line numbers in error messages and stack traces.
	     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
	     *   var JST = {\
	     *     "main": ' + _.template(mainText).source + '\
	     *   };\
	     * ');
	     */
	    function template(string, options, guard) {
	      // Based on John Resig's `tmpl` implementation
	      // (http://ejohn.org/blog/javascript-micro-templating/)
	      // and Laura Doktorova's doT.js (https://github.com/olado/doT).
	      var settings = lodash.templateSettings;

	      if (guard && isIterateeCall(string, options, guard)) {
	        options = undefined;
	      }
	      string = toString(string);
	      options = assignInWith({}, options, settings, assignInDefaults);

	      var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
	          importsKeys = keys(imports),
	          importsValues = baseValues(imports, importsKeys);

	      var isEscaping,
	          isEvaluating,
	          index = 0,
	          interpolate = options.interpolate || reNoMatch,
	          source = "__p += '";

	      // Compile the regexp to match each delimiter.
	      var reDelimiters = RegExp(
	        (options.escape || reNoMatch).source + '|' +
	        interpolate.source + '|' +
	        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
	        (options.evaluate || reNoMatch).source + '|$'
	      , 'g');

	      // Use a sourceURL for easier debugging.
	      var sourceURL = '//# sourceURL=' +
	        ('sourceURL' in options
	          ? options.sourceURL
	          : ('lodash.templateSources[' + (++templateCounter) + ']')
	        ) + '\n';

	      string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
	        interpolateValue || (interpolateValue = esTemplateValue);

	        // Escape characters that can't be included in string literals.
	        source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);

	        // Replace delimiters with snippets.
	        if (escapeValue) {
	          isEscaping = true;
	          source += "' +\n__e(" + escapeValue + ") +\n'";
	        }
	        if (evaluateValue) {
	          isEvaluating = true;
	          source += "';\n" + evaluateValue + ";\n__p += '";
	        }
	        if (interpolateValue) {
	          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
	        }
	        index = offset + match.length;

	        // The JS engine embedded in Adobe products needs `match` returned in
	        // order to produce the correct `offset` value.
	        return match;
	      });

	      source += "';\n";

	      // If `variable` is not specified wrap a with-statement around the generated
	      // code to add the data object to the top of the scope chain.
	      var variable = options.variable;
	      if (!variable) {
	        source = 'with (obj) {\n' + source + '\n}\n';
	      }
	      // Cleanup code by stripping empty strings.
	      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
	        .replace(reEmptyStringMiddle, '$1')
	        .replace(reEmptyStringTrailing, '$1;');

	      // Frame code as the function body.
	      source = 'function(' + (variable || 'obj') + ') {\n' +
	        (variable
	          ? ''
	          : 'obj || (obj = {});\n'
	        ) +
	        "var __t, __p = ''" +
	        (isEscaping
	           ? ', __e = _.escape'
	           : ''
	        ) +
	        (isEvaluating
	          ? ', __j = Array.prototype.join;\n' +
	            "function print() { __p += __j.call(arguments, '') }\n"
	          : ';\n'
	        ) +
	        source +
	        'return __p\n}';

	      var result = attempt(function() {
	        return Function(importsKeys, sourceURL + 'return ' + source)
	          .apply(undefined, importsValues);
	      });

	      // Provide the compiled function's source by its `toString` method or
	      // the `source` property as a convenience for inlining compiled templates.
	      result.source = source;
	      if (isError(result)) {
	        throw result;
	      }
	      return result;
	    }

	    /**
	     * Converts `string`, as a whole, to lower case just like
	     * [String#toLowerCase](https://mdn.io/toLowerCase).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the lower cased string.
	     * @example
	     *
	     * _.toLower('--Foo-Bar--');
	     * // => '--foo-bar--'
	     *
	     * _.toLower('fooBar');
	     * // => 'foobar'
	     *
	     * _.toLower('__FOO_BAR__');
	     * // => '__foo_bar__'
	     */
	    function toLower(value) {
	      return toString(value).toLowerCase();
	    }

	    /**
	     * Converts `string`, as a whole, to upper case just like
	     * [String#toUpperCase](https://mdn.io/toUpperCase).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the upper cased string.
	     * @example
	     *
	     * _.toUpper('--foo-bar--');
	     * // => '--FOO-BAR--'
	     *
	     * _.toUpper('fooBar');
	     * // => 'FOOBAR'
	     *
	     * _.toUpper('__foo_bar__');
	     * // => '__FOO_BAR__'
	     */
	    function toUpper(value) {
	      return toString(value).toUpperCase();
	    }

	    /**
	     * Removes leading and trailing whitespace or specified characters from `string`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to trim.
	     * @param {string} [chars=whitespace] The characters to trim.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {string} Returns the trimmed string.
	     * @example
	     *
	     * _.trim('  abc  ');
	     * // => 'abc'
	     *
	     * _.trim('-_-abc-_-', '_-');
	     * // => 'abc'
	     *
	     * _.map(['  foo  ', '  bar  '], _.trim);
	     * // => ['foo', 'bar']
	     */
	    function trim(string, chars, guard) {
	      string = toString(string);
	      if (!string) {
	        return string;
	      }
	      if (guard || chars === undefined) {
	        return string.replace(reTrim, '');
	      }
	      if (!(chars += '')) {
	        return string;
	      }
	      var strSymbols = stringToArray(string),
	          chrSymbols = stringToArray(chars),
	          start = charsStartIndex(strSymbols, chrSymbols),
	          end = charsEndIndex(strSymbols, chrSymbols) + 1;

	      return castSlice(strSymbols, start, end).join('');
	    }

	    /**
	     * Removes trailing whitespace or specified characters from `string`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to trim.
	     * @param {string} [chars=whitespace] The characters to trim.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {string} Returns the trimmed string.
	     * @example
	     *
	     * _.trimEnd('  abc  ');
	     * // => '  abc'
	     *
	     * _.trimEnd('-_-abc-_-', '_-');
	     * // => '-_-abc'
	     */
	    function trimEnd(string, chars, guard) {
	      string = toString(string);
	      if (!string) {
	        return string;
	      }
	      if (guard || chars === undefined) {
	        return string.replace(reTrimEnd, '');
	      }
	      if (!(chars += '')) {
	        return string;
	      }
	      var strSymbols = stringToArray(string),
	          end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;

	      return castSlice(strSymbols, 0, end).join('');
	    }

	    /**
	     * Removes leading whitespace or specified characters from `string`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to trim.
	     * @param {string} [chars=whitespace] The characters to trim.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {string} Returns the trimmed string.
	     * @example
	     *
	     * _.trimStart('  abc  ');
	     * // => 'abc  '
	     *
	     * _.trimStart('-_-abc-_-', '_-');
	     * // => 'abc-_-'
	     */
	    function trimStart(string, chars, guard) {
	      string = toString(string);
	      if (!string) {
	        return string;
	      }
	      if (guard || chars === undefined) {
	        return string.replace(reTrimStart, '');
	      }
	      if (!(chars += '')) {
	        return string;
	      }
	      var strSymbols = stringToArray(string),
	          start = charsStartIndex(strSymbols, stringToArray(chars));

	      return castSlice(strSymbols, start).join('');
	    }

	    /**
	     * Truncates `string` if it's longer than the given maximum string length.
	     * The last characters of the truncated string are replaced with the omission
	     * string which defaults to "...".
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to truncate.
	     * @param {Object} [options={}] The options object.
	     * @param {number} [options.length=30] The maximum string length.
	     * @param {string} [options.omission='...'] The string to indicate text is omitted.
	     * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
	     * @returns {string} Returns the truncated string.
	     * @example
	     *
	     * _.truncate('hi-diddly-ho there, neighborino');
	     * // => 'hi-diddly-ho there, neighbo...'
	     *
	     * _.truncate('hi-diddly-ho there, neighborino', {
	     *   'length': 24,
	     *   'separator': ' '
	     * });
	     * // => 'hi-diddly-ho there,...'
	     *
	     * _.truncate('hi-diddly-ho there, neighborino', {
	     *   'length': 24,
	     *   'separator': /,? +/
	     * });
	     * // => 'hi-diddly-ho there...'
	     *
	     * _.truncate('hi-diddly-ho there, neighborino', {
	     *   'omission': ' [...]'
	     * });
	     * // => 'hi-diddly-ho there, neig [...]'
	     */
	    function truncate(string, options) {
	      var length = DEFAULT_TRUNC_LENGTH,
	          omission = DEFAULT_TRUNC_OMISSION;

	      if (isObject(options)) {
	        var separator = 'separator' in options ? options.separator : separator;
	        length = 'length' in options ? toInteger(options.length) : length;
	        omission = 'omission' in options ? toString(options.omission) : omission;
	      }
	      string = toString(string);

	      var strLength = string.length;
	      if (reHasComplexSymbol.test(string)) {
	        var strSymbols = stringToArray(string);
	        strLength = strSymbols.length;
	      }
	      if (length >= strLength) {
	        return string;
	      }
	      var end = length - stringSize(omission);
	      if (end < 1) {
	        return omission;
	      }
	      var result = strSymbols
	        ? castSlice(strSymbols, 0, end).join('')
	        : string.slice(0, end);

	      if (separator === undefined) {
	        return result + omission;
	      }
	      if (strSymbols) {
	        end += (result.length - end);
	      }
	      if (isRegExp(separator)) {
	        if (string.slice(end).search(separator)) {
	          var match,
	              substring = result;

	          if (!separator.global) {
	            separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
	          }
	          separator.lastIndex = 0;
	          while ((match = separator.exec(substring))) {
	            var newEnd = match.index;
	          }
	          result = result.slice(0, newEnd === undefined ? end : newEnd);
	        }
	      } else if (string.indexOf(separator, end) != end) {
	        var index = result.lastIndexOf(separator);
	        if (index > -1) {
	          result = result.slice(0, index);
	        }
	      }
	      return result + omission;
	    }

	    /**
	     * The inverse of `_.escape`; this method converts the HTML entities
	     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#39;`, and `&#96;` in `string` to
	     * their corresponding characters.
	     *
	     * **Note:** No other HTML entities are unescaped. To unescape additional
	     * HTML entities use a third-party library like [_he_](https://mths.be/he).
	     *
	     * @static
	     * @memberOf _
	     * @since 0.6.0
	     * @category String
	     * @param {string} [string=''] The string to unescape.
	     * @returns {string} Returns the unescaped string.
	     * @example
	     *
	     * _.unescape('fred, barney, &amp; pebbles');
	     * // => 'fred, barney, & pebbles'
	     */
	    function unescape(string) {
	      string = toString(string);
	      return (string && reHasEscapedHtml.test(string))
	        ? string.replace(reEscapedHtml, unescapeHtmlChar)
	        : string;
	    }

	    /**
	     * Converts `string`, as space separated words, to upper case.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the upper cased string.
	     * @example
	     *
	     * _.upperCase('--foo-bar');
	     * // => 'FOO BAR'
	     *
	     * _.upperCase('fooBar');
	     * // => 'FOO BAR'
	     *
	     * _.upperCase('__foo_bar__');
	     * // => 'FOO BAR'
	     */
	    var upperCase = createCompounder(function(result, word, index) {
	      return result + (index ? ' ' : '') + word.toUpperCase();
	    });

	    /**
	     * Converts the first character of `string` to upper case.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category String
	     * @param {string} [string=''] The string to convert.
	     * @returns {string} Returns the converted string.
	     * @example
	     *
	     * _.upperFirst('fred');
	     * // => 'Fred'
	     *
	     * _.upperFirst('FRED');
	     * // => 'FRED'
	     */
	    var upperFirst = createCaseFirst('toUpperCase');

	    /**
	     * Splits `string` into an array of its words.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category String
	     * @param {string} [string=''] The string to inspect.
	     * @param {RegExp|string} [pattern] The pattern to match words.
	     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
	     * @returns {Array} Returns the words of `string`.
	     * @example
	     *
	     * _.words('fred, barney, & pebbles');
	     * // => ['fred', 'barney', 'pebbles']
	     *
	     * _.words('fred, barney, & pebbles', /[^, ]+/g);
	     * // => ['fred', 'barney', '&', 'pebbles']
	     */
	    function words(string, pattern, guard) {
	      string = toString(string);
	      pattern = guard ? undefined : pattern;

	      if (pattern === undefined) {
	        pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord;
	      }
	      return string.match(pattern) || [];
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Attempts to invoke `func`, returning either the result or the caught error
	     * object. Any additional arguments are provided to `func` when it's invoked.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Util
	     * @param {Function} func The function to attempt.
	     * @param {...*} [args] The arguments to invoke `func` with.
	     * @returns {*} Returns the `func` result or error object.
	     * @example
	     *
	     * // Avoid throwing errors for invalid selectors.
	     * var elements = _.attempt(function(selector) {
	     *   return document.querySelectorAll(selector);
	     * }, '>_>');
	     *
	     * if (_.isError(elements)) {
	     *   elements = [];
	     * }
	     */
	    var attempt = rest(function(func, args) {
	      try {
	        return apply(func, undefined, args);
	      } catch (e) {
	        return isError(e) ? e : new Error(e);
	      }
	    });

	    /**
	     * Binds methods of an object to the object itself, overwriting the existing
	     * method.
	     *
	     * **Note:** This method doesn't set the "length" property of bound functions.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @param {Object} object The object to bind and assign the bound methods to.
	     * @param {...(string|string[])} methodNames The object method names to bind.
	     * @returns {Object} Returns `object`.
	     * @example
	     *
	     * var view = {
	     *   'label': 'docs',
	     *   'onClick': function() {
	     *     console.log('clicked ' + this.label);
	     *   }
	     * };
	     *
	     * _.bindAll(view, 'onClick');
	     * jQuery(element).on('click', view.onClick);
	     * // => Logs 'clicked docs' when clicked.
	     */
	    var bindAll = rest(function(object, methodNames) {
	      arrayEach(baseFlatten(methodNames, 1), function(key) {
	        object[key] = bind(object[key], object);
	      });
	      return object;
	    });

	    /**
	     * Creates a function that iterates over `pairs` and invokes the corresponding
	     * function of the first predicate to return truthy. The predicate-function
	     * pairs are invoked with the `this` binding and arguments of the created
	     * function.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {Array} pairs The predicate-function pairs.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var func = _.cond([
	     *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
	     *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
	     *   [_.constant(true),                _.constant('no match')]
	     * ]);
	     *
	     * func({ 'a': 1, 'b': 2 });
	     * // => 'matches A'
	     *
	     * func({ 'a': 0, 'b': 1 });
	     * // => 'matches B'
	     *
	     * func({ 'a': '1', 'b': '2' });
	     * // => 'no match'
	     */
	    function cond(pairs) {
	      var length = pairs ? pairs.length : 0,
	          toIteratee = getIteratee();

	      pairs = !length ? [] : arrayMap(pairs, function(pair) {
	        if (typeof pair[1] != 'function') {
	          throw new TypeError(FUNC_ERROR_TEXT);
	        }
	        return [toIteratee(pair[0]), pair[1]];
	      });

	      return rest(function(args) {
	        var index = -1;
	        while (++index < length) {
	          var pair = pairs[index];
	          if (apply(pair[0], this, args)) {
	            return apply(pair[1], this, args);
	          }
	        }
	      });
	    }

	    /**
	     * Creates a function that invokes the predicate properties of `source` with
	     * the corresponding property values of a given object, returning `true` if
	     * all predicates return truthy, else `false`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {Object} source The object of property predicates to conform to.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney', 'age': 36 },
	     *   { 'user': 'fred',   'age': 40 }
	     * ];
	     *
	     * _.filter(users, _.conforms({ 'age': _.partial(_.gt, _, 38) }));
	     * // => [{ 'user': 'fred', 'age': 40 }]
	     */
	    function conforms(source) {
	      return baseConforms(baseClone(source, true));
	    }

	    /**
	     * Creates a function that returns `value`.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.4.0
	     * @category Util
	     * @param {*} value The value to return from the new function.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var object = { 'user': 'fred' };
	     * var getter = _.constant(object);
	     *
	     * getter() === object;
	     * // => true
	     */
	    function constant(value) {
	      return function() {
	        return value;
	      };
	    }

	    /**
	     * Creates a function that returns the result of invoking the given functions
	     * with the `this` binding of the created function, where each successive
	     * invocation is supplied the return value of the previous.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Util
	     * @param {...(Function|Function[])} [funcs] Functions to invoke.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * function square(n) {
	     *   return n * n;
	     * }
	     *
	     * var addSquare = _.flow(_.add, square);
	     * addSquare(1, 2);
	     * // => 9
	     */
	    var flow = createFlow();

	    /**
	     * This method is like `_.flow` except that it creates a function that
	     * invokes the given functions from right to left.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @param {...(Function|Function[])} [funcs] Functions to invoke.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * function square(n) {
	     *   return n * n;
	     * }
	     *
	     * var addSquare = _.flowRight(square, _.add);
	     * addSquare(1, 2);
	     * // => 9
	     */
	    var flowRight = createFlow(true);

	    /**
	     * This method returns the first argument given to it.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @param {*} value Any value.
	     * @returns {*} Returns `value`.
	     * @example
	     *
	     * var object = { 'user': 'fred' };
	     *
	     * _.identity(object) === object;
	     * // => true
	     */
	    function identity(value) {
	      return value;
	    }

	    /**
	     * Creates a function that invokes `func` with the arguments of the created
	     * function. If `func` is a property name, the created function returns the
	     * property value for a given element. If `func` is an array or object, the
	     * created function returns `true` for elements that contain the equivalent
	     * source properties, otherwise it returns `false`.
	     *
	     * @static
	     * @since 4.0.0
	     * @memberOf _
	     * @category Util
	     * @param {*} [func=_.identity] The value to convert to a callback.
	     * @returns {Function} Returns the callback.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney', 'age': 36, 'active': true },
	     *   { 'user': 'fred',   'age': 40, 'active': false }
	     * ];
	     *
	     * // The `_.matches` iteratee shorthand.
	     * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
	     * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
	     *
	     * // The `_.matchesProperty` iteratee shorthand.
	     * _.filter(users, _.iteratee(['user', 'fred']));
	     * // => [{ 'user': 'fred', 'age': 40 }]
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.map(users, _.iteratee('user'));
	     * // => ['barney', 'fred']
	     *
	     * // Create custom iteratee shorthands.
	     * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
	     *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
	     *     return func.test(string);
	     *   };
	     * });
	     *
	     * _.filter(['abc', 'def'], /ef/);
	     * // => ['def']
	     */
	    function iteratee(func) {
	      return baseIteratee(typeof func == 'function' ? func : baseClone(func, true));
	    }

	    /**
	     * Creates a function that performs a partial deep comparison between a given
	     * object and `source`, returning `true` if the given object has equivalent
	     * property values, else `false`. The created function is equivalent to
	     * `_.isMatch` with a `source` partially applied.
	     *
	     * **Note:** This method supports comparing the same values as `_.isEqual`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Util
	     * @param {Object} source The object of property values to match.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney', 'age': 36, 'active': true },
	     *   { 'user': 'fred',   'age': 40, 'active': false }
	     * ];
	     *
	     * _.filter(users, _.matches({ 'age': 40, 'active': false }));
	     * // => [{ 'user': 'fred', 'age': 40, 'active': false }]
	     */
	    function matches(source) {
	      return baseMatches(baseClone(source, true));
	    }

	    /**
	     * Creates a function that performs a partial deep comparison between the
	     * value at `path` of a given object to `srcValue`, returning `true` if the
	     * object value is equivalent, else `false`.
	     *
	     * **Note:** This method supports comparing the same values as `_.isEqual`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.2.0
	     * @category Util
	     * @param {Array|string} path The path of the property to get.
	     * @param {*} srcValue The value to match.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var users = [
	     *   { 'user': 'barney' },
	     *   { 'user': 'fred' }
	     * ];
	     *
	     * _.find(users, _.matchesProperty('user', 'fred'));
	     * // => { 'user': 'fred' }
	     */
	    function matchesProperty(path, srcValue) {
	      return baseMatchesProperty(path, baseClone(srcValue, true));
	    }

	    /**
	     * Creates a function that invokes the method at `path` of a given object.
	     * Any additional arguments are provided to the invoked method.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.7.0
	     * @category Util
	     * @param {Array|string} path The path of the method to invoke.
	     * @param {...*} [args] The arguments to invoke the method with.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var objects = [
	     *   { 'a': { 'b': _.constant(2) } },
	     *   { 'a': { 'b': _.constant(1) } }
	     * ];
	     *
	     * _.map(objects, _.method('a.b'));
	     * // => [2, 1]
	     *
	     * _.map(objects, _.method(['a', 'b']));
	     * // => [2, 1]
	     */
	    var method = rest(function(path, args) {
	      return function(object) {
	        return baseInvoke(object, path, args);
	      };
	    });

	    /**
	     * The opposite of `_.method`; this method creates a function that invokes
	     * the method at a given path of `object`. Any additional arguments are
	     * provided to the invoked method.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.7.0
	     * @category Util
	     * @param {Object} object The object to query.
	     * @param {...*} [args] The arguments to invoke the method with.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var array = _.times(3, _.constant),
	     *     object = { 'a': array, 'b': array, 'c': array };
	     *
	     * _.map(['a[2]', 'c[0]'], _.methodOf(object));
	     * // => [2, 0]
	     *
	     * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
	     * // => [2, 0]
	     */
	    var methodOf = rest(function(object, args) {
	      return function(path) {
	        return baseInvoke(object, path, args);
	      };
	    });

	    /**
	     * Adds all own enumerable string keyed function properties of a source
	     * object to the destination object. If `object` is a function, then methods
	     * are added to its prototype as well.
	     *
	     * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
	     * avoid conflicts caused by modifying the original.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @param {Function|Object} [object=lodash] The destination object.
	     * @param {Object} source The object of functions to add.
	     * @param {Object} [options={}] The options object.
	     * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
	     * @returns {Function|Object} Returns `object`.
	     * @example
	     *
	     * function vowels(string) {
	     *   return _.filter(string, function(v) {
	     *     return /[aeiou]/i.test(v);
	     *   });
	     * }
	     *
	     * _.mixin({ 'vowels': vowels });
	     * _.vowels('fred');
	     * // => ['e']
	     *
	     * _('fred').vowels().value();
	     * // => ['e']
	     *
	     * _.mixin({ 'vowels': vowels }, { 'chain': false });
	     * _('fred').vowels();
	     * // => ['e']
	     */
	    function mixin(object, source, options) {
	      var props = keys(source),
	          methodNames = baseFunctions(source, props);

	      if (options == null &&
	          !(isObject(source) && (methodNames.length || !props.length))) {
	        options = source;
	        source = object;
	        object = this;
	        methodNames = baseFunctions(source, keys(source));
	      }
	      var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
	          isFunc = isFunction(object);

	      arrayEach(methodNames, function(methodName) {
	        var func = source[methodName];
	        object[methodName] = func;
	        if (isFunc) {
	          object.prototype[methodName] = function() {
	            var chainAll = this.__chain__;
	            if (chain || chainAll) {
	              var result = object(this.__wrapped__),
	                  actions = result.__actions__ = copyArray(this.__actions__);

	              actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
	              result.__chain__ = chainAll;
	              return result;
	            }
	            return func.apply(object, arrayPush([this.value()], arguments));
	          };
	        }
	      });

	      return object;
	    }

	    /**
	     * Reverts the `_` variable to its previous value and returns a reference to
	     * the `lodash` function.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @returns {Function} Returns the `lodash` function.
	     * @example
	     *
	     * var lodash = _.noConflict();
	     */
	    function noConflict() {
	      if (root._ === this) {
	        root._ = oldDash;
	      }
	      return this;
	    }

	    /**
	     * A no-operation function that returns `undefined` regardless of the
	     * arguments it receives.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.3.0
	     * @category Util
	     * @example
	     *
	     * var object = { 'user': 'fred' };
	     *
	     * _.noop(object) === undefined;
	     * // => true
	     */
	    function noop() {
	      // No operation performed.
	    }

	    /**
	     * Creates a function that returns its nth argument. If `n` is negative,
	     * the nth argument from the end is returned.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {number} [n=0] The index of the argument to return.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var func = _.nthArg(1);
	     * func('a', 'b', 'c', 'd');
	     * // => 'b'
	     *
	     * var func = _.nthArg(-2);
	     * func('a', 'b', 'c', 'd');
	     * // => 'c'
	     */
	    function nthArg(n) {
	      n = toInteger(n);
	      return rest(function(args) {
	        return baseNth(args, n);
	      });
	    }

	    /**
	     * Creates a function that invokes `iteratees` with the arguments it receives
	     * and returns their results.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])}
	     *  [iteratees=[_.identity]] The iteratees to invoke.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var func = _.over(Math.max, Math.min);
	     *
	     * func(1, 2, 3, 4);
	     * // => [4, 1]
	     */
	    var over = createOver(arrayMap);

	    /**
	     * Creates a function that checks if **all** of the `predicates` return
	     * truthy when invoked with the arguments it receives.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])}
	     *  [predicates=[_.identity]] The predicates to check.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var func = _.overEvery(Boolean, isFinite);
	     *
	     * func('1');
	     * // => true
	     *
	     * func(null);
	     * // => false
	     *
	     * func(NaN);
	     * // => false
	     */
	    var overEvery = createOver(arrayEvery);

	    /**
	     * Creates a function that checks if **any** of the `predicates` return
	     * truthy when invoked with the arguments it receives.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])}
	     *  [predicates=[_.identity]] The predicates to check.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var func = _.overSome(Boolean, isFinite);
	     *
	     * func('1');
	     * // => true
	     *
	     * func(null);
	     * // => true
	     *
	     * func(NaN);
	     * // => false
	     */
	    var overSome = createOver(arraySome);

	    /**
	     * Creates a function that returns the value at `path` of a given object.
	     *
	     * @static
	     * @memberOf _
	     * @since 2.4.0
	     * @category Util
	     * @param {Array|string} path The path of the property to get.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var objects = [
	     *   { 'a': { 'b': 2 } },
	     *   { 'a': { 'b': 1 } }
	     * ];
	     *
	     * _.map(objects, _.property('a.b'));
	     * // => [2, 1]
	     *
	     * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
	     * // => [1, 2]
	     */
	    function property(path) {
	      return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
	    }

	    /**
	     * The opposite of `_.property`; this method creates a function that returns
	     * the value at a given path of `object`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.0.0
	     * @category Util
	     * @param {Object} object The object to query.
	     * @returns {Function} Returns the new function.
	     * @example
	     *
	     * var array = [0, 1, 2],
	     *     object = { 'a': array, 'b': array, 'c': array };
	     *
	     * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
	     * // => [2, 0]
	     *
	     * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
	     * // => [2, 0]
	     */
	    function propertyOf(object) {
	      return function(path) {
	        return object == null ? undefined : baseGet(object, path);
	      };
	    }

	    /**
	     * Creates an array of numbers (positive and/or negative) progressing from
	     * `start` up to, but not including, `end`. A step of `-1` is used if a negative
	     * `start` is specified without an `end` or `step`. If `end` is not specified,
	     * it's set to `start` with `start` then set to `0`.
	     *
	     * **Note:** JavaScript follows the IEEE-754 standard for resolving
	     * floating-point values which can produce unexpected results.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @param {number} [start=0] The start of the range.
	     * @param {number} end The end of the range.
	     * @param {number} [step=1] The value to increment or decrement by.
	     * @returns {Array} Returns the new array of numbers.
	     * @example
	     *
	     * _.range(4);
	     * // => [0, 1, 2, 3]
	     *
	     * _.range(-4);
	     * // => [0, -1, -2, -3]
	     *
	     * _.range(1, 5);
	     * // => [1, 2, 3, 4]
	     *
	     * _.range(0, 20, 5);
	     * // => [0, 5, 10, 15]
	     *
	     * _.range(0, -4, -1);
	     * // => [0, -1, -2, -3]
	     *
	     * _.range(1, 4, 0);
	     * // => [1, 1, 1]
	     *
	     * _.range(0);
	     * // => []
	     */
	    var range = createRange();

	    /**
	     * This method is like `_.range` except that it populates values in
	     * descending order.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {number} [start=0] The start of the range.
	     * @param {number} end The end of the range.
	     * @param {number} [step=1] The value to increment or decrement by.
	     * @returns {Array} Returns the new array of numbers.
	     * @example
	     *
	     * _.rangeRight(4);
	     * // => [3, 2, 1, 0]
	     *
	     * _.rangeRight(-4);
	     * // => [-3, -2, -1, 0]
	     *
	     * _.rangeRight(1, 5);
	     * // => [4, 3, 2, 1]
	     *
	     * _.rangeRight(0, 20, 5);
	     * // => [15, 10, 5, 0]
	     *
	     * _.rangeRight(0, -4, -1);
	     * // => [-3, -2, -1, 0]
	     *
	     * _.rangeRight(1, 4, 0);
	     * // => [1, 1, 1]
	     *
	     * _.rangeRight(0);
	     * // => []
	     */
	    var rangeRight = createRange(true);

	    /**
	     * Invokes the iteratee `n` times, returning an array of the results of
	     * each invocation. The iteratee is invoked with one argument; (index).
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @param {number} n The number of times to invoke `iteratee`.
	     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	     * @returns {Array} Returns the array of results.
	     * @example
	     *
	     * _.times(3, String);
	     * // => ['0', '1', '2']
	     *
	     *  _.times(4, _.constant(true));
	     * // => [true, true, true, true]
	     */
	    function times(n, iteratee) {
	      n = toInteger(n);
	      if (n < 1 || n > MAX_SAFE_INTEGER) {
	        return [];
	      }
	      var index = MAX_ARRAY_LENGTH,
	          length = nativeMin(n, MAX_ARRAY_LENGTH);

	      iteratee = getIteratee(iteratee);
	      n -= MAX_ARRAY_LENGTH;

	      var result = baseTimes(length, iteratee);
	      while (++index < n) {
	        iteratee(index);
	      }
	      return result;
	    }

	    /**
	     * Converts `value` to a property path array.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Util
	     * @param {*} value The value to convert.
	     * @returns {Array} Returns the new property path array.
	     * @example
	     *
	     * _.toPath('a.b.c');
	     * // => ['a', 'b', 'c']
	     *
	     * _.toPath('a[0].b.c');
	     * // => ['a', '0', 'b', 'c']
	     *
	     * var path = ['a', 'b', 'c'],
	     *     newPath = _.toPath(path);
	     *
	     * console.log(newPath);
	     * // => ['a', 'b', 'c']
	     *
	     * console.log(path === newPath);
	     * // => false
	     */
	    function toPath(value) {
	      if (isArray(value)) {
	        return arrayMap(value, toKey);
	      }
	      return isSymbol(value) ? [value] : copyArray(stringToPath(value));
	    }

	    /**
	     * Generates a unique ID. If `prefix` is given, the ID is appended to it.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Util
	     * @param {string} [prefix=''] The value to prefix the ID with.
	     * @returns {string} Returns the unique ID.
	     * @example
	     *
	     * _.uniqueId('contact_');
	     * // => 'contact_104'
	     *
	     * _.uniqueId();
	     * // => '105'
	     */
	    function uniqueId(prefix) {
	      var id = ++idCounter;
	      return toString(prefix) + id;
	    }

	    /*------------------------------------------------------------------------*/

	    /**
	     * Adds two numbers.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.4.0
	     * @category Math
	     * @param {number} augend The first number in an addition.
	     * @param {number} addend The second number in an addition.
	     * @returns {number} Returns the total.
	     * @example
	     *
	     * _.add(6, 4);
	     * // => 10
	     */
	    var add = createMathOperation(function(augend, addend) {
	      return augend + addend;
	    });

	    /**
	     * Computes `number` rounded up to `precision`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.10.0
	     * @category Math
	     * @param {number} number The number to round up.
	     * @param {number} [precision=0] The precision to round up to.
	     * @returns {number} Returns the rounded up number.
	     * @example
	     *
	     * _.ceil(4.006);
	     * // => 5
	     *
	     * _.ceil(6.004, 2);
	     * // => 6.01
	     *
	     * _.ceil(6040, -2);
	     * // => 6100
	     */
	    var ceil = createRound('ceil');

	    /**
	     * Divide two numbers.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.7.0
	     * @category Math
	     * @param {number} dividend The first number in a division.
	     * @param {number} divisor The second number in a division.
	     * @returns {number} Returns the quotient.
	     * @example
	     *
	     * _.divide(6, 4);
	     * // => 1.5
	     */
	    var divide = createMathOperation(function(dividend, divisor) {
	      return dividend / divisor;
	    });

	    /**
	     * Computes `number` rounded down to `precision`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.10.0
	     * @category Math
	     * @param {number} number The number to round down.
	     * @param {number} [precision=0] The precision to round down to.
	     * @returns {number} Returns the rounded down number.
	     * @example
	     *
	     * _.floor(4.006);
	     * // => 4
	     *
	     * _.floor(0.046, 2);
	     * // => 0.04
	     *
	     * _.floor(4060, -2);
	     * // => 4000
	     */
	    var floor = createRound('floor');

	    /**
	     * Computes the maximum value of `array`. If `array` is empty or falsey,
	     * `undefined` is returned.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @returns {*} Returns the maximum value.
	     * @example
	     *
	     * _.max([4, 2, 8, 6]);
	     * // => 8
	     *
	     * _.max([]);
	     * // => undefined
	     */
	    function max(array) {
	      return (array && array.length)
	        ? baseExtremum(array, identity, gt)
	        : undefined;
	    }

	    /**
	     * This method is like `_.max` except that it accepts `iteratee` which is
	     * invoked for each element in `array` to generate the criterion by which
	     * the value is ranked. The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {*} Returns the maximum value.
	     * @example
	     *
	     * var objects = [{ 'n': 1 }, { 'n': 2 }];
	     *
	     * _.maxBy(objects, function(o) { return o.n; });
	     * // => { 'n': 2 }
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.maxBy(objects, 'n');
	     * // => { 'n': 2 }
	     */
	    function maxBy(array, iteratee) {
	      return (array && array.length)
	        ? baseExtremum(array, getIteratee(iteratee), gt)
	        : undefined;
	    }

	    /**
	     * Computes the mean of the values in `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @returns {number} Returns the mean.
	     * @example
	     *
	     * _.mean([4, 2, 8, 6]);
	     * // => 5
	     */
	    function mean(array) {
	      return baseMean(array, identity);
	    }

	    /**
	     * This method is like `_.mean` except that it accepts `iteratee` which is
	     * invoked for each element in `array` to generate the value to be averaged.
	     * The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.7.0
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {number} Returns the mean.
	     * @example
	     *
	     * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
	     *
	     * _.meanBy(objects, function(o) { return o.n; });
	     * // => 5
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.meanBy(objects, 'n');
	     * // => 5
	     */
	    function meanBy(array, iteratee) {
	      return baseMean(array, getIteratee(iteratee));
	    }

	    /**
	     * Computes the minimum value of `array`. If `array` is empty or falsey,
	     * `undefined` is returned.
	     *
	     * @static
	     * @since 0.1.0
	     * @memberOf _
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @returns {*} Returns the minimum value.
	     * @example
	     *
	     * _.min([4, 2, 8, 6]);
	     * // => 2
	     *
	     * _.min([]);
	     * // => undefined
	     */
	    function min(array) {
	      return (array && array.length)
	        ? baseExtremum(array, identity, lt)
	        : undefined;
	    }

	    /**
	     * This method is like `_.min` except that it accepts `iteratee` which is
	     * invoked for each element in `array` to generate the criterion by which
	     * the value is ranked. The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {*} Returns the minimum value.
	     * @example
	     *
	     * var objects = [{ 'n': 1 }, { 'n': 2 }];
	     *
	     * _.minBy(objects, function(o) { return o.n; });
	     * // => { 'n': 1 }
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.minBy(objects, 'n');
	     * // => { 'n': 1 }
	     */
	    function minBy(array, iteratee) {
	      return (array && array.length)
	        ? baseExtremum(array, getIteratee(iteratee), lt)
	        : undefined;
	    }

	    /**
	     * Multiply two numbers.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.7.0
	     * @category Math
	     * @param {number} multiplier The first number in a multiplication.
	     * @param {number} multiplicand The second number in a multiplication.
	     * @returns {number} Returns the product.
	     * @example
	     *
	     * _.multiply(6, 4);
	     * // => 24
	     */
	    var multiply = createMathOperation(function(multiplier, multiplicand) {
	      return multiplier * multiplicand;
	    });

	    /**
	     * Computes `number` rounded to `precision`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.10.0
	     * @category Math
	     * @param {number} number The number to round.
	     * @param {number} [precision=0] The precision to round to.
	     * @returns {number} Returns the rounded number.
	     * @example
	     *
	     * _.round(4.006);
	     * // => 4
	     *
	     * _.round(4.006, 2);
	     * // => 4.01
	     *
	     * _.round(4060, -2);
	     * // => 4100
	     */
	    var round = createRound('round');

	    /**
	     * Subtract two numbers.
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Math
	     * @param {number} minuend The first number in a subtraction.
	     * @param {number} subtrahend The second number in a subtraction.
	     * @returns {number} Returns the difference.
	     * @example
	     *
	     * _.subtract(6, 4);
	     * // => 2
	     */
	    var subtract = createMathOperation(function(minuend, subtrahend) {
	      return minuend - subtrahend;
	    });

	    /**
	     * Computes the sum of the values in `array`.
	     *
	     * @static
	     * @memberOf _
	     * @since 3.4.0
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @returns {number} Returns the sum.
	     * @example
	     *
	     * _.sum([4, 2, 8, 6]);
	     * // => 20
	     */
	    function sum(array) {
	      return (array && array.length)
	        ? baseSum(array, identity)
	        : 0;
	    }

	    /**
	     * This method is like `_.sum` except that it accepts `iteratee` which is
	     * invoked for each element in `array` to generate the value to be summed.
	     * The iteratee is invoked with one argument: (value).
	     *
	     * @static
	     * @memberOf _
	     * @since 4.0.0
	     * @category Math
	     * @param {Array} array The array to iterate over.
	     * @param {Array|Function|Object|string} [iteratee=_.identity]
	     *  The iteratee invoked per element.
	     * @returns {number} Returns the sum.
	     * @example
	     *
	     * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
	     *
	     * _.sumBy(objects, function(o) { return o.n; });
	     * // => 20
	     *
	     * // The `_.property` iteratee shorthand.
	     * _.sumBy(objects, 'n');
	     * // => 20
	     */
	    function sumBy(array, iteratee) {
	      return (array && array.length)
	        ? baseSum(array, getIteratee(iteratee))
	        : 0;
	    }

	    /*------------------------------------------------------------------------*/

	    // Add methods that return wrapped values in chain sequences.
	    lodash.after = after;
	    lodash.ary = ary;
	    lodash.assign = assign;
	    lodash.assignIn = assignIn;
	    lodash.assignInWith = assignInWith;
	    lodash.assignWith = assignWith;
	    lodash.at = at;
	    lodash.before = before;
	    lodash.bind = bind;
	    lodash.bindAll = bindAll;
	    lodash.bindKey = bindKey;
	    lodash.castArray = castArray;
	    lodash.chain = chain;
	    lodash.chunk = chunk;
	    lodash.compact = compact;
	    lodash.concat = concat;
	    lodash.cond = cond;
	    lodash.conforms = conforms;
	    lodash.constant = constant;
	    lodash.countBy = countBy;
	    lodash.create = create;
	    lodash.curry = curry;
	    lodash.curryRight = curryRight;
	    lodash.debounce = debounce;
	    lodash.defaults = defaults;
	    lodash.defaultsDeep = defaultsDeep;
	    lodash.defer = defer;
	    lodash.delay = delay;
	    lodash.difference = difference;
	    lodash.differenceBy = differenceBy;
	    lodash.differenceWith = differenceWith;
	    lodash.drop = drop;
	    lodash.dropRight = dropRight;
	    lodash.dropRightWhile = dropRightWhile;
	    lodash.dropWhile = dropWhile;
	    lodash.fill = fill;
	    lodash.filter = filter;
	    lodash.flatMap = flatMap;
	    lodash.flatMapDeep = flatMapDeep;
	    lodash.flatMapDepth = flatMapDepth;
	    lodash.flatten = flatten;
	    lodash.flattenDeep = flattenDeep;
	    lodash.flattenDepth = flattenDepth;
	    lodash.flip = flip;
	    lodash.flow = flow;
	    lodash.flowRight = flowRight;
	    lodash.fromPairs = fromPairs;
	    lodash.functions = functions;
	    lodash.functionsIn = functionsIn;
	    lodash.groupBy = groupBy;
	    lodash.initial = initial;
	    lodash.intersection = intersection;
	    lodash.intersectionBy = intersectionBy;
	    lodash.intersectionWith = intersectionWith;
	    lodash.invert = invert;
	    lodash.invertBy = invertBy;
	    lodash.invokeMap = invokeMap;
	    lodash.iteratee = iteratee;
	    lodash.keyBy = keyBy;
	    lodash.keys = keys;
	    lodash.keysIn = keysIn;
	    lodash.map = map;
	    lodash.mapKeys = mapKeys;
	    lodash.mapValues = mapValues;
	    lodash.matches = matches;
	    lodash.matchesProperty = matchesProperty;
	    lodash.memoize = memoize;
	    lodash.merge = merge;
	    lodash.mergeWith = mergeWith;
	    lodash.method = method;
	    lodash.methodOf = methodOf;
	    lodash.mixin = mixin;
	    lodash.negate = negate;
	    lodash.nthArg = nthArg;
	    lodash.omit = omit;
	    lodash.omitBy = omitBy;
	    lodash.once = once;
	    lodash.orderBy = orderBy;
	    lodash.over = over;
	    lodash.overArgs = overArgs;
	    lodash.overEvery = overEvery;
	    lodash.overSome = overSome;
	    lodash.partial = partial;
	    lodash.partialRight = partialRight;
	    lodash.partition = partition;
	    lodash.pick = pick;
	    lodash.pickBy = pickBy;
	    lodash.property = property;
	    lodash.propertyOf = propertyOf;
	    lodash.pull = pull;
	    lodash.pullAll = pullAll;
	    lodash.pullAllBy = pullAllBy;
	    lodash.pullAllWith = pullAllWith;
	    lodash.pullAt = pullAt;
	    lodash.range = range;
	    lodash.rangeRight = rangeRight;
	    lodash.rearg = rearg;
	    lodash.reject = reject;
	    lodash.remove = remove;
	    lodash.rest = rest;
	    lodash.reverse = reverse;
	    lodash.sampleSize = sampleSize;
	    lodash.set = set;
	    lodash.setWith = setWith;
	    lodash.shuffle = shuffle;
	    lodash.slice = slice;
	    lodash.sortBy = sortBy;
	    lodash.sortedUniq = sortedUniq;
	    lodash.sortedUniqBy = sortedUniqBy;
	    lodash.split = split;
	    lodash.spread = spread;
	    lodash.tail = tail;
	    lodash.take = take;
	    lodash.takeRight = takeRight;
	    lodash.takeRightWhile = takeRightWhile;
	    lodash.takeWhile = takeWhile;
	    lodash.tap = tap;
	    lodash.throttle = throttle;
	    lodash.thru = thru;
	    lodash.toArray = toArray;
	    lodash.toPairs = toPairs;
	    lodash.toPairsIn = toPairsIn;
	    lodash.toPath = toPath;
	    lodash.toPlainObject = toPlainObject;
	    lodash.transform = transform;
	    lodash.unary = unary;
	    lodash.union = union;
	    lodash.unionBy = unionBy;
	    lodash.unionWith = unionWith;
	    lodash.uniq = uniq;
	    lodash.uniqBy = uniqBy;
	    lodash.uniqWith = uniqWith;
	    lodash.unset = unset;
	    lodash.unzip = unzip;
	    lodash.unzipWith = unzipWith;
	    lodash.update = update;
	    lodash.updateWith = updateWith;
	    lodash.values = values;
	    lodash.valuesIn = valuesIn;
	    lodash.without = without;
	    lodash.words = words;
	    lodash.wrap = wrap;
	    lodash.xor = xor;
	    lodash.xorBy = xorBy;
	    lodash.xorWith = xorWith;
	    lodash.zip = zip;
	    lodash.zipObject = zipObject;
	    lodash.zipObjectDeep = zipObjectDeep;
	    lodash.zipWith = zipWith;

	    // Add aliases.
	    lodash.entries = toPairs;
	    lodash.entriesIn = toPairsIn;
	    lodash.extend = assignIn;
	    lodash.extendWith = assignInWith;

	    // Add methods to `lodash.prototype`.
	    mixin(lodash, lodash);

	    /*------------------------------------------------------------------------*/

	    // Add methods that return unwrapped values in chain sequences.
	    lodash.add = add;
	    lodash.attempt = attempt;
	    lodash.camelCase = camelCase;
	    lodash.capitalize = capitalize;
	    lodash.ceil = ceil;
	    lodash.clamp = clamp;
	    lodash.clone = clone;
	    lodash.cloneDeep = cloneDeep;
	    lodash.cloneDeepWith = cloneDeepWith;
	    lodash.cloneWith = cloneWith;
	    lodash.deburr = deburr;
	    lodash.divide = divide;
	    lodash.endsWith = endsWith;
	    lodash.eq = eq;
	    lodash.escape = escape;
	    lodash.escapeRegExp = escapeRegExp;
	    lodash.every = every;
	    lodash.find = find;
	    lodash.findIndex = findIndex;
	    lodash.findKey = findKey;
	    lodash.findLast = findLast;
	    lodash.findLastIndex = findLastIndex;
	    lodash.findLastKey = findLastKey;
	    lodash.floor = floor;
	    lodash.forEach = forEach;
	    lodash.forEachRight = forEachRight;
	    lodash.forIn = forIn;
	    lodash.forInRight = forInRight;
	    lodash.forOwn = forOwn;
	    lodash.forOwnRight = forOwnRight;
	    lodash.get = get;
	    lodash.gt = gt;
	    lodash.gte = gte;
	    lodash.has = has;
	    lodash.hasIn = hasIn;
	    lodash.head = head;
	    lodash.identity = identity;
	    lodash.includes = includes;
	    lodash.indexOf = indexOf;
	    lodash.inRange = inRange;
	    lodash.invoke = invoke;
	    lodash.isArguments = isArguments;
	    lodash.isArray = isArray;
	    lodash.isArrayBuffer = isArrayBuffer;
	    lodash.isArrayLike = isArrayLike;
	    lodash.isArrayLikeObject = isArrayLikeObject;
	    lodash.isBoolean = isBoolean;
	    lodash.isBuffer = isBuffer;
	    lodash.isDate = isDate;
	    lodash.isElement = isElement;
	    lodash.isEmpty = isEmpty;
	    lodash.isEqual = isEqual;
	    lodash.isEqualWith = isEqualWith;
	    lodash.isError = isError;
	    lodash.isFinite = isFinite;
	    lodash.isFunction = isFunction;
	    lodash.isInteger = isInteger;
	    lodash.isLength = isLength;
	    lodash.isMap = isMap;
	    lodash.isMatch = isMatch;
	    lodash.isMatchWith = isMatchWith;
	    lodash.isNaN = isNaN;
	    lodash.isNative = isNative;
	    lodash.isNil = isNil;
	    lodash.isNull = isNull;
	    lodash.isNumber = isNumber;
	    lodash.isObject = isObject;
	    lodash.isObjectLike = isObjectLike;
	    lodash.isPlainObject = isPlainObject;
	    lodash.isRegExp = isRegExp;
	    lodash.isSafeInteger = isSafeInteger;
	    lodash.isSet = isSet;
	    lodash.isString = isString;
	    lodash.isSymbol = isSymbol;
	    lodash.isTypedArray = isTypedArray;
	    lodash.isUndefined = isUndefined;
	    lodash.isWeakMap = isWeakMap;
	    lodash.isWeakSet = isWeakSet;
	    lodash.join = join;
	    lodash.kebabCase = kebabCase;
	    lodash.last = last;
	    lodash.lastIndexOf = lastIndexOf;
	    lodash.lowerCase = lowerCase;
	    lodash.lowerFirst = lowerFirst;
	    lodash.lt = lt;
	    lodash.lte = lte;
	    lodash.max = max;
	    lodash.maxBy = maxBy;
	    lodash.mean = mean;
	    lodash.meanBy = meanBy;
	    lodash.min = min;
	    lodash.minBy = minBy;
	    lodash.multiply = multiply;
	    lodash.nth = nth;
	    lodash.noConflict = noConflict;
	    lodash.noop = noop;
	    lodash.now = now;
	    lodash.pad = pad;
	    lodash.padEnd = padEnd;
	    lodash.padStart = padStart;
	    lodash.parseInt = parseInt;
	    lodash.random = random;
	    lodash.reduce = reduce;
	    lodash.reduceRight = reduceRight;
	    lodash.repeat = repeat;
	    lodash.replace = replace;
	    lodash.result = result;
	    lodash.round = round;
	    lodash.runInContext = runInContext;
	    lodash.sample = sample;
	    lodash.size = size;
	    lodash.snakeCase = snakeCase;
	    lodash.some = some;
	    lodash.sortedIndex = sortedIndex;
	    lodash.sortedIndexBy = sortedIndexBy;
	    lodash.sortedIndexOf = sortedIndexOf;
	    lodash.sortedLastIndex = sortedLastIndex;
	    lodash.sortedLastIndexBy = sortedLastIndexBy;
	    lodash.sortedLastIndexOf = sortedLastIndexOf;
	    lodash.startCase = startCase;
	    lodash.startsWith = startsWith;
	    lodash.subtract = subtract;
	    lodash.sum = sum;
	    lodash.sumBy = sumBy;
	    lodash.template = template;
	    lodash.times = times;
	    lodash.toInteger = toInteger;
	    lodash.toLength = toLength;
	    lodash.toLower = toLower;
	    lodash.toNumber = toNumber;
	    lodash.toSafeInteger = toSafeInteger;
	    lodash.toString = toString;
	    lodash.toUpper = toUpper;
	    lodash.trim = trim;
	    lodash.trimEnd = trimEnd;
	    lodash.trimStart = trimStart;
	    lodash.truncate = truncate;
	    lodash.unescape = unescape;
	    lodash.uniqueId = uniqueId;
	    lodash.upperCase = upperCase;
	    lodash.upperFirst = upperFirst;

	    // Add aliases.
	    lodash.each = forEach;
	    lodash.eachRight = forEachRight;
	    lodash.first = head;

	    mixin(lodash, (function() {
	      var source = {};
	      baseForOwn(lodash, function(func, methodName) {
	        if (!hasOwnProperty.call(lodash.prototype, methodName)) {
	          source[methodName] = func;
	        }
	      });
	      return source;
	    }()), { 'chain': false });

	    /*------------------------------------------------------------------------*/

	    /**
	     * The semantic version number.
	     *
	     * @static
	     * @memberOf _
	     * @type {string}
	     */
	    lodash.VERSION = VERSION;

	    // Assign default placeholders.
	    arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
	      lodash[methodName].placeholder = lodash;
	    });

	    // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
	    arrayEach(['drop', 'take'], function(methodName, index) {
	      LazyWrapper.prototype[methodName] = function(n) {
	        var filtered = this.__filtered__;
	        if (filtered && !index) {
	          return new LazyWrapper(this);
	        }
	        n = n === undefined ? 1 : nativeMax(toInteger(n), 0);

	        var result = this.clone();
	        if (filtered) {
	          result.__takeCount__ = nativeMin(n, result.__takeCount__);
	        } else {
	          result.__views__.push({
	            'size': nativeMin(n, MAX_ARRAY_LENGTH),
	            'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
	          });
	        }
	        return result;
	      };

	      LazyWrapper.prototype[methodName + 'Right'] = function(n) {
	        return this.reverse()[methodName](n).reverse();
	      };
	    });

	    // Add `LazyWrapper` methods that accept an `iteratee` value.
	    arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
	      var type = index + 1,
	          isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;

	      LazyWrapper.prototype[methodName] = function(iteratee) {
	        var result = this.clone();
	        result.__iteratees__.push({
	          'iteratee': getIteratee(iteratee, 3),
	          'type': type
	        });
	        result.__filtered__ = result.__filtered__ || isFilter;
	        return result;
	      };
	    });

	    // Add `LazyWrapper` methods for `_.head` and `_.last`.
	    arrayEach(['head', 'last'], function(methodName, index) {
	      var takeName = 'take' + (index ? 'Right' : '');

	      LazyWrapper.prototype[methodName] = function() {
	        return this[takeName](1).value()[0];
	      };
	    });

	    // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
	    arrayEach(['initial', 'tail'], function(methodName, index) {
	      var dropName = 'drop' + (index ? '' : 'Right');

	      LazyWrapper.prototype[methodName] = function() {
	        return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
	      };
	    });

	    LazyWrapper.prototype.compact = function() {
	      return this.filter(identity);
	    };

	    LazyWrapper.prototype.find = function(predicate) {
	      return this.filter(predicate).head();
	    };

	    LazyWrapper.prototype.findLast = function(predicate) {
	      return this.reverse().find(predicate);
	    };

	    LazyWrapper.prototype.invokeMap = rest(function(path, args) {
	      if (typeof path == 'function') {
	        return new LazyWrapper(this);
	      }
	      return this.map(function(value) {
	        return baseInvoke(value, path, args);
	      });
	    });

	    LazyWrapper.prototype.reject = function(predicate) {
	      predicate = getIteratee(predicate, 3);
	      return this.filter(function(value) {
	        return !predicate(value);
	      });
	    };

	    LazyWrapper.prototype.slice = function(start, end) {
	      start = toInteger(start);

	      var result = this;
	      if (result.__filtered__ && (start > 0 || end < 0)) {
	        return new LazyWrapper(result);
	      }
	      if (start < 0) {
	        result = result.takeRight(-start);
	      } else if (start) {
	        result = result.drop(start);
	      }
	      if (end !== undefined) {
	        end = toInteger(end);
	        result = end < 0 ? result.dropRight(-end) : result.take(end - start);
	      }
	      return result;
	    };

	    LazyWrapper.prototype.takeRightWhile = function(predicate) {
	      return this.reverse().takeWhile(predicate).reverse();
	    };

	    LazyWrapper.prototype.toArray = function() {
	      return this.take(MAX_ARRAY_LENGTH);
	    };

	    // Add `LazyWrapper` methods to `lodash.prototype`.
	    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
	      var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
	          isTaker = /^(?:head|last)$/.test(methodName),
	          lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
	          retUnwrapped = isTaker || /^find/.test(methodName);

	      if (!lodashFunc) {
	        return;
	      }
	      lodash.prototype[methodName] = function() {
	        var value = this.__wrapped__,
	            args = isTaker ? [1] : arguments,
	            isLazy = value instanceof LazyWrapper,
	            iteratee = args[0],
	            useLazy = isLazy || isArray(value);

	        var interceptor = function(value) {
	          var result = lodashFunc.apply(lodash, arrayPush([value], args));
	          return (isTaker && chainAll) ? result[0] : result;
	        };

	        if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
	          // Avoid lazy use if the iteratee has a "length" value other than `1`.
	          isLazy = useLazy = false;
	        }
	        var chainAll = this.__chain__,
	            isHybrid = !!this.__actions__.length,
	            isUnwrapped = retUnwrapped && !chainAll,
	            onlyLazy = isLazy && !isHybrid;

	        if (!retUnwrapped && useLazy) {
	          value = onlyLazy ? value : new LazyWrapper(this);
	          var result = func.apply(value, args);
	          result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
	          return new LodashWrapper(result, chainAll);
	        }
	        if (isUnwrapped && onlyLazy) {
	          return func.apply(this, args);
	        }
	        result = this.thru(interceptor);
	        return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
	      };
	    });

	    // Add `Array` methods to `lodash.prototype`.
	    arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
	      var func = arrayProto[methodName],
	          chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
	          retUnwrapped = /^(?:pop|shift)$/.test(methodName);

	      lodash.prototype[methodName] = function() {
	        var args = arguments;
	        if (retUnwrapped && !this.__chain__) {
	          var value = this.value();
	          return func.apply(isArray(value) ? value : [], args);
	        }
	        return this[chainName](function(value) {
	          return func.apply(isArray(value) ? value : [], args);
	        });
	      };
	    });

	    // Map minified method names to their real names.
	    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
	      var lodashFunc = lodash[methodName];
	      if (lodashFunc) {
	        var key = (lodashFunc.name + ''),
	            names = realNames[key] || (realNames[key] = []);

	        names.push({ 'name': methodName, 'func': lodashFunc });
	      }
	    });

	    realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{
	      'name': 'wrapper',
	      'func': undefined
	    }];

	    // Add methods to `LazyWrapper`.
	    LazyWrapper.prototype.clone = lazyClone;
	    LazyWrapper.prototype.reverse = lazyReverse;
	    LazyWrapper.prototype.value = lazyValue;

	    // Add chain sequence methods to the `lodash` wrapper.
	    lodash.prototype.at = wrapperAt;
	    lodash.prototype.chain = wrapperChain;
	    lodash.prototype.commit = wrapperCommit;
	    lodash.prototype.next = wrapperNext;
	    lodash.prototype.plant = wrapperPlant;
	    lodash.prototype.reverse = wrapperReverse;
	    lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;

	    if (iteratorSymbol) {
	      lodash.prototype[iteratorSymbol] = wrapperToIterator;
	    }
	    return lodash;
	  }

	  /*--------------------------------------------------------------------------*/

	  // Export lodash.
	  var _ = runInContext();

	  // Expose lodash on the free variable `window` or `self` when available. This
	  // prevents errors in cases where lodash is loaded by a script tag in the presence
	  // of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details.
	  (freeWindow || freeSelf || {})._ = _;

	  // Some AMD build optimizers like r.js check for condition patterns like the following:
	  if (true) {
	    // Define as an anonymous module so, through path mapping, it can be
	    // referenced as the "underscore" module.
	    !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
	      return _;
	    }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	  }
	  // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
	  else if (freeExports && freeModule) {
	    // Export for Node.js.
	    if (moduleExports) {
	      (freeModule.exports = _)._ = _;
	    }
	    // Export for CommonJS support.
	    freeExports._ = _;
	  }
	  else {
	    // Export to the global object.
	    root._ = _;
	  }
	}.call(this));

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8)(module), (function() { return this; }())))

/***/ },
/* 8 */
/***/ function(module, exports) {

	module.exports = function(module) {
		if(!module.webpackPolyfill) {
			module.deprecate = function() {};
			module.paths = [];
			// module.parent = undefined by default
			module.children = [];
			module.webpackPolyfill = 1;
		}
		return module;
	}


/***/ },
/* 9 */
/***/ function(module, exports) {

	'use strict';

	//define(['jquery'], function(jQuery) {

	(function ($) {
	  window.NestedFormEvents = function () {
	    this.addFields = $.proxy(this.addFields, this);
	    this.removeFields = $.proxy(this.removeFields, this);
	  };

	  NestedFormEvents.prototype = {
	    addFields: function addFields(e) {
	      // Setup
	      var link = e.currentTarget;
	      var assoc = $(link).data('association'); // Name of child
	      var blueprint = $('#' + $(link).data('blueprint-id'));
	      var content = blueprint.data('blueprint'); // Fields template

	      // Make the context correct by replacing <parents> with the generated ID
	      // of each of the parent objects
	      var context = ($(link).closest('.fields').closestChild('input, textarea, select').eq(0).attr('name') || '').replace(/\[[a-z_]+\]$/, '');

	      // If the parent has no inputs we need to strip off the last pair
	      var current = content.match(new RegExp('\\[([a-z_]+)\\]\\[new_' + assoc + '\\]'));
	      if (current) {
	        context = context.replace(new RegExp('\\[' + current[1] + '\\]\\[(new_)?\\d+\\]$'), '');
	      }

	      // context will be something like this for a brand new form:
	      // project[tasks_attributes][1255929127459][assignments_attributes][1255929128105]
	      // or for an edit form:
	      // project[tasks_attributes][0][assignments_attributes][1]
	      if (context) {
	        var parentNames = context.match(/[a-z_]+_attributes(?=\]\[(new_)?\d+\])/g) || [];
	        var parentIds = context.match(/[0-9]+/g) || [];

	        for (var i = 0; i < parentNames.length; i++) {
	          if (parentIds[i]) {
	            content = content.replace(new RegExp('(_' + parentNames[i] + ')_.+?_', 'g'), '$1_' + parentIds[i] + '_');

	            content = content.replace(new RegExp('(\\[' + parentNames[i] + '\\])\\[.+?\\]', 'g'), '$1[' + parentIds[i] + ']');
	          }
	        }
	      }

	      // Make a unique ID for the new child
	      var regexp = new RegExp('new_' + assoc, 'g');
	      var new_id = this.newId();
	      content = $.trim(content.replace(regexp, new_id));

	      var field = this.insertFields(content, assoc, link);
	      // bubble up event upto document (through form)
	      field.trigger({ type: 'nested:fieldAdded', field: field }).trigger({ type: 'nested:fieldAdded:' + assoc, field: field });
	      return false;
	    },
	    newId: function newId() {
	      return new Date().getTime();
	    },
	    insertFields: function insertFields(content, assoc, link) {
	      var target = $(link).data('target');
	      if (target) {
	        return $(content).appendTo($(target));
	      } else {
	        return $(content).insertBefore(link);
	      }
	    },
	    removeFields: function removeFields(e) {
	      var $link = $(e.currentTarget),
	          assoc = $link.data('association'); // Name of child to be removed

	      var hiddenField = $link.prev('input[type=hidden]');
	      hiddenField.val('1');

	      var field = $link.closest('.fields');
	      field.hide();

	      field.trigger({ type: 'nested:fieldRemoved', field: field }).trigger({ type: 'nested:fieldRemoved:' + assoc, field: field });
	      return false;
	    }
	  };

	  window.nestedFormEvents = new NestedFormEvents();
	  $(document).delegate('form a.add_nested_fields', 'click', nestedFormEvents.addFields).delegate('form a.remove_nested_fields', 'click', nestedFormEvents.removeFields);
	})(jQuery);

	// http://plugins.jquery.com/project/closestChild
	/*
	 * Copyright 2011, Tobias Lindig
	 *
	 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
	 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
	 *
	 */
	(function ($) {
	  $.fn.closestChild = function (selector) {
	    // breadth first search for the first matched node
	    if (selector && selector != '') {
	      var queue = [];
	      queue.push(this);
	      while (queue.length > 0) {
	        var node = queue.shift();
	        var children = node.children();
	        for (var i = 0; i < children.length; ++i) {
	          var child = $(children[i]);
	          if (child.is(selector)) {
	            return child; //well, we found one
	          }
	          queue.push(child);
	        }
	      }
	    }
	    return $(); //nothing found
	  };
	})(jQuery);
	//})

/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*
	Turbolinks 5.0.0
	Copyright © 2016 Basecamp, LLC
	 */
	(function(){(function(){(function(){this.Turbolinks={supported:function(){return null!=window.history.pushState&&null!=window.requestAnimationFrame}(),visit:function(e,r){return t.controller.visit(e,r)},clearCache:function(){return t.controller.clearCache()}}}).call(this)}).call(this);var t=this.Turbolinks;(function(){(function(){var e,r;t.copyObject=function(t){var e,r,n;r={};for(e in t)n=t[e],r[e]=n;return r},t.closest=function(t,r){return e.call(t,r)},e=function(){var t,e;return t=document.documentElement,null!=(e=t.closest)?e:function(t){var e;for(e=this;e;){if(e.nodeType===Node.ELEMENT_NODE&&r.call(e,t))return e;e=e.parentNode}}}(),t.defer=function(t){return setTimeout(t,1)},t.dispatch=function(t,e){var r,n,o,i,s;return i=null!=e?e:{},s=i.target,r=i.cancelable,n=i.data,o=document.createEvent("Events"),o.initEvent(t,!0,r===!0),o.data=null!=n?n:{},(null!=s?s:document).dispatchEvent(o),o},t.match=function(t,e){return r.call(t,e)},r=function(){var t,e,r,n;return t=document.documentElement,null!=(e=null!=(r=null!=(n=t.matchesSelector)?n:t.webkitMatchesSelector)?r:t.msMatchesSelector)?e:t.mozMatchesSelector}(),t.uuid=function(){var t,e,r;for(r="",t=e=1;36>=e;t=++e)r+=9===t||14===t||19===t||24===t?"-":15===t?"4":20===t?(Math.floor(4*Math.random())+8).toString(16):Math.floor(15*Math.random()).toString(16);return r}}).call(this),function(){t.Location=function(){function t(t){var e,r;null==t&&(t=""),r=document.createElement("a"),r.href=t.toString(),this.absoluteURL=r.href,e=r.hash.length,2>e?this.requestURL=this.absoluteURL:(this.requestURL=this.absoluteURL.slice(0,-e),this.anchor=r.hash.slice(1))}var e,r,n,o;return t.wrap=function(t){return t instanceof this?t:new this(t)},t.prototype.getOrigin=function(){return this.absoluteURL.split("/",3).join("/")},t.prototype.getPath=function(){var t,e;return null!=(t=null!=(e=this.absoluteURL.match(/\/\/[^\/]*(\/[^?;]*)/))?e[1]:void 0)?t:"/"},t.prototype.getPathComponents=function(){return this.getPath().split("/").slice(1)},t.prototype.getLastPathComponent=function(){return this.getPathComponents().slice(-1)[0]},t.prototype.getExtension=function(){var t,e;return null!=(t=null!=(e=this.getLastPathComponent().match(/\.[^.]*$/))?e[0]:void 0)?t:""},t.prototype.isHTML=function(){return this.getExtension().match(/^(?:|\.(?:htm|html|xhtml))$/)},t.prototype.isPrefixedBy=function(t){var e;return e=r(t),this.isEqualTo(t)||o(this.absoluteURL,e)},t.prototype.isEqualTo=function(t){return this.absoluteURL===(null!=t?t.absoluteURL:void 0)},t.prototype.toCacheKey=function(){return this.requestURL},t.prototype.toJSON=function(){return this.absoluteURL},t.prototype.toString=function(){return this.absoluteURL},t.prototype.valueOf=function(){return this.absoluteURL},r=function(t){return e(t.getOrigin()+t.getPath())},e=function(t){return n(t,"/")?t:t+"/"},o=function(t,e){return t.slice(0,e.length)===e},n=function(t,e){return t.slice(-e.length)===e},t}()}.call(this),function(){var e=function(t,e){return function(){return t.apply(e,arguments)}};t.HttpRequest=function(){function r(r,n,o){this.delegate=r,this.requestCanceled=e(this.requestCanceled,this),this.requestTimedOut=e(this.requestTimedOut,this),this.requestFailed=e(this.requestFailed,this),this.requestLoaded=e(this.requestLoaded,this),this.requestProgressed=e(this.requestProgressed,this),this.url=t.Location.wrap(n).requestURL,this.referrer=t.Location.wrap(o).absoluteURL,this.createXHR()}return r.NETWORK_FAILURE=0,r.TIMEOUT_FAILURE=-1,r.timeout=60,r.prototype.send=function(){var t;return this.xhr&&!this.sent?(this.notifyApplicationBeforeRequestStart(),this.setProgress(0),this.xhr.send(),this.sent=!0,"function"==typeof(t=this.delegate).requestStarted?t.requestStarted():void 0):void 0},r.prototype.cancel=function(){return this.xhr&&this.sent?this.xhr.abort():void 0},r.prototype.requestProgressed=function(t){return t.lengthComputable?this.setProgress(t.loaded/t.total):void 0},r.prototype.requestLoaded=function(){return this.endRequest(function(t){return function(){var e;return 200<=(e=t.xhr.status)&&300>e?t.delegate.requestCompletedWithResponse(t.xhr.responseText,t.xhr.getResponseHeader("Turbolinks-Location")):(t.failed=!0,t.delegate.requestFailedWithStatusCode(t.xhr.status,t.xhr.responseText))}}(this))},r.prototype.requestFailed=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.NETWORK_FAILURE)}}(this))},r.prototype.requestTimedOut=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.TIMEOUT_FAILURE)}}(this))},r.prototype.requestCanceled=function(){return this.endRequest()},r.prototype.notifyApplicationBeforeRequestStart=function(){return t.dispatch("turbolinks:request-start",{data:{url:this.url,xhr:this.xhr}})},r.prototype.notifyApplicationAfterRequestEnd=function(){return t.dispatch("turbolinks:request-end",{data:{url:this.url,xhr:this.xhr}})},r.prototype.createXHR=function(){return this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url,!0),this.xhr.timeout=1e3*this.constructor.timeout,this.xhr.setRequestHeader("Accept","text/html, application/xhtml+xml"),this.xhr.setRequestHeader("Turbolinks-Referrer",this.referrer),this.xhr.onprogress=this.requestProgressed,this.xhr.onload=this.requestLoaded,this.xhr.onerror=this.requestFailed,this.xhr.ontimeout=this.requestTimedOut,this.xhr.onabort=this.requestCanceled},r.prototype.endRequest=function(t){return this.xhr?(this.notifyApplicationAfterRequestEnd(),null!=t&&t.call(this),this.destroy()):void 0},r.prototype.setProgress=function(t){var e;return this.progress=t,"function"==typeof(e=this.delegate).requestProgressed?e.requestProgressed(this.progress):void 0},r.prototype.destroy=function(){var t;return this.setProgress(1),"function"==typeof(t=this.delegate).requestFinished&&t.requestFinished(),this.delegate=null,this.xhr=null},r}()}.call(this),function(){var e=function(t,e){return function(){return t.apply(e,arguments)}};t.ProgressBar=function(){function t(){this.trickle=e(this.trickle,this),this.stylesheetElement=this.createStylesheetElement(),this.progressElement=this.createProgressElement()}var r;return r=300,t.defaultCSS=".turbolinks-progress-bar {\n  position: fixed;\n  display: block;\n  top: 0;\n  left: 0;\n  height: 3px;\n  background: #0076ff;\n  z-index: 9999;\n  transition: width "+r+"ms ease-out, opacity "+r/2+"ms "+r/2+"ms ease-in;\n  transform: translate3d(0, 0, 0);\n}",t.prototype.show=function(){return this.visible?void 0:(this.visible=!0,this.installStylesheetElement(),this.installProgressElement(),this.startTrickling())},t.prototype.hide=function(){return this.visible&&!this.hiding?(this.hiding=!0,this.fadeProgressElement(function(t){return function(){return t.uninstallProgressElement(),t.stopTrickling(),t.visible=!1,t.hiding=!1}}(this))):void 0},t.prototype.setValue=function(t){return this.value=t,this.refresh()},t.prototype.installStylesheetElement=function(){return document.head.insertBefore(this.stylesheetElement,document.head.firstChild)},t.prototype.installProgressElement=function(){return this.progressElement.style.width=0,this.progressElement.style.opacity=1,document.documentElement.insertBefore(this.progressElement,document.body),this.refresh()},t.prototype.fadeProgressElement=function(t){return this.progressElement.style.opacity=0,setTimeout(t,1.5*r)},t.prototype.uninstallProgressElement=function(){return this.progressElement.parentNode?document.documentElement.removeChild(this.progressElement):void 0},t.prototype.startTrickling=function(){return null!=this.trickleInterval?this.trickleInterval:this.trickleInterval=setInterval(this.trickle,r)},t.prototype.stopTrickling=function(){return clearInterval(this.trickleInterval),this.trickleInterval=null},t.prototype.trickle=function(){return this.setValue(this.value+Math.random()/100)},t.prototype.refresh=function(){return requestAnimationFrame(function(t){return function(){return t.progressElement.style.width=10+90*t.value+"%"}}(this))},t.prototype.createStylesheetElement=function(){var t;return t=document.createElement("style"),t.type="text/css",t.textContent=this.constructor.defaultCSS,t},t.prototype.createProgressElement=function(){var t;return t=document.createElement("div"),t.className="turbolinks-progress-bar",t},t}()}.call(this),function(){var e=function(t,e){return function(){return t.apply(e,arguments)}};t.BrowserAdapter=function(){function r(r){this.controller=r,this.showProgressBar=e(this.showProgressBar,this),this.progressBar=new t.ProgressBar}var n,o,i,s;return s=t.HttpRequest,n=s.NETWORK_FAILURE,i=s.TIMEOUT_FAILURE,o=500,r.prototype.visitProposedToLocationWithAction=function(t,e){return this.controller.startVisitToLocationWithAction(t,e)},r.prototype.visitStarted=function(t){return t.issueRequest(),t.changeHistory(),t.loadCachedSnapshot()},r.prototype.visitRequestStarted=function(t){return this.progressBar.setValue(0),t.hasCachedSnapshot()||"restore"!==t.action?this.showProgressBarAfterDelay():this.showProgressBar()},r.prototype.visitRequestProgressed=function(t){return this.progressBar.setValue(t.progress)},r.prototype.visitRequestCompleted=function(t){return t.loadResponse()},r.prototype.visitRequestFailedWithStatusCode=function(t,e){switch(e){case n:case i:return this.reload();default:return t.loadResponse()}},r.prototype.visitRequestFinished=function(t){return this.hideProgressBar()},r.prototype.visitCompleted=function(t){return t.followRedirect()},r.prototype.pageInvalidated=function(){return this.reload()},r.prototype.showProgressBarAfterDelay=function(){return this.progressBarTimeout=setTimeout(this.showProgressBar,o)},r.prototype.showProgressBar=function(){return this.progressBar.show()},r.prototype.hideProgressBar=function(){return this.progressBar.hide(),clearTimeout(this.progressBarTimeout)},r.prototype.reload=function(){return window.location.reload()},r}()}.call(this),function(){var e,r=function(t,e){return function(){return t.apply(e,arguments)}};e=!1,addEventListener("load",function(){return t.defer(function(){return e=!0})},!1),t.History=function(){function n(t){this.delegate=t,this.onPopState=r(this.onPopState,this)}return n.prototype.start=function(){return this.started?void 0:(addEventListener("popstate",this.onPopState,!1),this.started=!0)},n.prototype.stop=function(){return this.started?(removeEventListener("popstate",this.onPopState,!1),this.started=!1):void 0},n.prototype.push=function(e,r){return e=t.Location.wrap(e),this.update("push",e,r)},n.prototype.replace=function(e,r){return e=t.Location.wrap(e),this.update("replace",e,r)},n.prototype.onPopState=function(e){var r,n,o,i;return this.shouldHandlePopState()&&(i=null!=(n=e.state)?n.turbolinks:void 0)?(r=t.Location.wrap(window.location),o=i.restorationIdentifier,this.delegate.historyPoppedToLocationWithRestorationIdentifier(r,o)):void 0},n.prototype.shouldHandlePopState=function(){return e===!0},n.prototype.update=function(t,e,r){var n;return n={turbolinks:{restorationIdentifier:r}},history[t+"State"](n,null,e)},n}()}.call(this),function(){t.Snapshot=function(){function e(t){var e,r;r=t.head,e=t.body,this.head=null!=r?r:document.createElement("head"),this.body=null!=e?e:document.createElement("body")}return e.wrap=function(t){return t instanceof this?t:this.fromHTML(t)},e.fromHTML=function(t){var e;return e=document.createElement("html"),e.innerHTML=t,this.fromElement(e)},e.fromElement=function(t){return new this({head:t.querySelector("head"),body:t.querySelector("body")})},e.prototype.clone=function(){return new e({head:this.head.cloneNode(!0),body:this.body.cloneNode(!0)})},e.prototype.getRootLocation=function(){var e,r;return r=null!=(e=this.getSetting("root"))?e:"/",new t.Location(r)},e.prototype.getCacheControlValue=function(){return this.getSetting("cache-control")},e.prototype.hasAnchor=function(t){try{return null!=this.body.querySelector("[id='"+t+"']")}catch(e){}},e.prototype.isPreviewable=function(){return"no-preview"!==this.getCacheControlValue()},e.prototype.isCacheable=function(){return"no-cache"!==this.getCacheControlValue()},e.prototype.getSetting=function(t){var e,r;return r=this.head.querySelectorAll("meta[name='turbolinks-"+t+"']"),e=r[r.length-1],null!=e?e.getAttribute("content"):void 0},e}()}.call(this),function(){var e=[].slice;t.Renderer=function(){function t(){}var r;return t.render=function(){var t,r,n,o;return n=arguments[0],r=arguments[1],t=3<=arguments.length?e.call(arguments,2):[],o=function(t,e,r){r.prototype=t.prototype;var n=new r,o=t.apply(n,e);return Object(o)===o?o:n}(this,t,function(){}),o.delegate=n,o.render(r),o},t.prototype.renderView=function(t){return this.delegate.viewWillRender(this.newBody),t(),this.delegate.viewRendered(this.newBody)},t.prototype.invalidateView=function(){return this.delegate.viewInvalidated()},t.prototype.createScriptElement=function(t){var e;return"false"===t.getAttribute("data-turbolinks-eval")?t:(e=document.createElement("script"),e.textContent=t.textContent,r(e,t),e)},r=function(t,e){var r,n,o,i,s,a,u;for(i=e.attributes,a=[],r=0,n=i.length;n>r;r++)s=i[r],o=s.name,u=s.value,a.push(t.setAttribute(o,u));return a},t}()}.call(this),function(){t.HeadDetails=function(){function t(t){var e,r,i,s,a,u,c;for(this.element=t,this.elements={},c=this.element.childNodes,s=0,u=c.length;u>s;s++)i=c[s],i.nodeType===Node.ELEMENT_NODE&&(a=i.outerHTML,r=null!=(e=this.elements)[a]?e[a]:e[a]={type:o(i),tracked:n(i),elements:[]},r.elements.push(i))}var e,r,n,o;return t.prototype.hasElementWithKey=function(t){return t in this.elements},t.prototype.getTrackedElementSignature=function(){var t,e;return function(){var r,n;r=this.elements,n=[];for(t in r)e=r[t].tracked,e&&n.push(t);return n}.call(this).join("")},t.prototype.getScriptElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("script",t)},t.prototype.getStylesheetElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("stylesheet",t)},t.prototype.getElementsMatchingTypeNotInDetails=function(t,e){var r,n,o,i,s,a;o=this.elements,s=[];for(n in o)i=o[n],a=i.type,r=i.elements,a!==t||e.hasElementWithKey(n)||s.push(r[0]);return s},t.prototype.getProvisionalElements=function(){var t,e,r,n,o,i,s;r=[],n=this.elements;for(e in n)o=n[e],s=o.type,i=o.tracked,t=o.elements,null!=s||i?t.length>1&&r.push.apply(r,t.slice(1)):r.push.apply(r,t);return r},o=function(t){return e(t)?"script":r(t)?"stylesheet":void 0},n=function(t){return"reload"===t.getAttribute("data-turbolinks-track")},e=function(t){var e;return e=t.tagName.toLowerCase(),"script"===e},r=function(t){var e;return e=t.tagName.toLowerCase(),"style"===e||"link"===e&&"stylesheet"===t.getAttribute("rel")},t}()}.call(this),function(){var e=function(t,e){function n(){this.constructor=t}for(var o in e)r.call(e,o)&&(t[o]=e[o]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t},r={}.hasOwnProperty;t.SnapshotRenderer=function(r){function n(e,r){this.currentSnapshot=e,this.newSnapshot=r,this.currentHeadDetails=new t.HeadDetails(this.currentSnapshot.head),this.newHeadDetails=new t.HeadDetails(this.newSnapshot.head),this.newBody=this.newSnapshot.body}return e(n,r),n.prototype.render=function(t){return this.trackedElementsAreIdentical()?(this.mergeHead(),this.renderView(function(e){return function(){return e.replaceBody(),e.focusFirstAutofocusableElement(),t()}}(this))):this.invalidateView()},n.prototype.mergeHead=function(){return this.copyNewHeadStylesheetElements(),this.copyNewHeadScriptElements(),this.removeCurrentHeadProvisionalElements(),this.copyNewHeadProvisionalElements()},n.prototype.replaceBody=function(){return this.activateBodyScriptElements(),this.importBodyPermanentElements(),this.assignNewBody()},n.prototype.trackedElementsAreIdentical=function(){return this.currentHeadDetails.getTrackedElementSignature()===this.newHeadDetails.getTrackedElementSignature()},n.prototype.copyNewHeadStylesheetElements=function(){var t,e,r,n,o;for(n=this.getNewHeadStylesheetElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},n.prototype.copyNewHeadScriptElements=function(){var t,e,r,n,o;for(n=this.getNewHeadScriptElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(this.createScriptElement(t)));return o},n.prototype.removeCurrentHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getCurrentHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.removeChild(t));return o},n.prototype.copyNewHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getNewHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},n.prototype.importBodyPermanentElements=function(){var t,e,r,n,o,i;for(n=this.getNewBodyPermanentElements(),i=[],e=0,r=n.length;r>e;e++)o=n[e],(t=this.findCurrentBodyPermanentElement(o))?i.push(o.parentNode.replaceChild(t,o)):i.push(void 0);return i},n.prototype.activateBodyScriptElements=function(){var t,e,r,n,o,i;for(n=this.getNewBodyScriptElements(),i=[],e=0,r=n.length;r>e;e++)o=n[e],t=this.createScriptElement(o),i.push(o.parentNode.replaceChild(t,o));return i},n.prototype.assignNewBody=function(){return document.body=this.newBody},n.prototype.focusFirstAutofocusableElement=function(){var t;return null!=(t=this.findFirstAutofocusableElement())?t.focus():void 0},n.prototype.getNewHeadStylesheetElements=function(){return this.newHeadDetails.getStylesheetElementsNotInDetails(this.currentHeadDetails)},n.prototype.getNewHeadScriptElements=function(){return this.newHeadDetails.getScriptElementsNotInDetails(this.currentHeadDetails)},n.prototype.getCurrentHeadProvisionalElements=function(){return this.currentHeadDetails.getProvisionalElements()},n.prototype.getNewHeadProvisionalElements=function(){return this.newHeadDetails.getProvisionalElements()},n.prototype.getNewBodyPermanentElements=function(){return this.newBody.querySelectorAll("[id][data-turbolinks-permanent]")},n.prototype.findCurrentBodyPermanentElement=function(t){return document.body.querySelector("#"+t.id+"[data-turbolinks-permanent]")},n.prototype.getNewBodyScriptElements=function(){return this.newBody.querySelectorAll("script")},n.prototype.findFirstAutofocusableElement=function(){return document.body.querySelector("[autofocus]")},n}(t.Renderer)}.call(this),function(){var e=function(t,e){function n(){this.constructor=t}for(var o in e)r.call(e,o)&&(t[o]=e[o]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t},r={}.hasOwnProperty;t.ErrorRenderer=function(t){function r(t){this.html=t}return e(r,t),r.prototype.render=function(t){return this.renderView(function(e){return function(){return e.replaceDocumentHTML(),e.activateBodyScriptElements(),t()}}(this))},r.prototype.replaceDocumentHTML=function(){return document.documentElement.innerHTML=this.html},r.prototype.activateBodyScriptElements=function(){var t,e,r,n,o,i;for(n=this.getScriptElements(),i=[],e=0,r=n.length;r>e;e++)o=n[e],t=this.createScriptElement(o),i.push(o.parentNode.replaceChild(t,o));return i},r.prototype.getScriptElements=function(){return document.documentElement.querySelectorAll("script")},r}(t.Renderer)}.call(this),function(){t.View=function(){function e(t){this.delegate=t,this.element=document.documentElement}return e.prototype.getRootLocation=function(){return this.getSnapshot().getRootLocation()},e.prototype.getSnapshot=function(){return t.Snapshot.fromElement(this.element)},e.prototype.render=function(t,e){var r,n,o;return o=t.snapshot,r=t.error,n=t.isPreview,this.markAsPreview(n),null!=o?this.renderSnapshot(o,e):this.renderError(r,e)},e.prototype.markAsPreview=function(t){return t?this.element.setAttribute("data-turbolinks-preview",""):this.element.removeAttribute("data-turbolinks-preview")},e.prototype.renderSnapshot=function(e,r){return t.SnapshotRenderer.render(this.delegate,r,this.getSnapshot(),t.Snapshot.wrap(e))},e.prototype.renderError=function(e,r){return t.ErrorRenderer.render(this.delegate,r,e)},e}()}.call(this),function(){var e=function(t,e){return function(){return t.apply(e,arguments)}};t.ScrollManager=function(){function t(t){this.delegate=t,this.onScroll=e(this.onScroll,this)}return t.prototype.start=function(){return this.started?void 0:(addEventListener("scroll",this.onScroll,!1),this.onScroll(),this.started=!0)},t.prototype.stop=function(){return this.started?(removeEventListener("scroll",this.onScroll,!1),this.started=!1):void 0},t.prototype.scrollToElement=function(t){return t.scrollIntoView()},t.prototype.scrollToPosition=function(t){var e,r;return e=t.x,r=t.y,window.scrollTo(e,r)},t.prototype.onScroll=function(t){return this.updatePosition({x:window.pageXOffset,y:window.pageYOffset})},t.prototype.updatePosition=function(t){var e;return this.position=t,null!=(e=this.delegate)?e.scrollPositionChanged(this.position):void 0},t}()}.call(this),function(){t.SnapshotCache=function(){function e(t){this.size=t,this.keys=[],this.snapshots={}}var r;return e.prototype.has=function(t){var e;return e=r(t),e in this.snapshots},e.prototype.get=function(t){var e;if(this.has(t))return e=this.read(t),this.touch(t),e},e.prototype.put=function(t,e){return this.write(t,e),this.touch(t),e},e.prototype.read=function(t){var e;return e=r(t),this.snapshots[e]},e.prototype.write=function(t,e){var n;return n=r(t),this.snapshots[n]=e},e.prototype.touch=function(t){var e,n;return n=r(t),e=this.keys.indexOf(n),e>-1&&this.keys.splice(e,1),this.keys.unshift(n),this.trim()},e.prototype.trim=function(){var t,e,r,n,o;for(n=this.keys.splice(this.size),o=[],t=0,r=n.length;r>t;t++)e=n[t],o.push(delete this.snapshots[e]);return o},r=function(e){return t.Location.wrap(e).toCacheKey()},e}()}.call(this),function(){var e=function(t,e){return function(){return t.apply(e,arguments)}};t.Visit=function(){function r(r,n,o){this.controller=r,this.action=o,this.performScroll=e(this.performScroll,this),this.identifier=t.uuid(),this.location=t.Location.wrap(n),this.adapter=this.controller.adapter,this.state="initialized",this.timingMetrics={}}var n;return r.prototype.start=function(){return"initialized"===this.state?(this.recordTimingMetric("visitStart"),this.state="started",this.adapter.visitStarted(this)):void 0},r.prototype.cancel=function(){var t;return"started"===this.state?(null!=(t=this.request)&&t.cancel(),this.cancelRender(),this.state="canceled"):void 0},r.prototype.complete=function(){var t;return"started"===this.state?(this.recordTimingMetric("visitEnd"),this.state="completed","function"==typeof(t=this.adapter).visitCompleted&&t.visitCompleted(this),this.controller.visitCompleted(this)):void 0},r.prototype.fail=function(){var t;return"started"===this.state?(this.state="failed","function"==typeof(t=this.adapter).visitFailed?t.visitFailed(this):void 0):void 0},r.prototype.changeHistory=function(){var t,e;return this.historyChanged?void 0:(t=this.location.isEqualTo(this.referrer)?"replace":this.action,e=n(t),this.controller[e](this.location,this.restorationIdentifier),this.historyChanged=!0)},r.prototype.issueRequest=function(){return this.shouldIssueRequest()&&null==this.request?(this.progress=0,this.request=new t.HttpRequest(this,this.location,this.referrer),this.request.send()):void 0},r.prototype.getCachedSnapshot=function(){var t;return!(t=this.controller.getCachedSnapshotForLocation(this.location))||null!=this.location.anchor&&!t.hasAnchor(this.location.anchor)||"restore"!==this.action&&!t.isPreviewable()?void 0:t},r.prototype.hasCachedSnapshot=function(){return null!=this.getCachedSnapshot()},r.prototype.loadCachedSnapshot=function(){var t,e;return(e=this.getCachedSnapshot())?(t=this.shouldIssueRequest(),this.render(function(){var r;return this.cacheSnapshot(),this.controller.render({snapshot:e,isPreview:t},this.performScroll),"function"==typeof(r=this.adapter).visitRendered&&r.visitRendered(this),t?void 0:this.complete()})):void 0},r.prototype.loadResponse=function(){return null!=this.response?this.render(function(){var t,e;return this.cacheSnapshot(),this.request.failed?(this.controller.render({error:this.response},this.performScroll),"function"==typeof(t=this.adapter).visitRendered&&t.visitRendered(this),this.fail()):(this.controller.render({snapshot:this.response},this.performScroll),"function"==typeof(e=this.adapter).visitRendered&&e.visitRendered(this),this.complete())}):void 0},r.prototype.followRedirect=function(){return this.redirectedToLocation&&!this.followedRedirect?(this.location=this.redirectedToLocation,this.controller.replaceHistoryWithLocationAndRestorationIdentifier(this.redirectedToLocation,this.restorationIdentifier),this.followedRedirect=!0):void 0},r.prototype.requestStarted=function(){var t;return this.recordTimingMetric("requestStart"),"function"==typeof(t=this.adapter).visitRequestStarted?t.visitRequestStarted(this):void 0},r.prototype.requestProgressed=function(t){var e;return this.progress=t,"function"==typeof(e=this.adapter).visitRequestProgressed?e.visitRequestProgressed(this):void 0},r.prototype.requestCompletedWithResponse=function(e,r){return this.response=e,null!=r&&(this.redirectedToLocation=t.Location.wrap(r)),this.adapter.visitRequestCompleted(this)},r.prototype.requestFailedWithStatusCode=function(t,e){return this.response=e,this.adapter.visitRequestFailedWithStatusCode(this,t)},r.prototype.requestFinished=function(){var t;return this.recordTimingMetric("requestEnd"),"function"==typeof(t=this.adapter).visitRequestFinished?t.visitRequestFinished(this):void 0},r.prototype.performScroll=function(){return this.scrolled?void 0:("restore"===this.action?this.scrollToRestoredPosition()||this.scrollToTop():this.scrollToAnchor()||this.scrollToTop(),this.scrolled=!0)},r.prototype.scrollToRestoredPosition=function(){var t,e;return t=null!=(e=this.restorationData)?e.scrollPosition:void 0,null!=t?(this.controller.scrollToPosition(t),!0):void 0},r.prototype.scrollToAnchor=function(){return null!=this.location.anchor?(this.controller.scrollToAnchor(this.location.anchor),!0):void 0},r.prototype.scrollToTop=function(){return this.controller.scrollToPosition({x:0,y:0})},r.prototype.recordTimingMetric=function(t){var e;return null!=(e=this.timingMetrics)[t]?e[t]:e[t]=(new Date).getTime()},r.prototype.getTimingMetrics=function(){return t.copyObject(this.timingMetrics)},n=function(t){switch(t){case"replace":return"replaceHistoryWithLocationAndRestorationIdentifier";case"advance":case"restore":return"pushHistoryWithLocationAndRestorationIdentifier"}},r.prototype.shouldIssueRequest=function(){return"restore"===this.action?!this.hasCachedSnapshot():!0},r.prototype.cacheSnapshot=function(){return this.snapshotCached?void 0:(this.controller.cacheSnapshot(),this.snapshotCached=!0)},r.prototype.render=function(t){return this.cancelRender(),this.frame=requestAnimationFrame(function(e){return function(){return e.frame=null,t.call(e)}}(this))},r.prototype.cancelRender=function(){return this.frame?cancelAnimationFrame(this.frame):void 0},r}()}.call(this),function(){var e=function(t,e){return function(){return t.apply(e,arguments)}};t.Controller=function(){function r(){this.clickBubbled=e(this.clickBubbled,this),this.clickCaptured=e(this.clickCaptured,this),this.pageLoaded=e(this.pageLoaded,this),this.history=new t.History(this),this.view=new t.View(this),this.scrollManager=new t.ScrollManager(this),this.restorationData={},this.clearCache()}return r.prototype.start=function(){return t.supported&&!this.started?(addEventListener("click",this.clickCaptured,!0),addEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.start(),this.startHistory(),this.started=!0,this.enabled=!0):void 0},r.prototype.disable=function(){return this.enabled=!1},r.prototype.stop=function(){return this.started?(removeEventListener("click",this.clickCaptured,!0),removeEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.stop(),this.stopHistory(),this.started=!1):void 0},r.prototype.clearCache=function(){return this.cache=new t.SnapshotCache(10)},r.prototype.visit=function(e,r){var n,o;return null==r&&(r={}),e=t.Location.wrap(e),this.applicationAllowsVisitingLocation(e)?this.locationIsVisitable(e)?(n=null!=(o=r.action)?o:"advance",this.adapter.visitProposedToLocationWithAction(e,n)):window.location=e:void 0},r.prototype.startVisitToLocationWithAction=function(e,r,n){var o;return t.supported?(o=this.getRestorationDataForIdentifier(n),this.startVisit(e,r,{restorationData:o})):window.location=e},r.prototype.startHistory=function(){return this.location=t.Location.wrap(window.location),this.restorationIdentifier=t.uuid(),this.history.start(),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.stopHistory=function(){return this.history.stop()},r.prototype.pushHistoryWithLocationAndRestorationIdentifier=function(e,r){return this.restorationIdentifier=r,this.location=t.Location.wrap(e),this.history.push(this.location,this.restorationIdentifier)},r.prototype.replaceHistoryWithLocationAndRestorationIdentifier=function(e,r){return this.restorationIdentifier=r,this.location=t.Location.wrap(e),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.historyPoppedToLocationWithRestorationIdentifier=function(e,r){var n;return this.restorationIdentifier=r,this.enabled?(n=this.getRestorationDataForIdentifier(this.restorationIdentifier),this.startVisit(e,"restore",{restorationIdentifier:this.restorationIdentifier,restorationData:n,historyChanged:!0}),this.location=t.Location.wrap(e)):this.adapter.pageInvalidated()},r.prototype.getCachedSnapshotForLocation=function(t){var e;return e=this.cache.get(t),e?e.clone():void 0},r.prototype.shouldCacheSnapshot=function(){return this.view.getSnapshot().isCacheable()},r.prototype.cacheSnapshot=function(){var t;return this.shouldCacheSnapshot()?(this.notifyApplicationBeforeCachingSnapshot(),t=this.view.getSnapshot(),this.cache.put(this.lastRenderedLocation,t.clone())):void 0},r.prototype.scrollToAnchor=function(t){var e;return(e=document.getElementById(t))?this.scrollToElement(e):this.scrollToPosition({x:0,y:0})},r.prototype.scrollToElement=function(t){return this.scrollManager.scrollToElement(t)},r.prototype.scrollToPosition=function(t){return this.scrollManager.scrollToPosition(t)},r.prototype.scrollPositionChanged=function(t){var e;return e=this.getCurrentRestorationData(),e.scrollPosition=t},r.prototype.render=function(t,e){return this.view.render(t,e)},r.prototype.viewInvalidated=function(){return this.adapter.pageInvalidated()},r.prototype.viewWillRender=function(t){return this.notifyApplicationBeforeRender(t)},r.prototype.viewRendered=function(){return this.lastRenderedLocation=this.currentVisit.location,this.notifyApplicationAfterRender()},r.prototype.pageLoaded=function(){return this.lastRenderedLocation=this.location,this.notifyApplicationAfterPageLoad()},r.prototype.clickCaptured=function(){return removeEventListener("click",this.clickBubbled,!1),addEventListener("click",this.clickBubbled,!1)},r.prototype.clickBubbled=function(t){var e,r,n;return this.enabled&&this.clickEventIsSignificant(t)&&(r=this.getVisitableLinkForNode(t.target))&&(n=this.getVisitableLocationForLink(r))&&this.applicationAllowsFollowingLinkToLocation(r,n)?(t.preventDefault(),e=this.getActionForLink(r),this.visit(n,{action:e})):void 0},r.prototype.applicationAllowsFollowingLinkToLocation=function(t,e){var r;return r=this.notifyApplicationAfterClickingLinkToLocation(t,e),!r.defaultPrevented},r.prototype.applicationAllowsVisitingLocation=function(t){var e;return e=this.notifyApplicationBeforeVisitingLocation(t),!e.defaultPrevented},r.prototype.notifyApplicationAfterClickingLinkToLocation=function(e,r){return t.dispatch("turbolinks:click",{target:e,data:{url:r.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationBeforeVisitingLocation=function(e){return t.dispatch("turbolinks:before-visit",{data:{url:e.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationAfterVisitingLocation=function(e){return t.dispatch("turbolinks:visit",{data:{url:e.absoluteURL}})},r.prototype.notifyApplicationBeforeCachingSnapshot=function(){return t.dispatch("turbolinks:before-cache")},r.prototype.notifyApplicationBeforeRender=function(e){return t.dispatch("turbolinks:before-render",{data:{newBody:e}})},r.prototype.notifyApplicationAfterRender=function(){return t.dispatch("turbolinks:render")},r.prototype.notifyApplicationAfterPageLoad=function(e){return null==e&&(e={}),t.dispatch("turbolinks:load",{data:{url:this.location.absoluteURL,timing:e}})},r.prototype.startVisit=function(t,e,r){var n;return null!=(n=this.currentVisit)&&n.cancel(),this.currentVisit=this.createVisit(t,e,r),this.currentVisit.start(),this.notifyApplicationAfterVisitingLocation(t)},r.prototype.createVisit=function(e,r,n){
	var o,i,s,a,u;return i=null!=n?n:{},a=i.restorationIdentifier,s=i.restorationData,o=i.historyChanged,u=new t.Visit(this,e,r),u.restorationIdentifier=null!=a?a:t.uuid(),u.restorationData=t.copyObject(s),u.historyChanged=o,u.referrer=this.location,u},r.prototype.visitCompleted=function(t){return this.notifyApplicationAfterPageLoad(t.getTimingMetrics())},r.prototype.clickEventIsSignificant=function(t){return!(t.defaultPrevented||t.target.isContentEditable||t.which>1||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey)},r.prototype.getVisitableLinkForNode=function(e){return this.nodeIsVisitable(e)?t.closest(e,"a[href]:not([target])"):void 0},r.prototype.getVisitableLocationForLink=function(e){var r;return r=new t.Location(e.getAttribute("href")),this.locationIsVisitable(r)?r:void 0},r.prototype.getActionForLink=function(t){var e;return null!=(e=t.getAttribute("data-turbolinks-action"))?e:"advance"},r.prototype.nodeIsVisitable=function(e){var r;return(r=t.closest(e,"[data-turbolinks]"))?"false"!==r.getAttribute("data-turbolinks"):!0},r.prototype.locationIsVisitable=function(t){return t.isPrefixedBy(this.view.getRootLocation())&&t.isHTML()},r.prototype.getCurrentRestorationData=function(){return this.getRestorationDataForIdentifier(this.restorationIdentifier)},r.prototype.getRestorationDataForIdentifier=function(t){var e;return null!=(e=this.restorationData)[t]?e[t]:e[t]={}},r}()}.call(this),function(){var e,r,n;t.start=function(){return r()?(null==t.controller&&(t.controller=e()),t.controller.start()):void 0},r=function(){return null==window.Turbolinks&&(window.Turbolinks=t),n()},e=function(){var e;return e=new t.Controller,e.adapter=new t.BrowserAdapter(e),e},n=function(){return window.Turbolinks===t},n()&&t.start()}.call(this)}).call(this),"object"==typeof module&&module.exports?module.exports=t:"function"=="function"&&__webpack_require__(11)&&!(__WEBPACK_AMD_DEFINE_FACTORY__ = (t), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))}).call(this);

/***/ },
/* 11 */
/***/ function(module, exports) {

	/* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__;

	/* WEBPACK VAR INJECTION */}.call(exports, {}))

/***/ },
/* 12 */
/***/ function(module, exports, __webpack_require__) {

	// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
	__webpack_require__(13)
	__webpack_require__(14)
	__webpack_require__(15)
	__webpack_require__(16)
	__webpack_require__(17)
	__webpack_require__(18)
	__webpack_require__(19)
	__webpack_require__(20)
	__webpack_require__(21)
	__webpack_require__(22)
	__webpack_require__(23)
	__webpack_require__(24)

/***/ },
/* 13 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: transition.js v3.3.6
	 * http://getbootstrap.com/javascript/#transitions
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
	  // ============================================================

	  function transitionEnd() {
	    var el = document.createElement('bootstrap')

	    var transEndEventNames = {
	      WebkitTransition : 'webkitTransitionEnd',
	      MozTransition    : 'transitionend',
	      OTransition      : 'oTransitionEnd otransitionend',
	      transition       : 'transitionend'
	    }

	    for (var name in transEndEventNames) {
	      if (el.style[name] !== undefined) {
	        return { end: transEndEventNames[name] }
	      }
	    }

	    return false // explicit for ie8 (  ._.)
	  }

	  // http://blog.alexmaccaw.com/css-transitions
	  $.fn.emulateTransitionEnd = function (duration) {
	    var called = false
	    var $el = this
	    $(this).one('bsTransitionEnd', function () { called = true })
	    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
	    setTimeout(callback, duration)
	    return this
	  }

	  $(function () {
	    $.support.transition = transitionEnd()

	    if (!$.support.transition) return

	    $.event.special.bsTransitionEnd = {
	      bindType: $.support.transition.end,
	      delegateType: $.support.transition.end,
	      handle: function (e) {
	        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
	      }
	    }
	  })

	}(jQuery);


/***/ },
/* 14 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: alert.js v3.3.6
	 * http://getbootstrap.com/javascript/#alerts
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // ALERT CLASS DEFINITION
	  // ======================

	  var dismiss = '[data-dismiss="alert"]'
	  var Alert   = function (el) {
	    $(el).on('click', dismiss, this.close)
	  }

	  Alert.VERSION = '3.3.6'

	  Alert.TRANSITION_DURATION = 150

	  Alert.prototype.close = function (e) {
	    var $this    = $(this)
	    var selector = $this.attr('data-target')

	    if (!selector) {
	      selector = $this.attr('href')
	      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
	    }

	    var $parent = $(selector)

	    if (e) e.preventDefault()

	    if (!$parent.length) {
	      $parent = $this.closest('.alert')
	    }

	    $parent.trigger(e = $.Event('close.bs.alert'))

	    if (e.isDefaultPrevented()) return

	    $parent.removeClass('in')

	    function removeElement() {
	      // detach from parent, fire event then clean up data
	      $parent.detach().trigger('closed.bs.alert').remove()
	    }

	    $.support.transition && $parent.hasClass('fade') ?
	      $parent
	        .one('bsTransitionEnd', removeElement)
	        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
	      removeElement()
	  }


	  // ALERT PLUGIN DEFINITION
	  // =======================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this = $(this)
	      var data  = $this.data('bs.alert')

	      if (!data) $this.data('bs.alert', (data = new Alert(this)))
	      if (typeof option == 'string') data[option].call($this)
	    })
	  }

	  var old = $.fn.alert

	  $.fn.alert             = Plugin
	  $.fn.alert.Constructor = Alert


	  // ALERT NO CONFLICT
	  // =================

	  $.fn.alert.noConflict = function () {
	    $.fn.alert = old
	    return this
	  }


	  // ALERT DATA-API
	  // ==============

	  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)

	}(jQuery);


/***/ },
/* 15 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: button.js v3.3.6
	 * http://getbootstrap.com/javascript/#buttons
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // BUTTON PUBLIC CLASS DEFINITION
	  // ==============================

	  var Button = function (element, options) {
	    this.$element  = $(element)
	    this.options   = $.extend({}, Button.DEFAULTS, options)
	    this.isLoading = false
	  }

	  Button.VERSION  = '3.3.6'

	  Button.DEFAULTS = {
	    loadingText: 'loading...'
	  }

	  Button.prototype.setState = function (state) {
	    var d    = 'disabled'
	    var $el  = this.$element
	    var val  = $el.is('input') ? 'val' : 'html'
	    var data = $el.data()

	    state += 'Text'

	    if (data.resetText == null) $el.data('resetText', $el[val]())

	    // push to event loop to allow forms to submit
	    setTimeout($.proxy(function () {
	      $el[val](data[state] == null ? this.options[state] : data[state])

	      if (state == 'loadingText') {
	        this.isLoading = true
	        $el.addClass(d).attr(d, d)
	      } else if (this.isLoading) {
	        this.isLoading = false
	        $el.removeClass(d).removeAttr(d)
	      }
	    }, this), 0)
	  }

	  Button.prototype.toggle = function () {
	    var changed = true
	    var $parent = this.$element.closest('[data-toggle="buttons"]')

	    if ($parent.length) {
	      var $input = this.$element.find('input')
	      if ($input.prop('type') == 'radio') {
	        if ($input.prop('checked')) changed = false
	        $parent.find('.active').removeClass('active')
	        this.$element.addClass('active')
	      } else if ($input.prop('type') == 'checkbox') {
	        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
	        this.$element.toggleClass('active')
	      }
	      $input.prop('checked', this.$element.hasClass('active'))
	      if (changed) $input.trigger('change')
	    } else {
	      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
	      this.$element.toggleClass('active')
	    }
	  }


	  // BUTTON PLUGIN DEFINITION
	  // ========================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.button')
	      var options = typeof option == 'object' && option

	      if (!data) $this.data('bs.button', (data = new Button(this, options)))

	      if (option == 'toggle') data.toggle()
	      else if (option) data.setState(option)
	    })
	  }

	  var old = $.fn.button

	  $.fn.button             = Plugin
	  $.fn.button.Constructor = Button


	  // BUTTON NO CONFLICT
	  // ==================

	  $.fn.button.noConflict = function () {
	    $.fn.button = old
	    return this
	  }


	  // BUTTON DATA-API
	  // ===============

	  $(document)
	    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
	      var $btn = $(e.target)
	      if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
	      Plugin.call($btn, 'toggle')
	      if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
	    })
	    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
	      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
	    })

	}(jQuery);


/***/ },
/* 16 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: carousel.js v3.3.6
	 * http://getbootstrap.com/javascript/#carousel
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // CAROUSEL CLASS DEFINITION
	  // =========================

	  var Carousel = function (element, options) {
	    this.$element    = $(element)
	    this.$indicators = this.$element.find('.carousel-indicators')
	    this.options     = options
	    this.paused      = null
	    this.sliding     = null
	    this.interval    = null
	    this.$active     = null
	    this.$items      = null

	    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))

	    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
	      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
	      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
	  }

	  Carousel.VERSION  = '3.3.6'

	  Carousel.TRANSITION_DURATION = 600

	  Carousel.DEFAULTS = {
	    interval: 5000,
	    pause: 'hover',
	    wrap: true,
	    keyboard: true
	  }

	  Carousel.prototype.keydown = function (e) {
	    if (/input|textarea/i.test(e.target.tagName)) return
	    switch (e.which) {
	      case 37: this.prev(); break
	      case 39: this.next(); break
	      default: return
	    }

	    e.preventDefault()
	  }

	  Carousel.prototype.cycle = function (e) {
	    e || (this.paused = false)

	    this.interval && clearInterval(this.interval)

	    this.options.interval
	      && !this.paused
	      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))

	    return this
	  }

	  Carousel.prototype.getItemIndex = function (item) {
	    this.$items = item.parent().children('.item')
	    return this.$items.index(item || this.$active)
	  }

	  Carousel.prototype.getItemForDirection = function (direction, active) {
	    var activeIndex = this.getItemIndex(active)
	    var willWrap = (direction == 'prev' && activeIndex === 0)
	                || (direction == 'next' && activeIndex == (this.$items.length - 1))
	    if (willWrap && !this.options.wrap) return active
	    var delta = direction == 'prev' ? -1 : 1
	    var itemIndex = (activeIndex + delta) % this.$items.length
	    return this.$items.eq(itemIndex)
	  }

	  Carousel.prototype.to = function (pos) {
	    var that        = this
	    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))

	    if (pos > (this.$items.length - 1) || pos < 0) return

	    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
	    if (activeIndex == pos) return this.pause().cycle()

	    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
	  }

	  Carousel.prototype.pause = function (e) {
	    e || (this.paused = true)

	    if (this.$element.find('.next, .prev').length && $.support.transition) {
	      this.$element.trigger($.support.transition.end)
	      this.cycle(true)
	    }

	    this.interval = clearInterval(this.interval)

	    return this
	  }

	  Carousel.prototype.next = function () {
	    if (this.sliding) return
	    return this.slide('next')
	  }

	  Carousel.prototype.prev = function () {
	    if (this.sliding) return
	    return this.slide('prev')
	  }

	  Carousel.prototype.slide = function (type, next) {
	    var $active   = this.$element.find('.item.active')
	    var $next     = next || this.getItemForDirection(type, $active)
	    var isCycling = this.interval
	    var direction = type == 'next' ? 'left' : 'right'
	    var that      = this

	    if ($next.hasClass('active')) return (this.sliding = false)

	    var relatedTarget = $next[0]
	    var slideEvent = $.Event('slide.bs.carousel', {
	      relatedTarget: relatedTarget,
	      direction: direction
	    })
	    this.$element.trigger(slideEvent)
	    if (slideEvent.isDefaultPrevented()) return

	    this.sliding = true

	    isCycling && this.pause()

	    if (this.$indicators.length) {
	      this.$indicators.find('.active').removeClass('active')
	      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
	      $nextIndicator && $nextIndicator.addClass('active')
	    }

	    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
	    if ($.support.transition && this.$element.hasClass('slide')) {
	      $next.addClass(type)
	      $next[0].offsetWidth // force reflow
	      $active.addClass(direction)
	      $next.addClass(direction)
	      $active
	        .one('bsTransitionEnd', function () {
	          $next.removeClass([type, direction].join(' ')).addClass('active')
	          $active.removeClass(['active', direction].join(' '))
	          that.sliding = false
	          setTimeout(function () {
	            that.$element.trigger(slidEvent)
	          }, 0)
	        })
	        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
	    } else {
	      $active.removeClass('active')
	      $next.addClass('active')
	      this.sliding = false
	      this.$element.trigger(slidEvent)
	    }

	    isCycling && this.cycle()

	    return this
	  }


	  // CAROUSEL PLUGIN DEFINITION
	  // ==========================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.carousel')
	      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
	      var action  = typeof option == 'string' ? option : options.slide

	      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
	      if (typeof option == 'number') data.to(option)
	      else if (action) data[action]()
	      else if (options.interval) data.pause().cycle()
	    })
	  }

	  var old = $.fn.carousel

	  $.fn.carousel             = Plugin
	  $.fn.carousel.Constructor = Carousel


	  // CAROUSEL NO CONFLICT
	  // ====================

	  $.fn.carousel.noConflict = function () {
	    $.fn.carousel = old
	    return this
	  }


	  // CAROUSEL DATA-API
	  // =================

	  var clickHandler = function (e) {
	    var href
	    var $this   = $(this)
	    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
	    if (!$target.hasClass('carousel')) return
	    var options = $.extend({}, $target.data(), $this.data())
	    var slideIndex = $this.attr('data-slide-to')
	    if (slideIndex) options.interval = false

	    Plugin.call($target, options)

	    if (slideIndex) {
	      $target.data('bs.carousel').to(slideIndex)
	    }

	    e.preventDefault()
	  }

	  $(document)
	    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
	    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)

	  $(window).on('load', function () {
	    $('[data-ride="carousel"]').each(function () {
	      var $carousel = $(this)
	      Plugin.call($carousel, $carousel.data())
	    })
	  })

	}(jQuery);


/***/ },
/* 17 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: collapse.js v3.3.6
	 * http://getbootstrap.com/javascript/#collapse
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // COLLAPSE PUBLIC CLASS DEFINITION
	  // ================================

	  var Collapse = function (element, options) {
	    this.$element      = $(element)
	    this.options       = $.extend({}, Collapse.DEFAULTS, options)
	    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
	                           '[data-toggle="collapse"][data-target="#' + element.id + '"]')
	    this.transitioning = null

	    if (this.options.parent) {
	      this.$parent = this.getParent()
	    } else {
	      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
	    }

	    if (this.options.toggle) this.toggle()
	  }

	  Collapse.VERSION  = '3.3.6'

	  Collapse.TRANSITION_DURATION = 350

	  Collapse.DEFAULTS = {
	    toggle: true
	  }

	  Collapse.prototype.dimension = function () {
	    var hasWidth = this.$element.hasClass('width')
	    return hasWidth ? 'width' : 'height'
	  }

	  Collapse.prototype.show = function () {
	    if (this.transitioning || this.$element.hasClass('in')) return

	    var activesData
	    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')

	    if (actives && actives.length) {
	      activesData = actives.data('bs.collapse')
	      if (activesData && activesData.transitioning) return
	    }

	    var startEvent = $.Event('show.bs.collapse')
	    this.$element.trigger(startEvent)
	    if (startEvent.isDefaultPrevented()) return

	    if (actives && actives.length) {
	      Plugin.call(actives, 'hide')
	      activesData || actives.data('bs.collapse', null)
	    }

	    var dimension = this.dimension()

	    this.$element
	      .removeClass('collapse')
	      .addClass('collapsing')[dimension](0)
	      .attr('aria-expanded', true)

	    this.$trigger
	      .removeClass('collapsed')
	      .attr('aria-expanded', true)

	    this.transitioning = 1

	    var complete = function () {
	      this.$element
	        .removeClass('collapsing')
	        .addClass('collapse in')[dimension]('')
	      this.transitioning = 0
	      this.$element
	        .trigger('shown.bs.collapse')
	    }

	    if (!$.support.transition) return complete.call(this)

	    var scrollSize = $.camelCase(['scroll', dimension].join('-'))

	    this.$element
	      .one('bsTransitionEnd', $.proxy(complete, this))
	      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
	  }

	  Collapse.prototype.hide = function () {
	    if (this.transitioning || !this.$element.hasClass('in')) return

	    var startEvent = $.Event('hide.bs.collapse')
	    this.$element.trigger(startEvent)
	    if (startEvent.isDefaultPrevented()) return

	    var dimension = this.dimension()

	    this.$element[dimension](this.$element[dimension]())[0].offsetHeight

	    this.$element
	      .addClass('collapsing')
	      .removeClass('collapse in')
	      .attr('aria-expanded', false)

	    this.$trigger
	      .addClass('collapsed')
	      .attr('aria-expanded', false)

	    this.transitioning = 1

	    var complete = function () {
	      this.transitioning = 0
	      this.$element
	        .removeClass('collapsing')
	        .addClass('collapse')
	        .trigger('hidden.bs.collapse')
	    }

	    if (!$.support.transition) return complete.call(this)

	    this.$element
	      [dimension](0)
	      .one('bsTransitionEnd', $.proxy(complete, this))
	      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
	  }

	  Collapse.prototype.toggle = function () {
	    this[this.$element.hasClass('in') ? 'hide' : 'show']()
	  }

	  Collapse.prototype.getParent = function () {
	    return $(this.options.parent)
	      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
	      .each($.proxy(function (i, element) {
	        var $element = $(element)
	        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
	      }, this))
	      .end()
	  }

	  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
	    var isOpen = $element.hasClass('in')

	    $element.attr('aria-expanded', isOpen)
	    $trigger
	      .toggleClass('collapsed', !isOpen)
	      .attr('aria-expanded', isOpen)
	  }

	  function getTargetFromTrigger($trigger) {
	    var href
	    var target = $trigger.attr('data-target')
	      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7

	    return $(target)
	  }


	  // COLLAPSE PLUGIN DEFINITION
	  // ==========================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.collapse')
	      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)

	      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
	      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
	      if (typeof option == 'string') data[option]()
	    })
	  }

	  var old = $.fn.collapse

	  $.fn.collapse             = Plugin
	  $.fn.collapse.Constructor = Collapse


	  // COLLAPSE NO CONFLICT
	  // ====================

	  $.fn.collapse.noConflict = function () {
	    $.fn.collapse = old
	    return this
	  }


	  // COLLAPSE DATA-API
	  // =================

	  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
	    var $this   = $(this)

	    if (!$this.attr('data-target')) e.preventDefault()

	    var $target = getTargetFromTrigger($this)
	    var data    = $target.data('bs.collapse')
	    var option  = data ? 'toggle' : $this.data()

	    Plugin.call($target, option)
	  })

	}(jQuery);


/***/ },
/* 18 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: dropdown.js v3.3.6
	 * http://getbootstrap.com/javascript/#dropdowns
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // DROPDOWN CLASS DEFINITION
	  // =========================

	  var backdrop = '.dropdown-backdrop'
	  var toggle   = '[data-toggle="dropdown"]'
	  var Dropdown = function (element) {
	    $(element).on('click.bs.dropdown', this.toggle)
	  }

	  Dropdown.VERSION = '3.3.6'

	  function getParent($this) {
	    var selector = $this.attr('data-target')

	    if (!selector) {
	      selector = $this.attr('href')
	      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
	    }

	    var $parent = selector && $(selector)

	    return $parent && $parent.length ? $parent : $this.parent()
	  }

	  function clearMenus(e) {
	    if (e && e.which === 3) return
	    $(backdrop).remove()
	    $(toggle).each(function () {
	      var $this         = $(this)
	      var $parent       = getParent($this)
	      var relatedTarget = { relatedTarget: this }

	      if (!$parent.hasClass('open')) return

	      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return

	      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))

	      if (e.isDefaultPrevented()) return

	      $this.attr('aria-expanded', 'false')
	      $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
	    })
	  }

	  Dropdown.prototype.toggle = function (e) {
	    var $this = $(this)

	    if ($this.is('.disabled, :disabled')) return

	    var $parent  = getParent($this)
	    var isActive = $parent.hasClass('open')

	    clearMenus()

	    if (!isActive) {
	      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
	        // if mobile we use a backdrop because click events don't delegate
	        $(document.createElement('div'))
	          .addClass('dropdown-backdrop')
	          .insertAfter($(this))
	          .on('click', clearMenus)
	      }

	      var relatedTarget = { relatedTarget: this }
	      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))

	      if (e.isDefaultPrevented()) return

	      $this
	        .trigger('focus')
	        .attr('aria-expanded', 'true')

	      $parent
	        .toggleClass('open')
	        .trigger($.Event('shown.bs.dropdown', relatedTarget))
	    }

	    return false
	  }

	  Dropdown.prototype.keydown = function (e) {
	    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return

	    var $this = $(this)

	    e.preventDefault()
	    e.stopPropagation()

	    if ($this.is('.disabled, :disabled')) return

	    var $parent  = getParent($this)
	    var isActive = $parent.hasClass('open')

	    if (!isActive && e.which != 27 || isActive && e.which == 27) {
	      if (e.which == 27) $parent.find(toggle).trigger('focus')
	      return $this.trigger('click')
	    }

	    var desc = ' li:not(.disabled):visible a'
	    var $items = $parent.find('.dropdown-menu' + desc)

	    if (!$items.length) return

	    var index = $items.index(e.target)

	    if (e.which == 38 && index > 0)                 index--         // up
	    if (e.which == 40 && index < $items.length - 1) index++         // down
	    if (!~index)                                    index = 0

	    $items.eq(index).trigger('focus')
	  }


	  // DROPDOWN PLUGIN DEFINITION
	  // ==========================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this = $(this)
	      var data  = $this.data('bs.dropdown')

	      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
	      if (typeof option == 'string') data[option].call($this)
	    })
	  }

	  var old = $.fn.dropdown

	  $.fn.dropdown             = Plugin
	  $.fn.dropdown.Constructor = Dropdown


	  // DROPDOWN NO CONFLICT
	  // ====================

	  $.fn.dropdown.noConflict = function () {
	    $.fn.dropdown = old
	    return this
	  }


	  // APPLY TO STANDARD DROPDOWN ELEMENTS
	  // ===================================

	  $(document)
	    .on('click.bs.dropdown.data-api', clearMenus)
	    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
	    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
	    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
	    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)

	}(jQuery);


/***/ },
/* 19 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: modal.js v3.3.6
	 * http://getbootstrap.com/javascript/#modals
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // MODAL CLASS DEFINITION
	  // ======================

	  var Modal = function (element, options) {
	    this.options             = options
	    this.$body               = $(document.body)
	    this.$element            = $(element)
	    this.$dialog             = this.$element.find('.modal-dialog')
	    this.$backdrop           = null
	    this.isShown             = null
	    this.originalBodyPad     = null
	    this.scrollbarWidth      = 0
	    this.ignoreBackdropClick = false

	    if (this.options.remote) {
	      this.$element
	        .find('.modal-content')
	        .load(this.options.remote, $.proxy(function () {
	          this.$element.trigger('loaded.bs.modal')
	        }, this))
	    }
	  }

	  Modal.VERSION  = '3.3.6'

	  Modal.TRANSITION_DURATION = 300
	  Modal.BACKDROP_TRANSITION_DURATION = 150

	  Modal.DEFAULTS = {
	    backdrop: true,
	    keyboard: true,
	    show: true
	  }

	  Modal.prototype.toggle = function (_relatedTarget) {
	    return this.isShown ? this.hide() : this.show(_relatedTarget)
	  }

	  Modal.prototype.show = function (_relatedTarget) {
	    var that = this
	    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })

	    this.$element.trigger(e)

	    if (this.isShown || e.isDefaultPrevented()) return

	    this.isShown = true

	    this.checkScrollbar()
	    this.setScrollbar()
	    this.$body.addClass('modal-open')

	    this.escape()
	    this.resize()

	    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))

	    this.$dialog.on('mousedown.dismiss.bs.modal', function () {
	      that.$element.one('mouseup.dismiss.bs.modal', function (e) {
	        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
	      })
	    })

	    this.backdrop(function () {
	      var transition = $.support.transition && that.$element.hasClass('fade')

	      if (!that.$element.parent().length) {
	        that.$element.appendTo(that.$body) // don't move modals dom position
	      }

	      that.$element
	        .show()
	        .scrollTop(0)

	      that.adjustDialog()

	      if (transition) {
	        that.$element[0].offsetWidth // force reflow
	      }

	      that.$element.addClass('in')

	      that.enforceFocus()

	      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })

	      transition ?
	        that.$dialog // wait for modal to slide in
	          .one('bsTransitionEnd', function () {
	            that.$element.trigger('focus').trigger(e)
	          })
	          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
	        that.$element.trigger('focus').trigger(e)
	    })
	  }

	  Modal.prototype.hide = function (e) {
	    if (e) e.preventDefault()

	    e = $.Event('hide.bs.modal')

	    this.$element.trigger(e)

	    if (!this.isShown || e.isDefaultPrevented()) return

	    this.isShown = false

	    this.escape()
	    this.resize()

	    $(document).off('focusin.bs.modal')

	    this.$element
	      .removeClass('in')
	      .off('click.dismiss.bs.modal')
	      .off('mouseup.dismiss.bs.modal')

	    this.$dialog.off('mousedown.dismiss.bs.modal')

	    $.support.transition && this.$element.hasClass('fade') ?
	      this.$element
	        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
	        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
	      this.hideModal()
	  }

	  Modal.prototype.enforceFocus = function () {
	    $(document)
	      .off('focusin.bs.modal') // guard against infinite focus loop
	      .on('focusin.bs.modal', $.proxy(function (e) {
	        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
	          this.$element.trigger('focus')
	        }
	      }, this))
	  }

	  Modal.prototype.escape = function () {
	    if (this.isShown && this.options.keyboard) {
	      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
	        e.which == 27 && this.hide()
	      }, this))
	    } else if (!this.isShown) {
	      this.$element.off('keydown.dismiss.bs.modal')
	    }
	  }

	  Modal.prototype.resize = function () {
	    if (this.isShown) {
	      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
	    } else {
	      $(window).off('resize.bs.modal')
	    }
	  }

	  Modal.prototype.hideModal = function () {
	    var that = this
	    this.$element.hide()
	    this.backdrop(function () {
	      that.$body.removeClass('modal-open')
	      that.resetAdjustments()
	      that.resetScrollbar()
	      that.$element.trigger('hidden.bs.modal')
	    })
	  }

	  Modal.prototype.removeBackdrop = function () {
	    this.$backdrop && this.$backdrop.remove()
	    this.$backdrop = null
	  }

	  Modal.prototype.backdrop = function (callback) {
	    var that = this
	    var animate = this.$element.hasClass('fade') ? 'fade' : ''

	    if (this.isShown && this.options.backdrop) {
	      var doAnimate = $.support.transition && animate

	      this.$backdrop = $(document.createElement('div'))
	        .addClass('modal-backdrop ' + animate)
	        .appendTo(this.$body)

	      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
	        if (this.ignoreBackdropClick) {
	          this.ignoreBackdropClick = false
	          return
	        }
	        if (e.target !== e.currentTarget) return
	        this.options.backdrop == 'static'
	          ? this.$element[0].focus()
	          : this.hide()
	      }, this))

	      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow

	      this.$backdrop.addClass('in')

	      if (!callback) return

	      doAnimate ?
	        this.$backdrop
	          .one('bsTransitionEnd', callback)
	          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
	        callback()

	    } else if (!this.isShown && this.$backdrop) {
	      this.$backdrop.removeClass('in')

	      var callbackRemove = function () {
	        that.removeBackdrop()
	        callback && callback()
	      }
	      $.support.transition && this.$element.hasClass('fade') ?
	        this.$backdrop
	          .one('bsTransitionEnd', callbackRemove)
	          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
	        callbackRemove()

	    } else if (callback) {
	      callback()
	    }
	  }

	  // these following methods are used to handle overflowing modals

	  Modal.prototype.handleUpdate = function () {
	    this.adjustDialog()
	  }

	  Modal.prototype.adjustDialog = function () {
	    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight

	    this.$element.css({
	      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
	      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
	    })
	  }

	  Modal.prototype.resetAdjustments = function () {
	    this.$element.css({
	      paddingLeft: '',
	      paddingRight: ''
	    })
	  }

	  Modal.prototype.checkScrollbar = function () {
	    var fullWindowWidth = window.innerWidth
	    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
	      var documentElementRect = document.documentElement.getBoundingClientRect()
	      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
	    }
	    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
	    this.scrollbarWidth = this.measureScrollbar()
	  }

	  Modal.prototype.setScrollbar = function () {
	    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
	    this.originalBodyPad = document.body.style.paddingRight || ''
	    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
	  }

	  Modal.prototype.resetScrollbar = function () {
	    this.$body.css('padding-right', this.originalBodyPad)
	  }

	  Modal.prototype.measureScrollbar = function () { // thx walsh
	    var scrollDiv = document.createElement('div')
	    scrollDiv.className = 'modal-scrollbar-measure'
	    this.$body.append(scrollDiv)
	    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
	    this.$body[0].removeChild(scrollDiv)
	    return scrollbarWidth
	  }


	  // MODAL PLUGIN DEFINITION
	  // =======================

	  function Plugin(option, _relatedTarget) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.modal')
	      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)

	      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
	      if (typeof option == 'string') data[option](_relatedTarget)
	      else if (options.show) data.show(_relatedTarget)
	    })
	  }

	  var old = $.fn.modal

	  $.fn.modal             = Plugin
	  $.fn.modal.Constructor = Modal


	  // MODAL NO CONFLICT
	  // =================

	  $.fn.modal.noConflict = function () {
	    $.fn.modal = old
	    return this
	  }


	  // MODAL DATA-API
	  // ==============

	  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
	    var $this   = $(this)
	    var href    = $this.attr('href')
	    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
	    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())

	    if ($this.is('a')) e.preventDefault()

	    $target.one('show.bs.modal', function (showEvent) {
	      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
	      $target.one('hidden.bs.modal', function () {
	        $this.is(':visible') && $this.trigger('focus')
	      })
	    })
	    Plugin.call($target, option, this)
	  })

	}(jQuery);


/***/ },
/* 20 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: tooltip.js v3.3.6
	 * http://getbootstrap.com/javascript/#tooltip
	 * Inspired by the original jQuery.tipsy by Jason Frame
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // TOOLTIP PUBLIC CLASS DEFINITION
	  // ===============================

	  var Tooltip = function (element, options) {
	    this.type       = null
	    this.options    = null
	    this.enabled    = null
	    this.timeout    = null
	    this.hoverState = null
	    this.$element   = null
	    this.inState    = null

	    this.init('tooltip', element, options)
	  }

	  Tooltip.VERSION  = '3.3.6'

	  Tooltip.TRANSITION_DURATION = 150

	  Tooltip.DEFAULTS = {
	    animation: true,
	    placement: 'top',
	    selector: false,
	    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
	    trigger: 'hover focus',
	    title: '',
	    delay: 0,
	    html: false,
	    container: false,
	    viewport: {
	      selector: 'body',
	      padding: 0
	    }
	  }

	  Tooltip.prototype.init = function (type, element, options) {
	    this.enabled   = true
	    this.type      = type
	    this.$element  = $(element)
	    this.options   = this.getOptions(options)
	    this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
	    this.inState   = { click: false, hover: false, focus: false }

	    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
	      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
	    }

	    var triggers = this.options.trigger.split(' ')

	    for (var i = triggers.length; i--;) {
	      var trigger = triggers[i]

	      if (trigger == 'click') {
	        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
	      } else if (trigger != 'manual') {
	        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
	        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'

	        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
	        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
	      }
	    }

	    this.options.selector ?
	      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
	      this.fixTitle()
	  }

	  Tooltip.prototype.getDefaults = function () {
	    return Tooltip.DEFAULTS
	  }

	  Tooltip.prototype.getOptions = function (options) {
	    options = $.extend({}, this.getDefaults(), this.$element.data(), options)

	    if (options.delay && typeof options.delay == 'number') {
	      options.delay = {
	        show: options.delay,
	        hide: options.delay
	      }
	    }

	    return options
	  }

	  Tooltip.prototype.getDelegateOptions = function () {
	    var options  = {}
	    var defaults = this.getDefaults()

	    this._options && $.each(this._options, function (key, value) {
	      if (defaults[key] != value) options[key] = value
	    })

	    return options
	  }

	  Tooltip.prototype.enter = function (obj) {
	    var self = obj instanceof this.constructor ?
	      obj : $(obj.currentTarget).data('bs.' + this.type)

	    if (!self) {
	      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
	      $(obj.currentTarget).data('bs.' + this.type, self)
	    }

	    if (obj instanceof $.Event) {
	      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
	    }

	    if (self.tip().hasClass('in') || self.hoverState == 'in') {
	      self.hoverState = 'in'
	      return
	    }

	    clearTimeout(self.timeout)

	    self.hoverState = 'in'

	    if (!self.options.delay || !self.options.delay.show) return self.show()

	    self.timeout = setTimeout(function () {
	      if (self.hoverState == 'in') self.show()
	    }, self.options.delay.show)
	  }

	  Tooltip.prototype.isInStateTrue = function () {
	    for (var key in this.inState) {
	      if (this.inState[key]) return true
	    }

	    return false
	  }

	  Tooltip.prototype.leave = function (obj) {
	    var self = obj instanceof this.constructor ?
	      obj : $(obj.currentTarget).data('bs.' + this.type)

	    if (!self) {
	      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
	      $(obj.currentTarget).data('bs.' + this.type, self)
	    }

	    if (obj instanceof $.Event) {
	      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
	    }

	    if (self.isInStateTrue()) return

	    clearTimeout(self.timeout)

	    self.hoverState = 'out'

	    if (!self.options.delay || !self.options.delay.hide) return self.hide()

	    self.timeout = setTimeout(function () {
	      if (self.hoverState == 'out') self.hide()
	    }, self.options.delay.hide)
	  }

	  Tooltip.prototype.show = function () {
	    var e = $.Event('show.bs.' + this.type)

	    if (this.hasContent() && this.enabled) {
	      this.$element.trigger(e)

	      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
	      if (e.isDefaultPrevented() || !inDom) return
	      var that = this

	      var $tip = this.tip()

	      var tipId = this.getUID(this.type)

	      this.setContent()
	      $tip.attr('id', tipId)
	      this.$element.attr('aria-describedby', tipId)

	      if (this.options.animation) $tip.addClass('fade')

	      var placement = typeof this.options.placement == 'function' ?
	        this.options.placement.call(this, $tip[0], this.$element[0]) :
	        this.options.placement

	      var autoToken = /\s?auto?\s?/i
	      var autoPlace = autoToken.test(placement)
	      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

	      $tip
	        .detach()
	        .css({ top: 0, left: 0, display: 'block' })
	        .addClass(placement)
	        .data('bs.' + this.type, this)

	      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
	      this.$element.trigger('inserted.bs.' + this.type)

	      var pos          = this.getPosition()
	      var actualWidth  = $tip[0].offsetWidth
	      var actualHeight = $tip[0].offsetHeight

	      if (autoPlace) {
	        var orgPlacement = placement
	        var viewportDim = this.getPosition(this.$viewport)

	        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
	                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
	                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
	                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
	                    placement

	        $tip
	          .removeClass(orgPlacement)
	          .addClass(placement)
	      }

	      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)

	      this.applyPlacement(calculatedOffset, placement)

	      var complete = function () {
	        var prevHoverState = that.hoverState
	        that.$element.trigger('shown.bs.' + that.type)
	        that.hoverState = null

	        if (prevHoverState == 'out') that.leave(that)
	      }

	      $.support.transition && this.$tip.hasClass('fade') ?
	        $tip
	          .one('bsTransitionEnd', complete)
	          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
	        complete()
	    }
	  }

	  Tooltip.prototype.applyPlacement = function (offset, placement) {
	    var $tip   = this.tip()
	    var width  = $tip[0].offsetWidth
	    var height = $tip[0].offsetHeight

	    // manually read margins because getBoundingClientRect includes difference
	    var marginTop = parseInt($tip.css('margin-top'), 10)
	    var marginLeft = parseInt($tip.css('margin-left'), 10)

	    // we must check for NaN for ie 8/9
	    if (isNaN(marginTop))  marginTop  = 0
	    if (isNaN(marginLeft)) marginLeft = 0

	    offset.top  += marginTop
	    offset.left += marginLeft

	    // $.fn.offset doesn't round pixel values
	    // so we use setOffset directly with our own function B-0
	    $.offset.setOffset($tip[0], $.extend({
	      using: function (props) {
	        $tip.css({
	          top: Math.round(props.top),
	          left: Math.round(props.left)
	        })
	      }
	    }, offset), 0)

	    $tip.addClass('in')

	    // check to see if placing tip in new offset caused the tip to resize itself
	    var actualWidth  = $tip[0].offsetWidth
	    var actualHeight = $tip[0].offsetHeight

	    if (placement == 'top' && actualHeight != height) {
	      offset.top = offset.top + height - actualHeight
	    }

	    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)

	    if (delta.left) offset.left += delta.left
	    else offset.top += delta.top

	    var isVertical          = /top|bottom/.test(placement)
	    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
	    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'

	    $tip.offset(offset)
	    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
	  }

	  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
	    this.arrow()
	      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
	      .css(isVertical ? 'top' : 'left', '')
	  }

	  Tooltip.prototype.setContent = function () {
	    var $tip  = this.tip()
	    var title = this.getTitle()

	    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
	    $tip.removeClass('fade in top bottom left right')
	  }

	  Tooltip.prototype.hide = function (callback) {
	    var that = this
	    var $tip = $(this.$tip)
	    var e    = $.Event('hide.bs.' + this.type)

	    function complete() {
	      if (that.hoverState != 'in') $tip.detach()
	      that.$element
	        .removeAttr('aria-describedby')
	        .trigger('hidden.bs.' + that.type)
	      callback && callback()
	    }

	    this.$element.trigger(e)

	    if (e.isDefaultPrevented()) return

	    $tip.removeClass('in')

	    $.support.transition && $tip.hasClass('fade') ?
	      $tip
	        .one('bsTransitionEnd', complete)
	        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
	      complete()

	    this.hoverState = null

	    return this
	  }

	  Tooltip.prototype.fixTitle = function () {
	    var $e = this.$element
	    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
	      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
	    }
	  }

	  Tooltip.prototype.hasContent = function () {
	    return this.getTitle()
	  }

	  Tooltip.prototype.getPosition = function ($element) {
	    $element   = $element || this.$element

	    var el     = $element[0]
	    var isBody = el.tagName == 'BODY'

	    var elRect    = el.getBoundingClientRect()
	    if (elRect.width == null) {
	      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
	      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
	    }
	    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
	    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
	    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null

	    return $.extend({}, elRect, scroll, outerDims, elOffset)
	  }

	  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
	    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
	           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
	           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
	        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }

	  }

	  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
	    var delta = { top: 0, left: 0 }
	    if (!this.$viewport) return delta

	    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
	    var viewportDimensions = this.getPosition(this.$viewport)

	    if (/right|left/.test(placement)) {
	      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
	      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
	      if (topEdgeOffset < viewportDimensions.top) { // top overflow
	        delta.top = viewportDimensions.top - topEdgeOffset
	      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
	        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
	      }
	    } else {
	      var leftEdgeOffset  = pos.left - viewportPadding
	      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
	      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
	        delta.left = viewportDimensions.left - leftEdgeOffset
	      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
	        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
	      }
	    }

	    return delta
	  }

	  Tooltip.prototype.getTitle = function () {
	    var title
	    var $e = this.$element
	    var o  = this.options

	    title = $e.attr('data-original-title')
	      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

	    return title
	  }

	  Tooltip.prototype.getUID = function (prefix) {
	    do prefix += ~~(Math.random() * 1000000)
	    while (document.getElementById(prefix))
	    return prefix
	  }

	  Tooltip.prototype.tip = function () {
	    if (!this.$tip) {
	      this.$tip = $(this.options.template)
	      if (this.$tip.length != 1) {
	        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
	      }
	    }
	    return this.$tip
	  }

	  Tooltip.prototype.arrow = function () {
	    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
	  }

	  Tooltip.prototype.enable = function () {
	    this.enabled = true
	  }

	  Tooltip.prototype.disable = function () {
	    this.enabled = false
	  }

	  Tooltip.prototype.toggleEnabled = function () {
	    this.enabled = !this.enabled
	  }

	  Tooltip.prototype.toggle = function (e) {
	    var self = this
	    if (e) {
	      self = $(e.currentTarget).data('bs.' + this.type)
	      if (!self) {
	        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
	        $(e.currentTarget).data('bs.' + this.type, self)
	      }
	    }

	    if (e) {
	      self.inState.click = !self.inState.click
	      if (self.isInStateTrue()) self.enter(self)
	      else self.leave(self)
	    } else {
	      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
	    }
	  }

	  Tooltip.prototype.destroy = function () {
	    var that = this
	    clearTimeout(this.timeout)
	    this.hide(function () {
	      that.$element.off('.' + that.type).removeData('bs.' + that.type)
	      if (that.$tip) {
	        that.$tip.detach()
	      }
	      that.$tip = null
	      that.$arrow = null
	      that.$viewport = null
	    })
	  }


	  // TOOLTIP PLUGIN DEFINITION
	  // =========================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.tooltip')
	      var options = typeof option == 'object' && option

	      if (!data && /destroy|hide/.test(option)) return
	      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
	      if (typeof option == 'string') data[option]()
	    })
	  }

	  var old = $.fn.tooltip

	  $.fn.tooltip             = Plugin
	  $.fn.tooltip.Constructor = Tooltip


	  // TOOLTIP NO CONFLICT
	  // ===================

	  $.fn.tooltip.noConflict = function () {
	    $.fn.tooltip = old
	    return this
	  }

	}(jQuery);


/***/ },
/* 21 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: popover.js v3.3.6
	 * http://getbootstrap.com/javascript/#popovers
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // POPOVER PUBLIC CLASS DEFINITION
	  // ===============================

	  var Popover = function (element, options) {
	    this.init('popover', element, options)
	  }

	  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')

	  Popover.VERSION  = '3.3.6'

	  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
	    placement: 'right',
	    trigger: 'click',
	    content: '',
	    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
	  })


	  // NOTE: POPOVER EXTENDS tooltip.js
	  // ================================

	  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)

	  Popover.prototype.constructor = Popover

	  Popover.prototype.getDefaults = function () {
	    return Popover.DEFAULTS
	  }

	  Popover.prototype.setContent = function () {
	    var $tip    = this.tip()
	    var title   = this.getTitle()
	    var content = this.getContent()

	    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
	    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
	      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
	    ](content)

	    $tip.removeClass('fade top bottom left right in')

	    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
	    // this manually by checking the contents.
	    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
	  }

	  Popover.prototype.hasContent = function () {
	    return this.getTitle() || this.getContent()
	  }

	  Popover.prototype.getContent = function () {
	    var $e = this.$element
	    var o  = this.options

	    return $e.attr('data-content')
	      || (typeof o.content == 'function' ?
	            o.content.call($e[0]) :
	            o.content)
	  }

	  Popover.prototype.arrow = function () {
	    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
	  }


	  // POPOVER PLUGIN DEFINITION
	  // =========================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.popover')
	      var options = typeof option == 'object' && option

	      if (!data && /destroy|hide/.test(option)) return
	      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
	      if (typeof option == 'string') data[option]()
	    })
	  }

	  var old = $.fn.popover

	  $.fn.popover             = Plugin
	  $.fn.popover.Constructor = Popover


	  // POPOVER NO CONFLICT
	  // ===================

	  $.fn.popover.noConflict = function () {
	    $.fn.popover = old
	    return this
	  }

	}(jQuery);


/***/ },
/* 22 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: scrollspy.js v3.3.6
	 * http://getbootstrap.com/javascript/#scrollspy
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // SCROLLSPY CLASS DEFINITION
	  // ==========================

	  function ScrollSpy(element, options) {
	    this.$body          = $(document.body)
	    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
	    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
	    this.selector       = (this.options.target || '') + ' .nav li > a'
	    this.offsets        = []
	    this.targets        = []
	    this.activeTarget   = null
	    this.scrollHeight   = 0

	    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
	    this.refresh()
	    this.process()
	  }

	  ScrollSpy.VERSION  = '3.3.6'

	  ScrollSpy.DEFAULTS = {
	    offset: 10
	  }

	  ScrollSpy.prototype.getScrollHeight = function () {
	    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
	  }

	  ScrollSpy.prototype.refresh = function () {
	    var that          = this
	    var offsetMethod  = 'offset'
	    var offsetBase    = 0

	    this.offsets      = []
	    this.targets      = []
	    this.scrollHeight = this.getScrollHeight()

	    if (!$.isWindow(this.$scrollElement[0])) {
	      offsetMethod = 'position'
	      offsetBase   = this.$scrollElement.scrollTop()
	    }

	    this.$body
	      .find(this.selector)
	      .map(function () {
	        var $el   = $(this)
	        var href  = $el.data('target') || $el.attr('href')
	        var $href = /^#./.test(href) && $(href)

	        return ($href
	          && $href.length
	          && $href.is(':visible')
	          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
	      })
	      .sort(function (a, b) { return a[0] - b[0] })
	      .each(function () {
	        that.offsets.push(this[0])
	        that.targets.push(this[1])
	      })
	  }

	  ScrollSpy.prototype.process = function () {
	    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
	    var scrollHeight = this.getScrollHeight()
	    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
	    var offsets      = this.offsets
	    var targets      = this.targets
	    var activeTarget = this.activeTarget
	    var i

	    if (this.scrollHeight != scrollHeight) {
	      this.refresh()
	    }

	    if (scrollTop >= maxScroll) {
	      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
	    }

	    if (activeTarget && scrollTop < offsets[0]) {
	      this.activeTarget = null
	      return this.clear()
	    }

	    for (i = offsets.length; i--;) {
	      activeTarget != targets[i]
	        && scrollTop >= offsets[i]
	        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
	        && this.activate(targets[i])
	    }
	  }

	  ScrollSpy.prototype.activate = function (target) {
	    this.activeTarget = target

	    this.clear()

	    var selector = this.selector +
	      '[data-target="' + target + '"],' +
	      this.selector + '[href="' + target + '"]'

	    var active = $(selector)
	      .parents('li')
	      .addClass('active')

	    if (active.parent('.dropdown-menu').length) {
	      active = active
	        .closest('li.dropdown')
	        .addClass('active')
	    }

	    active.trigger('activate.bs.scrollspy')
	  }

	  ScrollSpy.prototype.clear = function () {
	    $(this.selector)
	      .parentsUntil(this.options.target, '.active')
	      .removeClass('active')
	  }


	  // SCROLLSPY PLUGIN DEFINITION
	  // ===========================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.scrollspy')
	      var options = typeof option == 'object' && option

	      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
	      if (typeof option == 'string') data[option]()
	    })
	  }

	  var old = $.fn.scrollspy

	  $.fn.scrollspy             = Plugin
	  $.fn.scrollspy.Constructor = ScrollSpy


	  // SCROLLSPY NO CONFLICT
	  // =====================

	  $.fn.scrollspy.noConflict = function () {
	    $.fn.scrollspy = old
	    return this
	  }


	  // SCROLLSPY DATA-API
	  // ==================

	  $(window).on('load.bs.scrollspy.data-api', function () {
	    $('[data-spy="scroll"]').each(function () {
	      var $spy = $(this)
	      Plugin.call($spy, $spy.data())
	    })
	  })

	}(jQuery);


/***/ },
/* 23 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: tab.js v3.3.6
	 * http://getbootstrap.com/javascript/#tabs
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // TAB CLASS DEFINITION
	  // ====================

	  var Tab = function (element) {
	    // jscs:disable requireDollarBeforejQueryAssignment
	    this.element = $(element)
	    // jscs:enable requireDollarBeforejQueryAssignment
	  }

	  Tab.VERSION = '3.3.6'

	  Tab.TRANSITION_DURATION = 150

	  Tab.prototype.show = function () {
	    var $this    = this.element
	    var $ul      = $this.closest('ul:not(.dropdown-menu)')
	    var selector = $this.data('target')

	    if (!selector) {
	      selector = $this.attr('href')
	      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
	    }

	    if ($this.parent('li').hasClass('active')) return

	    var $previous = $ul.find('.active:last a')
	    var hideEvent = $.Event('hide.bs.tab', {
	      relatedTarget: $this[0]
	    })
	    var showEvent = $.Event('show.bs.tab', {
	      relatedTarget: $previous[0]
	    })

	    $previous.trigger(hideEvent)
	    $this.trigger(showEvent)

	    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return

	    var $target = $(selector)

	    this.activate($this.closest('li'), $ul)
	    this.activate($target, $target.parent(), function () {
	      $previous.trigger({
	        type: 'hidden.bs.tab',
	        relatedTarget: $this[0]
	      })
	      $this.trigger({
	        type: 'shown.bs.tab',
	        relatedTarget: $previous[0]
	      })
	    })
	  }

	  Tab.prototype.activate = function (element, container, callback) {
	    var $active    = container.find('> .active')
	    var transition = callback
	      && $.support.transition
	      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)

	    function next() {
	      $active
	        .removeClass('active')
	        .find('> .dropdown-menu > .active')
	          .removeClass('active')
	        .end()
	        .find('[data-toggle="tab"]')
	          .attr('aria-expanded', false)

	      element
	        .addClass('active')
	        .find('[data-toggle="tab"]')
	          .attr('aria-expanded', true)

	      if (transition) {
	        element[0].offsetWidth // reflow for transition
	        element.addClass('in')
	      } else {
	        element.removeClass('fade')
	      }

	      if (element.parent('.dropdown-menu').length) {
	        element
	          .closest('li.dropdown')
	            .addClass('active')
	          .end()
	          .find('[data-toggle="tab"]')
	            .attr('aria-expanded', true)
	      }

	      callback && callback()
	    }

	    $active.length && transition ?
	      $active
	        .one('bsTransitionEnd', next)
	        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
	      next()

	    $active.removeClass('in')
	  }


	  // TAB PLUGIN DEFINITION
	  // =====================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this = $(this)
	      var data  = $this.data('bs.tab')

	      if (!data) $this.data('bs.tab', (data = new Tab(this)))
	      if (typeof option == 'string') data[option]()
	    })
	  }

	  var old = $.fn.tab

	  $.fn.tab             = Plugin
	  $.fn.tab.Constructor = Tab


	  // TAB NO CONFLICT
	  // ===============

	  $.fn.tab.noConflict = function () {
	    $.fn.tab = old
	    return this
	  }


	  // TAB DATA-API
	  // ============

	  var clickHandler = function (e) {
	    e.preventDefault()
	    Plugin.call($(this), 'show')
	  }

	  $(document)
	    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
	    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)

	}(jQuery);


/***/ },
/* 24 */
/***/ function(module, exports) {

	/* ========================================================================
	 * Bootstrap: affix.js v3.3.6
	 * http://getbootstrap.com/javascript/#affix
	 * ========================================================================
	 * Copyright 2011-2015 Twitter, Inc.
	 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
	 * ======================================================================== */


	+function ($) {
	  'use strict';

	  // AFFIX CLASS DEFINITION
	  // ======================

	  var Affix = function (element, options) {
	    this.options = $.extend({}, Affix.DEFAULTS, options)

	    this.$target = $(this.options.target)
	      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
	      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))

	    this.$element     = $(element)
	    this.affixed      = null
	    this.unpin        = null
	    this.pinnedOffset = null

	    this.checkPosition()
	  }

	  Affix.VERSION  = '3.3.6'

	  Affix.RESET    = 'affix affix-top affix-bottom'

	  Affix.DEFAULTS = {
	    offset: 0,
	    target: window
	  }

	  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
	    var scrollTop    = this.$target.scrollTop()
	    var position     = this.$element.offset()
	    var targetHeight = this.$target.height()

	    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false

	    if (this.affixed == 'bottom') {
	      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
	      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
	    }

	    var initializing   = this.affixed == null
	    var colliderTop    = initializing ? scrollTop : position.top
	    var colliderHeight = initializing ? targetHeight : height

	    if (offsetTop != null && scrollTop <= offsetTop) return 'top'
	    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'

	    return false
	  }

	  Affix.prototype.getPinnedOffset = function () {
	    if (this.pinnedOffset) return this.pinnedOffset
	    this.$element.removeClass(Affix.RESET).addClass('affix')
	    var scrollTop = this.$target.scrollTop()
	    var position  = this.$element.offset()
	    return (this.pinnedOffset = position.top - scrollTop)
	  }

	  Affix.prototype.checkPositionWithEventLoop = function () {
	    setTimeout($.proxy(this.checkPosition, this), 1)
	  }

	  Affix.prototype.checkPosition = function () {
	    if (!this.$element.is(':visible')) return

	    var height       = this.$element.height()
	    var offset       = this.options.offset
	    var offsetTop    = offset.top
	    var offsetBottom = offset.bottom
	    var scrollHeight = Math.max($(document).height(), $(document.body).height())

	    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
	    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
	    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)

	    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)

	    if (this.affixed != affix) {
	      if (this.unpin != null) this.$element.css('top', '')

	      var affixType = 'affix' + (affix ? '-' + affix : '')
	      var e         = $.Event(affixType + '.bs.affix')

	      this.$element.trigger(e)

	      if (e.isDefaultPrevented()) return

	      this.affixed = affix
	      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null

	      this.$element
	        .removeClass(Affix.RESET)
	        .addClass(affixType)
	        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
	    }

	    if (affix == 'bottom') {
	      this.$element.offset({
	        top: scrollHeight - height - offsetBottom
	      })
	    }
	  }


	  // AFFIX PLUGIN DEFINITION
	  // =======================

	  function Plugin(option) {
	    return this.each(function () {
	      var $this   = $(this)
	      var data    = $this.data('bs.affix')
	      var options = typeof option == 'object' && option

	      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
	      if (typeof option == 'string') data[option]()
	    })
	  }

	  var old = $.fn.affix

	  $.fn.affix             = Plugin
	  $.fn.affix.Constructor = Affix


	  // AFFIX NO CONFLICT
	  // =================

	  $.fn.affix.noConflict = function () {
	    $.fn.affix = old
	    return this
	  }


	  // AFFIX DATA-API
	  // ==============

	  $(window).on('load', function () {
	    $('[data-spy="affix"]').each(function () {
	      var $spy = $(this)
	      var data = $spy.data()

	      data.offset = data.offset || {}

	      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
	      if (data.offsetTop    != null) data.offset.top    = data.offsetTop

	      Plugin.call($spy, data)
	    })
	  })

	}(jQuery);


/***/ },
/* 25 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict';

	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

	/*!
	 * jQuery Mousewheel 3.1.13
	 *
	 * Copyright jQuery Foundation and other contributors
	 * Released under the MIT license
	 * http://jquery.org/license
	 */

	(function (factory) {
	  if (true) {
	    // AMD. Register as an anonymous module.
	    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__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__));
	  } else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
	    // Node/CommonJS style for Browserify
	    module.exports = factory;
	  } else {
	    // Browser globals
	    factory(jQuery);
	  }
	})(function ($) {

	  var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
	      toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
	      slice = Array.prototype.slice,
	      nullLowestDeltaTimeout,
	      lowestDelta;

	  if ($.event.fixHooks) {
	    for (var i = toFix.length; i;) {
	      $.event.fixHooks[toFix[--i]] = $.event.mouseHooks;
	    }
	  }

	  var special = $.event.special.mousewheel = {
	    version: '3.1.12',

	    setup: function setup() {
	      if (this.addEventListener) {
	        for (var i = toBind.length; i;) {
	          this.addEventListener(toBind[--i], handler, false);
	        }
	      } else {
	        this.onmousewheel = handler;
	      }
	      // Store the line height and page height for this particular element
	      $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
	      $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
	    },

	    teardown: function teardown() {
	      if (this.removeEventListener) {
	        for (var i = toBind.length; i;) {
	          this.removeEventListener(toBind[--i], handler, false);
	        }
	      } else {
	        this.onmousewheel = null;
	      }
	      // Clean up the data we added to the element
	      $.removeData(this, 'mousewheel-line-height');
	      $.removeData(this, 'mousewheel-page-height');
	    },

	    getLineHeight: function getLineHeight(elem) {
	      var $elem = $(elem),
	          $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
	      if (!$parent.length) {
	        $parent = $('body');
	      }
	      return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
	    },

	    getPageHeight: function getPageHeight(elem) {
	      return $(elem).height();
	    },

	    settings: {
	      adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
	      normalizeOffset: true // calls getBoundingClientRect for each event
	    }
	  };

	  $.fn.extend({
	    mousewheel: function mousewheel(fn) {
	      return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
	    },

	    unmousewheel: function unmousewheel(fn) {
	      return this.unbind('mousewheel', fn);
	    }
	  });

	  function handler(event) {
	    var orgEvent = event || window.event,
	        args = slice.call(arguments, 1),
	        delta = 0,
	        deltaX = 0,
	        deltaY = 0,
	        absDelta = 0,
	        offsetX = 0,
	        offsetY = 0;
	    event = $.event.fix(orgEvent);
	    event.type = 'mousewheel';

	    // Old school scrollwheel delta
	    if ('detail' in orgEvent) {
	      deltaY = orgEvent.detail * -1;
	    }
	    if ('wheelDelta' in orgEvent) {
	      deltaY = orgEvent.wheelDelta;
	    }
	    if ('wheelDeltaY' in orgEvent) {
	      deltaY = orgEvent.wheelDeltaY;
	    }
	    if ('wheelDeltaX' in orgEvent) {
	      deltaX = orgEvent.wheelDeltaX * -1;
	    }

	    // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
	    if ('axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
	      deltaX = deltaY * -1;
	      deltaY = 0;
	    }

	    // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
	    delta = deltaY === 0 ? deltaX : deltaY;

	    // New school wheel delta (wheel event)
	    if ('deltaY' in orgEvent) {
	      deltaY = orgEvent.deltaY * -1;
	      delta = deltaY;
	    }
	    if ('deltaX' in orgEvent) {
	      deltaX = orgEvent.deltaX;
	      if (deltaY === 0) {
	        delta = deltaX * -1;
	      }
	    }

	    // No change actually happened, no reason to go any further
	    if (deltaY === 0 && deltaX === 0) {
	      return;
	    }

	    // Need to convert lines and pages to pixels if we aren't already in pixels
	    // There are three delta modes:
	    //   * deltaMode 0 is by pixels, nothing to do
	    //   * deltaMode 1 is by lines
	    //   * deltaMode 2 is by pages
	    if (orgEvent.deltaMode === 1) {
	      var lineHeight = $.data(this, 'mousewheel-line-height');
	      delta *= lineHeight;
	      deltaY *= lineHeight;
	      deltaX *= lineHeight;
	    } else if (orgEvent.deltaMode === 2) {
	      var pageHeight = $.data(this, 'mousewheel-page-height');
	      delta *= pageHeight;
	      deltaY *= pageHeight;
	      deltaX *= pageHeight;
	    }

	    // Store lowest absolute delta to normalize the delta values
	    absDelta = Math.max(Math.abs(deltaY), Math.abs(deltaX));

	    if (!lowestDelta || absDelta < lowestDelta) {
	      lowestDelta = absDelta;

	      // Adjust older deltas if necessary
	      if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
	        lowestDelta /= 40;
	      }
	    }

	    // Adjust older deltas if necessary
	    if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
	      // Divide all the things by 40!
	      delta /= 40;
	      deltaX /= 40;
	      deltaY /= 40;
	    }

	    // Get a whole, normalized value for the deltas
	    delta = Math[delta >= 1 ? 'floor' : 'ceil'](delta / lowestDelta);
	    deltaX = Math[deltaX >= 1 ? 'floor' : 'ceil'](deltaX / lowestDelta);
	    deltaY = Math[deltaY >= 1 ? 'floor' : 'ceil'](deltaY / lowestDelta);

	    // Normalise offsetX and offsetY properties
	    if (special.settings.normalizeOffset && this.getBoundingClientRect) {
	      var boundingRect = this.getBoundingClientRect();
	      offsetX = event.clientX - boundingRect.left;
	      offsetY = event.clientY - boundingRect.top;
	    }

	    // Add information to the event object
	    event.deltaX = deltaX;
	    event.deltaY = deltaY;
	    event.deltaFactor = lowestDelta;
	    event.offsetX = offsetX;
	    event.offsetY = offsetY;
	    // Go ahead and set deltaMode to 0 since we converted to pixels
	    // Although this is a little odd since we overwrite the deltaX/Y
	    // properties with normalized deltas.
	    event.deltaMode = 0;

	    // Add event and delta to the front of the arguments
	    args.unshift(event, delta, deltaX, deltaY);

	    // Clearout lowestDelta after sometime to better
	    // handle multiple device types that give different
	    // a different lowestDelta
	    // Ex: trackpad = 3 and mouse wheel = 120
	    if (nullLowestDeltaTimeout) {
	      clearTimeout(nullLowestDeltaTimeout);
	    }
	    nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);

	    return ($.event.dispatch || $.event.handle).apply(this, args);
	  }

	  function nullLowestDelta() {
	    lowestDelta = null;
	  }

	  function shouldAdjustOldDeltas(orgEvent, absDelta) {
	    // If this is an older event and the delta is divisable by 120,
	    // then we are assuming that the browser is treating this as an
	    // older mouse wheel event and that we should divide the deltas
	    // by 40 to try and get a more usable deltaFactor.
	    // Side note, this actually impacts the reported scroll distance
	    // in older browsers and can cause scrolling to be slower than native.
	    // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
	    return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
	  }
	});

/***/ },
/* 26 */
/***/ function(module, exports) {

	'use strict';

	//define(['jquery'], function(jQuery) {
	(function ($) {

	  var cocoon_element_counter = 0;

	  var create_new_id = function create_new_id() {
	    return new Date().getTime() + cocoon_element_counter++;
	  };

	  var newcontent_braced = function newcontent_braced(id) {
	    return '[' + id + ']$1';
	  };

	  var newcontent_underscord = function newcontent_underscord(id) {
	    return '_' + id + '_$1';
	  };

	  $(document).on('click', '.add_fields', function (e) {
	    e.preventDefault();
	    var $this = $(this),
	        assoc = $this.data('association'),
	        assocs = $this.data('associations'),
	        content = $this.data('association-insertion-template'),
	        insertionMethod = $this.data('association-insertion-method') || $this.data('association-insertion-position') || 'before',
	        insertionNode = $this.data('association-insertion-node'),
	        insertionTraversal = $this.data('association-insertion-traversal'),
	        count = parseInt($this.data('count'), 10),
	        regexp_braced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g'),
	        regexp_underscord = new RegExp('_new_' + assoc + '_(\\w*)', 'g'),
	        new_id = create_new_id(),
	        new_content = content.replace(regexp_braced, newcontent_braced(new_id)),
	        new_contents = [];

	    if (new_content == content) {
	      regexp_braced = new RegExp('\\[new_' + assocs + '\\](.*?\\s)', 'g');
	      regexp_underscord = new RegExp('_new_' + assocs + '_(\\w*)', 'g');
	      new_content = content.replace(regexp_braced, newcontent_braced(new_id));
	    }

	    new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
	    new_contents = [new_content];

	    count = isNaN(count) ? 1 : Math.max(count, 1);
	    count -= 1;

	    while (count) {
	      new_id = create_new_id();
	      new_content = content.replace(regexp_braced, newcontent_braced(new_id));
	      new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
	      new_contents.push(new_content);

	      count -= 1;
	    }

	    if (insertionNode) {
	      if (insertionTraversal) {
	        insertionNode = $this[insertionTraversal](insertionNode);
	      } else {
	        insertionNode = insertionNode == "this" ? $this : $(insertionNode);
	      }
	    } else {
	      insertionNode = $this.parent();
	    }

	    $.each(new_contents, function (i, node) {
	      var contentNode = $(node);

	      insertionNode.trigger('cocoon:before-insert', [contentNode]);

	      // allow any of the jquery dom manipulation methods (after, before, append, prepend, etc)
	      // to be called on the node.  allows the insertion node to be the parent of the inserted
	      // code and doesn't force it to be a sibling like after/before does. default: 'before'
	      var addedContent = insertionNode[insertionMethod](contentNode);

	      insertionNode.trigger('cocoon:after-insert', [contentNode]);
	    });
	  });

	  $(document).on('click', '.remove_fields.dynamic, .remove_fields.existing', function (e) {
	    var $this = $(this),
	        wrapper_class = $this.data('wrapper-class') || 'nested-fields',
	        node_to_delete = $this.closest('.' + wrapper_class),
	        trigger_node = node_to_delete.parent();

	    e.preventDefault();

	    trigger_node.trigger('cocoon:before-remove', [node_to_delete]);

	    var timeout = trigger_node.data('remove-timeout') || 0;

	    setTimeout(function () {
	      if ($this.hasClass('dynamic')) {
	        node_to_delete.remove();
	      } else {
	        $this.prev("input[type=hidden]").val("1");
	        node_to_delete.hide();
	      }
	      trigger_node.trigger('cocoon:after-remove', [node_to_delete]);
	    }, timeout);
	  });

	  $('.remove_fields.existing.destroyed').each(function (i, obj) {
	    var $this = $(this),
	        wrapper_class = $this.data('wrapper-class') || 'nested-fields';

	    $this.closest('.' + wrapper_class).hide();
	  });
	})(jQuery);
	//});

/***/ },
/* 27 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _reactDom = __webpack_require__(64);

	var _reactDom2 = _interopRequireDefault(_reactDom);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	;(function (document, window) {
	  // jQuery is optional. Use it to support legacy browsers.
	  var $ = typeof window.jQuery !== 'undefined' && window.jQuery;

	  window.ReactRailsUJS = {
	    // This attribute holds the name of component which should be mounted
	    // example: `data-react-class="MyApp.Items.EditForm"`
	    CLASS_NAME_ATTR: 'data-react-class',

	    // This attribute holds JSON stringified props for initializing the component
	    // example: `data-react-props="{\"item\": { \"id\": 1, \"name\": \"My Item\"} }"`
	    PROPS_ATTR: 'data-react-props',

	    // helper method for the mount and unmount methods to find the
	    // `data-react-class` DOM elements
	    findDOMNodes: function findDOMNodes(searchSelector) {
	      // we will use fully qualified paths as we do not bind the callbacks
	      var selector, parent;

	      switch (typeof searchSelector === 'undefined' ? 'undefined' : _typeof(searchSelector)) {
	        case 'undefined':
	          selector = '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
	          parent = document;
	          break;
	        case 'object':
	          selector = '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
	          parent = searchSelector;
	          break;
	        case 'string':
	          selector = searchSelector + '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + '], ' + searchSelector + ' [' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
	          parent = document;
	          break;
	        default:
	          break;
	      }

	      if ($) {
	        return $(selector, parent);
	      } else {
	        return parent.querySelectorAll(selector);
	      }
	    },

	    // Get the constructor for a className
	    getConstructor: function getConstructor(className) {
	      // Assume className is simple and can be found at top-level (window).
	      // Fallback to eval to handle cases like 'My.React.ComponentName'.
	      // Also, try to gracefully import Babel 6 style default exports
	      //
	      var constructor;

	      // Try to access the class globally first
	      constructor = window[className];

	      // If that didn't work, try eval
	      if (!constructor) {
	        constructor = eval.call(window, className);
	      }

	      // Lastly, if there is a default attribute try that
	      if (constructor && constructor.default) {
	        constructor = constructor.default;
	      }

	      return constructor;
	    },

	    // Within `searchSelector`, find nodes which should have React components
	    // inside them, and mount them with their props.
	    mountComponents: function mountComponents(searchSelector) {
	      var nodes = window.ReactRailsUJS.findDOMNodes(searchSelector);
	      for (var i = 0; i < nodes.length; ++i) {
	        var node = nodes[i];
	        var className = node.getAttribute(window.ReactRailsUJS.CLASS_NAME_ATTR);
	        var constructor = this.getConstructor(className);
	        var propsJson = node.getAttribute(window.ReactRailsUJS.PROPS_ATTR);
	        var props = propsJson && JSON.parse(propsJson);

	        if (typeof constructor === "undefined") {
	          var message = "Cannot find component: '" + className + "'";
	          if (console && console.log) {
	            console.log("%c[react-rails] %c" + message + " for element", "font-weight: bold", "", node);
	          }
	          var error = new Error(message + ". Make sure your component is globally available to render.");
	          throw error;
	        } else {
	          _reactDom2.default.render(_react2.default.createElement(constructor, props), node);
	        }
	      }
	    },

	    // Within `searchSelector`, find nodes which have React components
	    // inside them, and unmount those components.
	    unmountComponents: function unmountComponents(searchSelector) {
	      var nodes = window.ReactRailsUJS.findDOMNodes(searchSelector);

	      for (var i = 0; i < nodes.length; ++i) {
	        var node = nodes[i];

	        _reactDom2.default.unmountComponentAtNode(node);
	      }
	    }
	  };
	})(document, window);

/***/ },
/* 28 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	module.exports = __webpack_require__(29);


/***/ },
/* 29 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var ReactBaseClasses = __webpack_require__(32);
	var ReactChildren = __webpack_require__(41);
	var ReactDOMFactories = __webpack_require__(49);
	var ReactElement = __webpack_require__(43);
	var ReactPropTypes = __webpack_require__(55);
	var ReactVersion = __webpack_require__(60);

	var createReactClass = __webpack_require__(61);
	var onlyChild = __webpack_require__(63);

	var createElement = ReactElement.createElement;
	var createFactory = ReactElement.createFactory;
	var cloneElement = ReactElement.cloneElement;

	if (process.env.NODE_ENV !== 'production') {
	  var lowPriorityWarning = __webpack_require__(40);
	  var canDefineProperty = __webpack_require__(37);
	  var ReactElementValidator = __webpack_require__(50);
	  var didWarnPropTypesDeprecated = false;
	  createElement = ReactElementValidator.createElement;
	  createFactory = ReactElementValidator.createFactory;
	  cloneElement = ReactElementValidator.cloneElement;
	}

	var __spread = _assign;
	var createMixin = function (mixin) {
	  return mixin;
	};

	if (process.env.NODE_ENV !== 'production') {
	  var warnedForSpread = false;
	  var warnedForCreateMixin = false;
	  __spread = function () {
	    lowPriorityWarning(warnedForSpread, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.');
	    warnedForSpread = true;
	    return _assign.apply(null, arguments);
	  };

	  createMixin = function (mixin) {
	    lowPriorityWarning(warnedForCreateMixin, 'React.createMixin is deprecated and should not be used. ' + 'In React v16.0, it will be removed. ' + 'You can use this mixin directly instead. ' + 'See https://fb.me/createmixin-was-never-implemented for more info.');
	    warnedForCreateMixin = true;
	    return mixin;
	  };
	}

	var React = {
	  // Modern

	  Children: {
	    map: ReactChildren.map,
	    forEach: ReactChildren.forEach,
	    count: ReactChildren.count,
	    toArray: ReactChildren.toArray,
	    only: onlyChild
	  },

	  Component: ReactBaseClasses.Component,
	  PureComponent: ReactBaseClasses.PureComponent,

	  createElement: createElement,
	  cloneElement: cloneElement,
	  isValidElement: ReactElement.isValidElement,

	  // Classic

	  PropTypes: ReactPropTypes,
	  createClass: createReactClass,
	  createFactory: createFactory,
	  createMixin: createMixin,

	  // This looks DOM specific but these are actually isomorphic helpers
	  // since they are just generating DOM strings.
	  DOM: ReactDOMFactories,

	  version: ReactVersion,

	  // Deprecated hook for JSX spread, don't use this for anything.
	  __spread: __spread
	};

	if (process.env.NODE_ENV !== 'production') {
	  var warnedForCreateClass = false;
	  if (canDefineProperty) {
	    Object.defineProperty(React, 'PropTypes', {
	      get: function () {
	        lowPriorityWarning(didWarnPropTypesDeprecated, 'Accessing PropTypes via the main React package is deprecated,' + ' and will be removed in  React v16.0.' + ' Use the latest available v15.* prop-types package from npm instead.' + ' For info on usage, compatibility, migration and more, see ' + 'https://fb.me/prop-types-docs');
	        didWarnPropTypesDeprecated = true;
	        return ReactPropTypes;
	      }
	    });

	    Object.defineProperty(React, 'createClass', {
	      get: function () {
	        lowPriorityWarning(warnedForCreateClass, 'Accessing createClass via the main React package is deprecated,' + ' and will be removed in React v16.0.' + " Use a plain JavaScript class instead. If you're not yet " + 'ready to migrate, create-react-class v15.* is available ' + 'on npm as a temporary, drop-in replacement. ' + 'For more info see https://fb.me/react-create-class');
	        warnedForCreateClass = true;
	        return createReactClass;
	      }
	    });
	  }

	  // React.DOM factories are deprecated. Wrap these methods so that
	  // invocations of the React.DOM namespace and alert users to switch
	  // to the `react-dom-factories` package.
	  React.DOM = {};
	  var warnedForFactories = false;
	  Object.keys(ReactDOMFactories).forEach(function (factory) {
	    React.DOM[factory] = function () {
	      if (!warnedForFactories) {
	        lowPriorityWarning(false, 'Accessing factories like React.DOM.%s has been deprecated ' + 'and will be removed in v16.0+. Use the ' + 'react-dom-factories package instead. ' + ' Version 1.0 provides a drop-in replacement.' + ' For more info, see https://fb.me/react-dom-factories', factory);
	        warnedForFactories = true;
	      }
	      return ReactDOMFactories[factory].apply(ReactDOMFactories, arguments);
	    };
	  });
	}

	module.exports = React;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 30 */
/***/ function(module, exports) {

	// shim for using process in browser
	var process = module.exports = {};

	// cached from whatever global is present so that test runners that stub it
	// don't break things.  But we need to wrap it in a try catch in case it is
	// wrapped in strict mode code which doesn't define any globals.  It's inside a
	// function because try/catches deoptimize in certain engines.

	var cachedSetTimeout;
	var cachedClearTimeout;

	function defaultSetTimout() {
	    throw new Error('setTimeout has not been defined');
	}
	function defaultClearTimeout () {
	    throw new Error('clearTimeout has not been defined');
	}
	(function () {
	    try {
	        if (typeof setTimeout === 'function') {
	            cachedSetTimeout = setTimeout;
	        } else {
	            cachedSetTimeout = defaultSetTimout;
	        }
	    } catch (e) {
	        cachedSetTimeout = defaultSetTimout;
	    }
	    try {
	        if (typeof clearTimeout === 'function') {
	            cachedClearTimeout = clearTimeout;
	        } else {
	            cachedClearTimeout = defaultClearTimeout;
	        }
	    } catch (e) {
	        cachedClearTimeout = defaultClearTimeout;
	    }
	} ())
	function runTimeout(fun) {
	    if (cachedSetTimeout === setTimeout) {
	        //normal enviroments in sane situations
	        return setTimeout(fun, 0);
	    }
	    // if setTimeout wasn't available but was latter defined
	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
	        cachedSetTimeout = setTimeout;
	        return setTimeout(fun, 0);
	    }
	    try {
	        // when when somebody has screwed with setTimeout but no I.E. maddness
	        return cachedSetTimeout(fun, 0);
	    } catch(e){
	        try {
	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
	            return cachedSetTimeout.call(null, fun, 0);
	        } catch(e){
	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
	            return cachedSetTimeout.call(this, fun, 0);
	        }
	    }


	}
	function runClearTimeout(marker) {
	    if (cachedClearTimeout === clearTimeout) {
	        //normal enviroments in sane situations
	        return clearTimeout(marker);
	    }
	    // if clearTimeout wasn't available but was latter defined
	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
	        cachedClearTimeout = clearTimeout;
	        return clearTimeout(marker);
	    }
	    try {
	        // when when somebody has screwed with setTimeout but no I.E. maddness
	        return cachedClearTimeout(marker);
	    } catch (e){
	        try {
	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
	            return cachedClearTimeout.call(null, marker);
	        } catch (e){
	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
	            return cachedClearTimeout.call(this, marker);
	        }
	    }



	}
	var queue = [];
	var draining = false;
	var currentQueue;
	var queueIndex = -1;

	function cleanUpNextTick() {
	    if (!draining || !currentQueue) {
	        return;
	    }
	    draining = false;
	    if (currentQueue.length) {
	        queue = currentQueue.concat(queue);
	    } else {
	        queueIndex = -1;
	    }
	    if (queue.length) {
	        drainQueue();
	    }
	}

	function drainQueue() {
	    if (draining) {
	        return;
	    }
	    var timeout = runTimeout(cleanUpNextTick);
	    draining = true;

	    var len = queue.length;
	    while(len) {
	        currentQueue = queue;
	        queue = [];
	        while (++queueIndex < len) {
	            if (currentQueue) {
	                currentQueue[queueIndex].run();
	            }
	        }
	        queueIndex = -1;
	        len = queue.length;
	    }
	    currentQueue = null;
	    draining = false;
	    runClearTimeout(timeout);
	}

	process.nextTick = function (fun) {
	    var args = new Array(arguments.length - 1);
	    if (arguments.length > 1) {
	        for (var i = 1; i < arguments.length; i++) {
	            args[i - 1] = arguments[i];
	        }
	    }
	    queue.push(new Item(fun, args));
	    if (queue.length === 1 && !draining) {
	        runTimeout(drainQueue);
	    }
	};

	// v8 likes predictible objects
	function Item(fun, array) {
	    this.fun = fun;
	    this.array = array;
	}
	Item.prototype.run = function () {
	    this.fun.apply(null, this.array);
	};
	process.title = 'browser';
	process.browser = true;
	process.env = {};
	process.argv = [];
	process.version = ''; // empty string to avoid regexp issues
	process.versions = {};

	function noop() {}

	process.on = noop;
	process.addListener = noop;
	process.once = noop;
	process.off = noop;
	process.removeListener = noop;
	process.removeAllListeners = noop;
	process.emit = noop;
	process.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; };


/***/ },
/* 31 */
/***/ function(module, exports) {

	/*
	object-assign
	(c) Sindre Sorhus
	@license MIT
	*/

	'use strict';
	/* eslint-disable no-unused-vars */
	var getOwnPropertySymbols = Object.getOwnPropertySymbols;
	var hasOwnProperty = Object.prototype.hasOwnProperty;
	var propIsEnumerable = Object.prototype.propertyIsEnumerable;

	function toObject(val) {
		if (val === null || val === undefined) {
			throw new TypeError('Object.assign cannot be called with null or undefined');
		}

		return Object(val);
	}

	function shouldUseNative() {
		try {
			if (!Object.assign) {
				return false;
			}

			// Detect buggy property enumeration order in older V8 versions.

			// https://bugs.chromium.org/p/v8/issues/detail?id=4118
			var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
			test1[5] = 'de';
			if (Object.getOwnPropertyNames(test1)[0] === '5') {
				return false;
			}

			// https://bugs.chromium.org/p/v8/issues/detail?id=3056
			var test2 = {};
			for (var i = 0; i < 10; i++) {
				test2['_' + String.fromCharCode(i)] = i;
			}
			var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
				return test2[n];
			});
			if (order2.join('') !== '0123456789') {
				return false;
			}

			// https://bugs.chromium.org/p/v8/issues/detail?id=3056
			var test3 = {};
			'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
				test3[letter] = letter;
			});
			if (Object.keys(Object.assign({}, test3)).join('') !==
					'abcdefghijklmnopqrst') {
				return false;
			}

			return true;
		} catch (err) {
			// We don't expect any of the above to throw, but better to be safe.
			return false;
		}
	}

	module.exports = shouldUseNative() ? Object.assign : function (target, source) {
		var from;
		var to = toObject(target);
		var symbols;

		for (var s = 1; s < arguments.length; s++) {
			from = Object(arguments[s]);

			for (var key in from) {
				if (hasOwnProperty.call(from, key)) {
					to[key] = from[key];
				}
			}

			if (getOwnPropertySymbols) {
				symbols = getOwnPropertySymbols(from);
				for (var i = 0; i < symbols.length; i++) {
					if (propIsEnumerable.call(from, symbols[i])) {
						to[symbols[i]] = from[symbols[i]];
					}
				}
			}
		}

		return to;
	};


/***/ },
/* 32 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(33),
	    _assign = __webpack_require__(31);

	var ReactNoopUpdateQueue = __webpack_require__(34);

	var canDefineProperty = __webpack_require__(37);
	var emptyObject = __webpack_require__(38);
	var invariant = __webpack_require__(39);
	var lowPriorityWarning = __webpack_require__(40);

	/**
	 * Base class helpers for the updating state of a component.
	 */
	function ReactComponent(props, context, updater) {
	  this.props = props;
	  this.context = context;
	  this.refs = emptyObject;
	  // We initialize the default updater but the real one gets injected by the
	  // renderer.
	  this.updater = updater || ReactNoopUpdateQueue;
	}

	ReactComponent.prototype.isReactComponent = {};

	/**
	 * Sets a subset of the state. Always use this to mutate
	 * state. You should treat `this.state` as immutable.
	 *
	 * There is no guarantee that `this.state` will be immediately updated, so
	 * accessing `this.state` after calling this method may return the old value.
	 *
	 * There is no guarantee that calls to `setState` will run synchronously,
	 * as they may eventually be batched together.  You can provide an optional
	 * callback that will be executed when the call to setState is actually
	 * completed.
	 *
	 * When a function is provided to setState, it will be called at some point in
	 * the future (not synchronously). It will be called with the up to date
	 * component arguments (state, props, context). These values can be different
	 * from this.* because your function may be called after receiveProps but before
	 * shouldComponentUpdate, and this new state, props, and context will not yet be
	 * assigned to this.
	 *
	 * @param {object|function} partialState Next partial state or function to
	 *        produce next partial state to be merged with current state.
	 * @param {?function} callback Called after state is updated.
	 * @final
	 * @protected
	 */
	ReactComponent.prototype.setState = function (partialState, callback) {
	  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;
	  this.updater.enqueueSetState(this, partialState);
	  if (callback) {
	    this.updater.enqueueCallback(this, callback, 'setState');
	  }
	};

	/**
	 * Forces an update. This should only be invoked when it is known with
	 * certainty that we are **not** in a DOM transaction.
	 *
	 * You may want to call this when you know that some deeper aspect of the
	 * component's state has changed but `setState` was not called.
	 *
	 * This will not invoke `shouldComponentUpdate`, but it will invoke
	 * `componentWillUpdate` and `componentDidUpdate`.
	 *
	 * @param {?function} callback Called after update is complete.
	 * @final
	 * @protected
	 */
	ReactComponent.prototype.forceUpdate = function (callback) {
	  this.updater.enqueueForceUpdate(this);
	  if (callback) {
	    this.updater.enqueueCallback(this, callback, 'forceUpdate');
	  }
	};

	/**
	 * Deprecated APIs. These APIs used to exist on classic React classes but since
	 * we would like to deprecate them, we're not going to move them over to this
	 * modern base class. Instead, we define a getter that warns if it's accessed.
	 */
	if (process.env.NODE_ENV !== 'production') {
	  var deprecatedAPIs = {
	    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
	    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']
	  };
	  var defineDeprecationWarning = function (methodName, info) {
	    if (canDefineProperty) {
	      Object.defineProperty(ReactComponent.prototype, methodName, {
	        get: function () {
	          lowPriorityWarning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]);
	          return undefined;
	        }
	      });
	    }
	  };
	  for (var fnName in deprecatedAPIs) {
	    if (deprecatedAPIs.hasOwnProperty(fnName)) {
	      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
	    }
	  }
	}

	/**
	 * Base class helpers for the updating state of a component.
	 */
	function ReactPureComponent(props, context, updater) {
	  // Duplicated from ReactComponent.
	  this.props = props;
	  this.context = context;
	  this.refs = emptyObject;
	  // We initialize the default updater but the real one gets injected by the
	  // renderer.
	  this.updater = updater || ReactNoopUpdateQueue;
	}

	function ComponentDummy() {}
	ComponentDummy.prototype = ReactComponent.prototype;
	ReactPureComponent.prototype = new ComponentDummy();
	ReactPureComponent.prototype.constructor = ReactPureComponent;
	// Avoid an extra prototype jump for these methods.
	_assign(ReactPureComponent.prototype, ReactComponent.prototype);
	ReactPureComponent.prototype.isPureReactComponent = true;

	module.exports = {
	  Component: ReactComponent,
	  PureComponent: ReactPureComponent
	};
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 33 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */
	'use strict';

	/**
	 * WARNING: DO NOT manually require this module.
	 * This is a replacement for `invariant(...)` used by the error code system
	 * and will _only_ be required by the corresponding babel pass.
	 * It always throws.
	 */

	function reactProdInvariant(code) {
	  var argCount = arguments.length - 1;

	  var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;

	  for (var argIdx = 0; argIdx < argCount; argIdx++) {
	    message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
	  }

	  message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';

	  var error = new Error(message);
	  error.name = 'Invariant Violation';
	  error.framesToPop = 1; // we don't care about reactProdInvariant's own frame

	  throw error;
	}

	module.exports = reactProdInvariant;

/***/ },
/* 34 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2015-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var warning = __webpack_require__(35);

	function warnNoop(publicInstance, callerName) {
	  if (process.env.NODE_ENV !== 'production') {
	    var constructor = publicInstance.constructor;
	    process.env.NODE_ENV !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;
	  }
	}

	/**
	 * This is the abstract API for an update queue.
	 */
	var ReactNoopUpdateQueue = {
	  /**
	   * Checks whether or not this composite component is mounted.
	   * @param {ReactClass} publicInstance The instance we want to test.
	   * @return {boolean} True if mounted, false otherwise.
	   * @protected
	   * @final
	   */
	  isMounted: function (publicInstance) {
	    return false;
	  },

	  /**
	   * Enqueue a callback that will be executed after all the pending updates
	   * have processed.
	   *
	   * @param {ReactClass} publicInstance The instance to use as `this` context.
	   * @param {?function} callback Called after state is updated.
	   * @internal
	   */
	  enqueueCallback: function (publicInstance, callback) {},

	  /**
	   * Forces an update. This should only be invoked when it is known with
	   * certainty that we are **not** in a DOM transaction.
	   *
	   * You may want to call this when you know that some deeper aspect of the
	   * component's state has changed but `setState` was not called.
	   *
	   * This will not invoke `shouldComponentUpdate`, but it will invoke
	   * `componentWillUpdate` and `componentDidUpdate`.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @internal
	   */
	  enqueueForceUpdate: function (publicInstance) {
	    warnNoop(publicInstance, 'forceUpdate');
	  },

	  /**
	   * Replaces all of the state. Always use this or `setState` to mutate state.
	   * You should treat `this.state` as immutable.
	   *
	   * There is no guarantee that `this.state` will be immediately updated, so
	   * accessing `this.state` after calling this method may return the old value.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @param {object} completeState Next state.
	   * @internal
	   */
	  enqueueReplaceState: function (publicInstance, completeState) {
	    warnNoop(publicInstance, 'replaceState');
	  },

	  /**
	   * Sets a subset of the state. This only exists because _pendingState is
	   * internal. This provides a merging strategy that is not available to deep
	   * properties which is confusing. TODO: Expose pendingState or don't use it
	   * during the merge.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @param {object} partialState Next partial state to be merged with state.
	   * @internal
	   */
	  enqueueSetState: function (publicInstance, partialState) {
	    warnNoop(publicInstance, 'setState');
	  }
	};

	module.exports = ReactNoopUpdateQueue;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 35 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var emptyFunction = __webpack_require__(36);

	/**
	 * Similar to invariant but only logs a warning if the condition is not met.
	 * This can be used to log issues in development environments in critical
	 * paths. Removing the logging code for production environments will keep the
	 * same logic and follow the same code paths.
	 */

	var warning = emptyFunction;

	if (process.env.NODE_ENV !== 'production') {
	  var printWarning = function printWarning(format) {
	    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
	      args[_key - 1] = arguments[_key];
	    }

	    var argIndex = 0;
	    var message = 'Warning: ' + format.replace(/%s/g, function () {
	      return args[argIndex++];
	    });
	    if (typeof console !== 'undefined') {
	      console.error(message);
	    }
	    try {
	      // --- Welcome to debugging React ---
	      // This error was thrown as a convenience so that you can use this stack
	      // to find the callsite that caused this warning to fire.
	      throw new Error(message);
	    } catch (x) {}
	  };

	  warning = function warning(condition, format) {
	    if (format === undefined) {
	      throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
	    }

	    if (format.indexOf('Failed Composite propType: ') === 0) {
	      return; // Ignore CompositeComponent proptype check.
	    }

	    if (!condition) {
	      for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
	        args[_key2 - 2] = arguments[_key2];
	      }

	      printWarning.apply(undefined, [format].concat(args));
	    }
	  };
	}

	module.exports = warning;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 36 */
/***/ function(module, exports) {

	"use strict";

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	function makeEmptyFunction(arg) {
	  return function () {
	    return arg;
	  };
	}

	/**
	 * This function accepts and discards inputs; it has no side effects. This is
	 * primarily useful idiomatically for overridable function endpoints which
	 * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
	 */
	var emptyFunction = function emptyFunction() {};

	emptyFunction.thatReturns = makeEmptyFunction;
	emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
	emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
	emptyFunction.thatReturnsNull = makeEmptyFunction(null);
	emptyFunction.thatReturnsThis = function () {
	  return this;
	};
	emptyFunction.thatReturnsArgument = function (arg) {
	  return arg;
	};

	module.exports = emptyFunction;

/***/ },
/* 37 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var canDefineProperty = false;
	if (process.env.NODE_ENV !== 'production') {
	  try {
	    // $FlowFixMe https://github.com/facebook/flow/issues/285
	    Object.defineProperty({}, 'x', { get: function () {} });
	    canDefineProperty = true;
	  } catch (x) {
	    // IE will fail on defineProperty
	  }
	}

	module.exports = canDefineProperty;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 38 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var emptyObject = {};

	if (process.env.NODE_ENV !== 'production') {
	  Object.freeze(emptyObject);
	}

	module.exports = emptyObject;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 39 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * Use invariant() to assert state which your program assumes to be true.
	 *
	 * Provide sprintf-style format (only %s is supported) and arguments
	 * to provide information about what broke and what you were
	 * expecting.
	 *
	 * The invariant message will be stripped in production, but the invariant
	 * will remain to ensure logic does not differ in production.
	 */

	var validateFormat = function validateFormat(format) {};

	if (process.env.NODE_ENV !== 'production') {
	  validateFormat = function validateFormat(format) {
	    if (format === undefined) {
	      throw new Error('invariant requires an error message argument');
	    }
	  };
	}

	function invariant(condition, format, a, b, c, d, e, f) {
	  validateFormat(format);

	  if (!condition) {
	    var error;
	    if (format === undefined) {
	      error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
	    } else {
	      var args = [a, b, c, d, e, f];
	      var argIndex = 0;
	      error = new Error(format.replace(/%s/g, function () {
	        return args[argIndex++];
	      }));
	      error.name = 'Invariant Violation';
	    }

	    error.framesToPop = 1; // we don't care about invariant's own frame
	    throw error;
	  }
	}

	module.exports = invariant;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 40 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * Forked from fbjs/warning:
	 * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js
	 *
	 * Only change is we use console.warn instead of console.error,
	 * and do nothing when 'console' is not supported.
	 * This really simplifies the code.
	 * ---
	 * Similar to invariant but only logs a warning if the condition is not met.
	 * This can be used to log issues in development environments in critical
	 * paths. Removing the logging code for production environments will keep the
	 * same logic and follow the same code paths.
	 */

	var lowPriorityWarning = function () {};

	if (process.env.NODE_ENV !== 'production') {
	  var printWarning = function (format) {
	    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
	      args[_key - 1] = arguments[_key];
	    }

	    var argIndex = 0;
	    var message = 'Warning: ' + format.replace(/%s/g, function () {
	      return args[argIndex++];
	    });
	    if (typeof console !== 'undefined') {
	      console.warn(message);
	    }
	    try {
	      // --- Welcome to debugging React ---
	      // This error was thrown as a convenience so that you can use this stack
	      // to find the callsite that caused this warning to fire.
	      throw new Error(message);
	    } catch (x) {}
	  };

	  lowPriorityWarning = function (condition, format) {
	    if (format === undefined) {
	      throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
	    }
	    if (!condition) {
	      for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
	        args[_key2 - 2] = arguments[_key2];
	      }

	      printWarning.apply(undefined, [format].concat(args));
	    }
	  };
	}

	module.exports = lowPriorityWarning;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 41 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var PooledClass = __webpack_require__(42);
	var ReactElement = __webpack_require__(43);

	var emptyFunction = __webpack_require__(36);
	var traverseAllChildren = __webpack_require__(46);

	var twoArgumentPooler = PooledClass.twoArgumentPooler;
	var fourArgumentPooler = PooledClass.fourArgumentPooler;

	var userProvidedKeyEscapeRegex = /\/+/g;
	function escapeUserProvidedKey(text) {
	  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');
	}

	/**
	 * PooledClass representing the bookkeeping associated with performing a child
	 * traversal. Allows avoiding binding callbacks.
	 *
	 * @constructor ForEachBookKeeping
	 * @param {!function} forEachFunction Function to perform traversal with.
	 * @param {?*} forEachContext Context to perform context with.
	 */
	function ForEachBookKeeping(forEachFunction, forEachContext) {
	  this.func = forEachFunction;
	  this.context = forEachContext;
	  this.count = 0;
	}
	ForEachBookKeeping.prototype.destructor = function () {
	  this.func = null;
	  this.context = null;
	  this.count = 0;
	};
	PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);

	function forEachSingleChild(bookKeeping, child, name) {
	  var func = bookKeeping.func,
	      context = bookKeeping.context;

	  func.call(context, child, bookKeeping.count++);
	}

	/**
	 * Iterates through children that are typically specified as `props.children`.
	 *
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach
	 *
	 * The provided forEachFunc(child, index) will be called for each
	 * leaf child.
	 *
	 * @param {?*} children Children tree container.
	 * @param {function(*, int)} forEachFunc
	 * @param {*} forEachContext Context for forEachContext.
	 */
	function forEachChildren(children, forEachFunc, forEachContext) {
	  if (children == null) {
	    return children;
	  }
	  var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);
	  traverseAllChildren(children, forEachSingleChild, traverseContext);
	  ForEachBookKeeping.release(traverseContext);
	}

	/**
	 * PooledClass representing the bookkeeping associated with performing a child
	 * mapping. Allows avoiding binding callbacks.
	 *
	 * @constructor MapBookKeeping
	 * @param {!*} mapResult Object containing the ordered map of results.
	 * @param {!function} mapFunction Function to perform mapping with.
	 * @param {?*} mapContext Context to perform mapping with.
	 */
	function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {
	  this.result = mapResult;
	  this.keyPrefix = keyPrefix;
	  this.func = mapFunction;
	  this.context = mapContext;
	  this.count = 0;
	}
	MapBookKeeping.prototype.destructor = function () {
	  this.result = null;
	  this.keyPrefix = null;
	  this.func = null;
	  this.context = null;
	  this.count = 0;
	};
	PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);

	function mapSingleChildIntoContext(bookKeeping, child, childKey) {
	  var result = bookKeeping.result,
	      keyPrefix = bookKeeping.keyPrefix,
	      func = bookKeeping.func,
	      context = bookKeeping.context;


	  var mappedChild = func.call(context, child, bookKeeping.count++);
	  if (Array.isArray(mappedChild)) {
	    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);
	  } else if (mappedChild != null) {
	    if (ReactElement.isValidElement(mappedChild)) {
	      mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,
	      // Keep both the (mapped) and old keys if they differ, just as
	      // traverseAllChildren used to do for objects as children
	      keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);
	    }
	    result.push(mappedChild);
	  }
	}

	function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
	  var escapedPrefix = '';
	  if (prefix != null) {
	    escapedPrefix = escapeUserProvidedKey(prefix) + '/';
	  }
	  var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);
	  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
	  MapBookKeeping.release(traverseContext);
	}

	/**
	 * Maps children that are typically specified as `props.children`.
	 *
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.children.map
	 *
	 * The provided mapFunction(child, key, index) will be called for each
	 * leaf child.
	 *
	 * @param {?*} children Children tree container.
	 * @param {function(*, int)} func The map function.
	 * @param {*} context Context for mapFunction.
	 * @return {object} Object containing the ordered map of results.
	 */
	function mapChildren(children, func, context) {
	  if (children == null) {
	    return children;
	  }
	  var result = [];
	  mapIntoWithKeyPrefixInternal(children, result, null, func, context);
	  return result;
	}

	function forEachSingleChildDummy(traverseContext, child, name) {
	  return null;
	}

	/**
	 * Count the number of children that are typically specified as
	 * `props.children`.
	 *
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.children.count
	 *
	 * @param {?*} children Children tree container.
	 * @return {number} The number of children.
	 */
	function countChildren(children, context) {
	  return traverseAllChildren(children, forEachSingleChildDummy, null);
	}

	/**
	 * Flatten a children object (typically specified as `props.children`) and
	 * return an array with appropriately re-keyed children.
	 *
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray
	 */
	function toArray(children) {
	  var result = [];
	  mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);
	  return result;
	}

	var ReactChildren = {
	  forEach: forEachChildren,
	  map: mapChildren,
	  mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,
	  count: countChildren,
	  toArray: toArray
	};

	module.exports = ReactChildren;

/***/ },
/* 42 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(33);

	var invariant = __webpack_require__(39);

	/**
	 * Static poolers. Several custom versions for each potential number of
	 * arguments. A completely generic pooler is easy to implement, but would
	 * require accessing the `arguments` object. In each of these, `this` refers to
	 * the Class itself, not an instance. If any others are needed, simply add them
	 * here, or in their own files.
	 */
	var oneArgumentPooler = function (copyFieldsFrom) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, copyFieldsFrom);
	    return instance;
	  } else {
	    return new Klass(copyFieldsFrom);
	  }
	};

	var twoArgumentPooler = function (a1, a2) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, a1, a2);
	    return instance;
	  } else {
	    return new Klass(a1, a2);
	  }
	};

	var threeArgumentPooler = function (a1, a2, a3) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, a1, a2, a3);
	    return instance;
	  } else {
	    return new Klass(a1, a2, a3);
	  }
	};

	var fourArgumentPooler = function (a1, a2, a3, a4) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, a1, a2, a3, a4);
	    return instance;
	  } else {
	    return new Klass(a1, a2, a3, a4);
	  }
	};

	var standardReleaser = function (instance) {
	  var Klass = this;
	  !(instance instanceof Klass) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0;
	  instance.destructor();
	  if (Klass.instancePool.length < Klass.poolSize) {
	    Klass.instancePool.push(instance);
	  }
	};

	var DEFAULT_POOL_SIZE = 10;
	var DEFAULT_POOLER = oneArgumentPooler;

	/**
	 * Augments `CopyConstructor` to be a poolable class, augmenting only the class
	 * itself (statically) not adding any prototypical fields. Any CopyConstructor
	 * you give this may have a `poolSize` property, and will look for a
	 * prototypical `destructor` on instances.
	 *
	 * @param {Function} CopyConstructor Constructor that can be used to reset.
	 * @param {Function} pooler Customizable pooler.
	 */
	var addPoolingTo = function (CopyConstructor, pooler) {
	  // Casting as any so that flow ignores the actual implementation and trusts
	  // it to match the type we declared
	  var NewKlass = CopyConstructor;
	  NewKlass.instancePool = [];
	  NewKlass.getPooled = pooler || DEFAULT_POOLER;
	  if (!NewKlass.poolSize) {
	    NewKlass.poolSize = DEFAULT_POOL_SIZE;
	  }
	  NewKlass.release = standardReleaser;
	  return NewKlass;
	};

	var PooledClass = {
	  addPoolingTo: addPoolingTo,
	  oneArgumentPooler: oneArgumentPooler,
	  twoArgumentPooler: twoArgumentPooler,
	  threeArgumentPooler: threeArgumentPooler,
	  fourArgumentPooler: fourArgumentPooler
	};

	module.exports = PooledClass;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 43 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var ReactCurrentOwner = __webpack_require__(44);

	var warning = __webpack_require__(35);
	var canDefineProperty = __webpack_require__(37);
	var hasOwnProperty = Object.prototype.hasOwnProperty;

	var REACT_ELEMENT_TYPE = __webpack_require__(45);

	var RESERVED_PROPS = {
	  key: true,
	  ref: true,
	  __self: true,
	  __source: true
	};

	var specialPropKeyWarningShown, specialPropRefWarningShown;

	function hasValidRef(config) {
	  if (process.env.NODE_ENV !== 'production') {
	    if (hasOwnProperty.call(config, 'ref')) {
	      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
	      if (getter && getter.isReactWarning) {
	        return false;
	      }
	    }
	  }
	  return config.ref !== undefined;
	}

	function hasValidKey(config) {
	  if (process.env.NODE_ENV !== 'production') {
	    if (hasOwnProperty.call(config, 'key')) {
	      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
	      if (getter && getter.isReactWarning) {
	        return false;
	      }
	    }
	  }
	  return config.key !== undefined;
	}

	function defineKeyPropWarningGetter(props, displayName) {
	  var warnAboutAccessingKey = function () {
	    if (!specialPropKeyWarningShown) {
	      specialPropKeyWarningShown = true;
	      process.env.NODE_ENV !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;
	    }
	  };
	  warnAboutAccessingKey.isReactWarning = true;
	  Object.defineProperty(props, 'key', {
	    get: warnAboutAccessingKey,
	    configurable: true
	  });
	}

	function defineRefPropWarningGetter(props, displayName) {
	  var warnAboutAccessingRef = function () {
	    if (!specialPropRefWarningShown) {
	      specialPropRefWarningShown = true;
	      process.env.NODE_ENV !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;
	    }
	  };
	  warnAboutAccessingRef.isReactWarning = true;
	  Object.defineProperty(props, 'ref', {
	    get: warnAboutAccessingRef,
	    configurable: true
	  });
	}

	/**
	 * Factory method to create a new React element. This no longer adheres to
	 * the class pattern, so do not use new to call it. Also, no instanceof check
	 * will work. Instead test $$typeof field against Symbol.for('react.element') to check
	 * if something is a React Element.
	 *
	 * @param {*} type
	 * @param {*} key
	 * @param {string|object} ref
	 * @param {*} self A *temporary* helper to detect places where `this` is
	 * different from the `owner` when React.createElement is called, so that we
	 * can warn. We want to get rid of owner and replace string `ref`s with arrow
	 * functions, and as long as `this` and owner are the same, there will be no
	 * change in behavior.
	 * @param {*} source An annotation object (added by a transpiler or otherwise)
	 * indicating filename, line number, and/or other information.
	 * @param {*} owner
	 * @param {*} props
	 * @internal
	 */
	var ReactElement = function (type, key, ref, self, source, owner, props) {
	  var element = {
	    // This tag allow us to uniquely identify this as a React Element
	    $$typeof: REACT_ELEMENT_TYPE,

	    // Built-in properties that belong on the element
	    type: type,
	    key: key,
	    ref: ref,
	    props: props,

	    // Record the component responsible for creating this element.
	    _owner: owner
	  };

	  if (process.env.NODE_ENV !== 'production') {
	    // The validation flag is currently mutative. We put it on
	    // an external backing store so that we can freeze the whole object.
	    // This can be replaced with a WeakMap once they are implemented in
	    // commonly used development environments.
	    element._store = {};

	    // To make comparing ReactElements easier for testing purposes, we make
	    // the validation flag non-enumerable (where possible, which should
	    // include every environment we run tests in), so the test framework
	    // ignores it.
	    if (canDefineProperty) {
	      Object.defineProperty(element._store, 'validated', {
	        configurable: false,
	        enumerable: false,
	        writable: true,
	        value: false
	      });
	      // self and source are DEV only properties.
	      Object.defineProperty(element, '_self', {
	        configurable: false,
	        enumerable: false,
	        writable: false,
	        value: self
	      });
	      // Two elements created in two different places should be considered
	      // equal for testing purposes and therefore we hide it from enumeration.
	      Object.defineProperty(element, '_source', {
	        configurable: false,
	        enumerable: false,
	        writable: false,
	        value: source
	      });
	    } else {
	      element._store.validated = false;
	      element._self = self;
	      element._source = source;
	    }
	    if (Object.freeze) {
	      Object.freeze(element.props);
	      Object.freeze(element);
	    }
	  }

	  return element;
	};

	/**
	 * Create and return a new ReactElement of the given type.
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.createelement
	 */
	ReactElement.createElement = function (type, config, children) {
	  var propName;

	  // Reserved names are extracted
	  var props = {};

	  var key = null;
	  var ref = null;
	  var self = null;
	  var source = null;

	  if (config != null) {
	    if (hasValidRef(config)) {
	      ref = config.ref;
	    }
	    if (hasValidKey(config)) {
	      key = '' + config.key;
	    }

	    self = config.__self === undefined ? null : config.__self;
	    source = config.__source === undefined ? null : config.__source;
	    // Remaining properties are added to a new props object
	    for (propName in config) {
	      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
	        props[propName] = config[propName];
	      }
	    }
	  }

	  // Children can be more than one argument, and those are transferred onto
	  // the newly allocated props object.
	  var childrenLength = arguments.length - 2;
	  if (childrenLength === 1) {
	    props.children = children;
	  } else if (childrenLength > 1) {
	    var childArray = Array(childrenLength);
	    for (var i = 0; i < childrenLength; i++) {
	      childArray[i] = arguments[i + 2];
	    }
	    if (process.env.NODE_ENV !== 'production') {
	      if (Object.freeze) {
	        Object.freeze(childArray);
	      }
	    }
	    props.children = childArray;
	  }

	  // Resolve default props
	  if (type && type.defaultProps) {
	    var defaultProps = type.defaultProps;
	    for (propName in defaultProps) {
	      if (props[propName] === undefined) {
	        props[propName] = defaultProps[propName];
	      }
	    }
	  }
	  if (process.env.NODE_ENV !== 'production') {
	    if (key || ref) {
	      if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) {
	        var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
	        if (key) {
	          defineKeyPropWarningGetter(props, displayName);
	        }
	        if (ref) {
	          defineRefPropWarningGetter(props, displayName);
	        }
	      }
	    }
	  }
	  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
	};

	/**
	 * Return a function that produces ReactElements of a given type.
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.createfactory
	 */
	ReactElement.createFactory = function (type) {
	  var factory = ReactElement.createElement.bind(null, type);
	  // Expose the type on the factory and the prototype so that it can be
	  // easily accessed on elements. E.g. `<Foo />.type === Foo`.
	  // This should not be named `constructor` since this may not be the function
	  // that created the element, and it may not even be a constructor.
	  // Legacy hook TODO: Warn if this is accessed
	  factory.type = type;
	  return factory;
	};

	ReactElement.cloneAndReplaceKey = function (oldElement, newKey) {
	  var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);

	  return newElement;
	};

	/**
	 * Clone and return a new ReactElement using element as the starting point.
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement
	 */
	ReactElement.cloneElement = function (element, config, children) {
	  var propName;

	  // Original props are copied
	  var props = _assign({}, element.props);

	  // Reserved names are extracted
	  var key = element.key;
	  var ref = element.ref;
	  // Self is preserved since the owner is preserved.
	  var self = element._self;
	  // Source is preserved since cloneElement is unlikely to be targeted by a
	  // transpiler, and the original source is probably a better indicator of the
	  // true owner.
	  var source = element._source;

	  // Owner will be preserved, unless ref is overridden
	  var owner = element._owner;

	  if (config != null) {
	    if (hasValidRef(config)) {
	      // Silently steal the ref from the parent.
	      ref = config.ref;
	      owner = ReactCurrentOwner.current;
	    }
	    if (hasValidKey(config)) {
	      key = '' + config.key;
	    }

	    // Remaining properties override existing props
	    var defaultProps;
	    if (element.type && element.type.defaultProps) {
	      defaultProps = element.type.defaultProps;
	    }
	    for (propName in config) {
	      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
	        if (config[propName] === undefined && defaultProps !== undefined) {
	          // Resolve default props
	          props[propName] = defaultProps[propName];
	        } else {
	          props[propName] = config[propName];
	        }
	      }
	    }
	  }

	  // Children can be more than one argument, and those are transferred onto
	  // the newly allocated props object.
	  var childrenLength = arguments.length - 2;
	  if (childrenLength === 1) {
	    props.children = children;
	  } else if (childrenLength > 1) {
	    var childArray = Array(childrenLength);
	    for (var i = 0; i < childrenLength; i++) {
	      childArray[i] = arguments[i + 2];
	    }
	    props.children = childArray;
	  }

	  return ReactElement(element.type, key, ref, self, source, owner, props);
	};

	/**
	 * Verifies the object is a ReactElement.
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.isvalidelement
	 * @param {?object} object
	 * @return {boolean} True if `object` is a valid component.
	 * @final
	 */
	ReactElement.isValidElement = function (object) {
	  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
	};

	module.exports = ReactElement;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 44 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	/**
	 * Keeps track of the current owner.
	 *
	 * The current owner is the component who should own any components that are
	 * currently being constructed.
	 */
	var ReactCurrentOwner = {
	  /**
	   * @internal
	   * @type {ReactComponent}
	   */
	  current: null
	};

	module.exports = ReactCurrentOwner;

/***/ },
/* 45 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	// The Symbol used to tag the ReactElement type. If there is no native Symbol
	// nor polyfill, then a plain number is used for performance.

	var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;

	module.exports = REACT_ELEMENT_TYPE;

/***/ },
/* 46 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(33);

	var ReactCurrentOwner = __webpack_require__(44);
	var REACT_ELEMENT_TYPE = __webpack_require__(45);

	var getIteratorFn = __webpack_require__(47);
	var invariant = __webpack_require__(39);
	var KeyEscapeUtils = __webpack_require__(48);
	var warning = __webpack_require__(35);

	var SEPARATOR = '.';
	var SUBSEPARATOR = ':';

	/**
	 * This is inlined from ReactElement since this file is shared between
	 * isomorphic and renderers. We could extract this to a
	 *
	 */

	/**
	 * TODO: Test that a single child and an array with one item have the same key
	 * pattern.
	 */

	var didWarnAboutMaps = false;

	/**
	 * Generate a key string that identifies a component within a set.
	 *
	 * @param {*} component A component that could contain a manual key.
	 * @param {number} index Index that is used if a manual key is not provided.
	 * @return {string}
	 */
	function getComponentKey(component, index) {
	  // Do some typechecking here since we call this blindly. We want to ensure
	  // that we don't block potential future ES APIs.
	  if (component && typeof component === 'object' && component.key != null) {
	    // Explicit key
	    return KeyEscapeUtils.escape(component.key);
	  }
	  // Implicit key determined by the index in the set
	  return index.toString(36);
	}

	/**
	 * @param {?*} children Children tree container.
	 * @param {!string} nameSoFar Name of the key path so far.
	 * @param {!function} callback Callback to invoke with each child found.
	 * @param {?*} traverseContext Used to pass information throughout the traversal
	 * process.
	 * @return {!number} The number of children in this subtree.
	 */
	function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {
	  var type = typeof children;

	  if (type === 'undefined' || type === 'boolean') {
	    // All of the above are perceived as null.
	    children = null;
	  }

	  if (children === null || type === 'string' || type === 'number' ||
	  // The following is inlined from ReactElement. This means we can optimize
	  // some checks. React Fiber also inlines this logic for similar purposes.
	  type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE) {
	    callback(traverseContext, children,
	    // If it's the only child, treat the name as if it was wrapped in an array
	    // so that it's consistent if the number of children grows.
	    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);
	    return 1;
	  }

	  var child;
	  var nextName;
	  var subtreeCount = 0; // Count of children found in the current subtree.
	  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;

	  if (Array.isArray(children)) {
	    for (var i = 0; i < children.length; i++) {
	      child = children[i];
	      nextName = nextNamePrefix + getComponentKey(child, i);
	      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
	    }
	  } else {
	    var iteratorFn = getIteratorFn(children);
	    if (iteratorFn) {
	      var iterator = iteratorFn.call(children);
	      var step;
	      if (iteratorFn !== children.entries) {
	        var ii = 0;
	        while (!(step = iterator.next()).done) {
	          child = step.value;
	          nextName = nextNamePrefix + getComponentKey(child, ii++);
	          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
	        }
	      } else {
	        if (process.env.NODE_ENV !== 'production') {
	          var mapsAsChildrenAddendum = '';
	          if (ReactCurrentOwner.current) {
	            var mapsAsChildrenOwnerName = ReactCurrentOwner.current.getName();
	            if (mapsAsChildrenOwnerName) {
	              mapsAsChildrenAddendum = ' Check the render method of `' + mapsAsChildrenOwnerName + '`.';
	            }
	          }
	          process.env.NODE_ENV !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.%s', mapsAsChildrenAddendum) : void 0;
	          didWarnAboutMaps = true;
	        }
	        // Iterator will provide entry [k,v] tuples rather than values.
	        while (!(step = iterator.next()).done) {
	          var entry = step.value;
	          if (entry) {
	            child = entry[1];
	            nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);
	            subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
	          }
	        }
	      }
	    } else if (type === 'object') {
	      var addendum = '';
	      if (process.env.NODE_ENV !== 'production') {
	        addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';
	        if (children._isReactElement) {
	          addendum = " It looks like you're using an element created by a different " + 'version of React. Make sure to use only one copy of React.';
	        }
	        if (ReactCurrentOwner.current) {
	          var name = ReactCurrentOwner.current.getName();
	          if (name) {
	            addendum += ' Check the render method of `' + name + '`.';
	          }
	        }
	      }
	      var childrenString = String(children);
	       true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0;
	    }
	  }

	  return subtreeCount;
	}

	/**
	 * Traverses children that are typically specified as `props.children`, but
	 * might also be specified through attributes:
	 *
	 * - `traverseAllChildren(this.props.children, ...)`
	 * - `traverseAllChildren(this.props.leftPanelChildren, ...)`
	 *
	 * The `traverseContext` is an optional argument that is passed through the
	 * entire traversal. It can be used to store accumulations or anything else that
	 * the callback might find relevant.
	 *
	 * @param {?*} children Children tree object.
	 * @param {!function} callback To invoke upon traversing each child.
	 * @param {?*} traverseContext Context for traversal.
	 * @return {!number} The number of children in this subtree.
	 */
	function traverseAllChildren(children, callback, traverseContext) {
	  if (children == null) {
	    return 0;
	  }

	  return traverseAllChildrenImpl(children, '', callback, traverseContext);
	}

	module.exports = traverseAllChildren;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 47 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	/* global Symbol */

	var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
	var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.

	/**
	 * Returns the iterator method function contained on the iterable object.
	 *
	 * Be sure to invoke the function with the iterable as context:
	 *
	 *     var iteratorFn = getIteratorFn(myIterable);
	 *     if (iteratorFn) {
	 *       var iterator = iteratorFn.call(myIterable);
	 *       ...
	 *     }
	 *
	 * @param {?object} maybeIterable
	 * @return {?function}
	 */
	function getIteratorFn(maybeIterable) {
	  var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
	  if (typeof iteratorFn === 'function') {
	    return iteratorFn;
	  }
	}

	module.exports = getIteratorFn;

/***/ },
/* 48 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	/**
	 * Escape and wrap key so it is safe to use as a reactid
	 *
	 * @param {string} key to be escaped.
	 * @return {string} the escaped key.
	 */

	function escape(key) {
	  var escapeRegex = /[=:]/g;
	  var escaperLookup = {
	    '=': '=0',
	    ':': '=2'
	  };
	  var escapedString = ('' + key).replace(escapeRegex, function (match) {
	    return escaperLookup[match];
	  });

	  return '$' + escapedString;
	}

	/**
	 * Unescape and unwrap key for human-readable display
	 *
	 * @param {string} key to unescape.
	 * @return {string} the unescaped key.
	 */
	function unescape(key) {
	  var unescapeRegex = /(=0|=2)/g;
	  var unescaperLookup = {
	    '=0': '=',
	    '=2': ':'
	  };
	  var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);

	  return ('' + keySubstring).replace(unescapeRegex, function (match) {
	    return unescaperLookup[match];
	  });
	}

	var KeyEscapeUtils = {
	  escape: escape,
	  unescape: unescape
	};

	module.exports = KeyEscapeUtils;

/***/ },
/* 49 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactElement = __webpack_require__(43);

	/**
	 * Create a factory that creates HTML tag elements.
	 *
	 * @private
	 */
	var createDOMFactory = ReactElement.createFactory;
	if (process.env.NODE_ENV !== 'production') {
	  var ReactElementValidator = __webpack_require__(50);
	  createDOMFactory = ReactElementValidator.createFactory;
	}

	/**
	 * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.
	 *
	 * @public
	 */
	var ReactDOMFactories = {
	  a: createDOMFactory('a'),
	  abbr: createDOMFactory('abbr'),
	  address: createDOMFactory('address'),
	  area: createDOMFactory('area'),
	  article: createDOMFactory('article'),
	  aside: createDOMFactory('aside'),
	  audio: createDOMFactory('audio'),
	  b: createDOMFactory('b'),
	  base: createDOMFactory('base'),
	  bdi: createDOMFactory('bdi'),
	  bdo: createDOMFactory('bdo'),
	  big: createDOMFactory('big'),
	  blockquote: createDOMFactory('blockquote'),
	  body: createDOMFactory('body'),
	  br: createDOMFactory('br'),
	  button: createDOMFactory('button'),
	  canvas: createDOMFactory('canvas'),
	  caption: createDOMFactory('caption'),
	  cite: createDOMFactory('cite'),
	  code: createDOMFactory('code'),
	  col: createDOMFactory('col'),
	  colgroup: createDOMFactory('colgroup'),
	  data: createDOMFactory('data'),
	  datalist: createDOMFactory('datalist'),
	  dd: createDOMFactory('dd'),
	  del: createDOMFactory('del'),
	  details: createDOMFactory('details'),
	  dfn: createDOMFactory('dfn'),
	  dialog: createDOMFactory('dialog'),
	  div: createDOMFactory('div'),
	  dl: createDOMFactory('dl'),
	  dt: createDOMFactory('dt'),
	  em: createDOMFactory('em'),
	  embed: createDOMFactory('embed'),
	  fieldset: createDOMFactory('fieldset'),
	  figcaption: createDOMFactory('figcaption'),
	  figure: createDOMFactory('figure'),
	  footer: createDOMFactory('footer'),
	  form: createDOMFactory('form'),
	  h1: createDOMFactory('h1'),
	  h2: createDOMFactory('h2'),
	  h3: createDOMFactory('h3'),
	  h4: createDOMFactory('h4'),
	  h5: createDOMFactory('h5'),
	  h6: createDOMFactory('h6'),
	  head: createDOMFactory('head'),
	  header: createDOMFactory('header'),
	  hgroup: createDOMFactory('hgroup'),
	  hr: createDOMFactory('hr'),
	  html: createDOMFactory('html'),
	  i: createDOMFactory('i'),
	  iframe: createDOMFactory('iframe'),
	  img: createDOMFactory('img'),
	  input: createDOMFactory('input'),
	  ins: createDOMFactory('ins'),
	  kbd: createDOMFactory('kbd'),
	  keygen: createDOMFactory('keygen'),
	  label: createDOMFactory('label'),
	  legend: createDOMFactory('legend'),
	  li: createDOMFactory('li'),
	  link: createDOMFactory('link'),
	  main: createDOMFactory('main'),
	  map: createDOMFactory('map'),
	  mark: createDOMFactory('mark'),
	  menu: createDOMFactory('menu'),
	  menuitem: createDOMFactory('menuitem'),
	  meta: createDOMFactory('meta'),
	  meter: createDOMFactory('meter'),
	  nav: createDOMFactory('nav'),
	  noscript: createDOMFactory('noscript'),
	  object: createDOMFactory('object'),
	  ol: createDOMFactory('ol'),
	  optgroup: createDOMFactory('optgroup'),
	  option: createDOMFactory('option'),
	  output: createDOMFactory('output'),
	  p: createDOMFactory('p'),
	  param: createDOMFactory('param'),
	  picture: createDOMFactory('picture'),
	  pre: createDOMFactory('pre'),
	  progress: createDOMFactory('progress'),
	  q: createDOMFactory('q'),
	  rp: createDOMFactory('rp'),
	  rt: createDOMFactory('rt'),
	  ruby: createDOMFactory('ruby'),
	  s: createDOMFactory('s'),
	  samp: createDOMFactory('samp'),
	  script: createDOMFactory('script'),
	  section: createDOMFactory('section'),
	  select: createDOMFactory('select'),
	  small: createDOMFactory('small'),
	  source: createDOMFactory('source'),
	  span: createDOMFactory('span'),
	  strong: createDOMFactory('strong'),
	  style: createDOMFactory('style'),
	  sub: createDOMFactory('sub'),
	  summary: createDOMFactory('summary'),
	  sup: createDOMFactory('sup'),
	  table: createDOMFactory('table'),
	  tbody: createDOMFactory('tbody'),
	  td: createDOMFactory('td'),
	  textarea: createDOMFactory('textarea'),
	  tfoot: createDOMFactory('tfoot'),
	  th: createDOMFactory('th'),
	  thead: createDOMFactory('thead'),
	  time: createDOMFactory('time'),
	  title: createDOMFactory('title'),
	  tr: createDOMFactory('tr'),
	  track: createDOMFactory('track'),
	  u: createDOMFactory('u'),
	  ul: createDOMFactory('ul'),
	  'var': createDOMFactory('var'),
	  video: createDOMFactory('video'),
	  wbr: createDOMFactory('wbr'),

	  // SVG
	  circle: createDOMFactory('circle'),
	  clipPath: createDOMFactory('clipPath'),
	  defs: createDOMFactory('defs'),
	  ellipse: createDOMFactory('ellipse'),
	  g: createDOMFactory('g'),
	  image: createDOMFactory('image'),
	  line: createDOMFactory('line'),
	  linearGradient: createDOMFactory('linearGradient'),
	  mask: createDOMFactory('mask'),
	  path: createDOMFactory('path'),
	  pattern: createDOMFactory('pattern'),
	  polygon: createDOMFactory('polygon'),
	  polyline: createDOMFactory('polyline'),
	  radialGradient: createDOMFactory('radialGradient'),
	  rect: createDOMFactory('rect'),
	  stop: createDOMFactory('stop'),
	  svg: createDOMFactory('svg'),
	  text: createDOMFactory('text'),
	  tspan: createDOMFactory('tspan')
	};

	module.exports = ReactDOMFactories;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 50 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	/**
	 * ReactElementValidator provides a wrapper around a element factory
	 * which validates the props passed to the element. This is intended to be
	 * used only in DEV and could be replaced by a static type checker for languages
	 * that support it.
	 */

	'use strict';

	var ReactCurrentOwner = __webpack_require__(44);
	var ReactComponentTreeHook = __webpack_require__(51);
	var ReactElement = __webpack_require__(43);

	var checkReactTypeSpec = __webpack_require__(52);

	var canDefineProperty = __webpack_require__(37);
	var getIteratorFn = __webpack_require__(47);
	var warning = __webpack_require__(35);
	var lowPriorityWarning = __webpack_require__(40);

	function getDeclarationErrorAddendum() {
	  if (ReactCurrentOwner.current) {
	    var name = ReactCurrentOwner.current.getName();
	    if (name) {
	      return ' Check the render method of `' + name + '`.';
	    }
	  }
	  return '';
	}

	function getSourceInfoErrorAddendum(elementProps) {
	  if (elementProps !== null && elementProps !== undefined && elementProps.__source !== undefined) {
	    var source = elementProps.__source;
	    var fileName = source.fileName.replace(/^.*[\\\/]/, '');
	    var lineNumber = source.lineNumber;
	    return ' Check your code at ' + fileName + ':' + lineNumber + '.';
	  }
	  return '';
	}

	/**
	 * Warn if there's no key explicitly set on dynamic arrays of children or
	 * object keys are not valid. This allows us to keep track of children between
	 * updates.
	 */
	var ownerHasKeyUseWarning = {};

	function getCurrentComponentErrorInfo(parentType) {
	  var info = getDeclarationErrorAddendum();

	  if (!info) {
	    var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;
	    if (parentName) {
	      info = ' Check the top-level render call using <' + parentName + '>.';
	    }
	  }
	  return info;
	}

	/**
	 * Warn if the element doesn't have an explicit key assigned to it.
	 * This element is in an array. The array could grow and shrink or be
	 * reordered. All children that haven't already been validated are required to
	 * have a "key" property assigned to it. Error statuses are cached so a warning
	 * will only be shown once.
	 *
	 * @internal
	 * @param {ReactElement} element Element that requires a key.
	 * @param {*} parentType element's parent's type.
	 */
	function validateExplicitKey(element, parentType) {
	  if (!element._store || element._store.validated || element.key != null) {
	    return;
	  }
	  element._store.validated = true;

	  var memoizer = ownerHasKeyUseWarning.uniqueKey || (ownerHasKeyUseWarning.uniqueKey = {});

	  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
	  if (memoizer[currentComponentErrorInfo]) {
	    return;
	  }
	  memoizer[currentComponentErrorInfo] = true;

	  // Usually the current owner is the offender, but if it accepts children as a
	  // property, it may be the creator of the child that's responsible for
	  // assigning it a key.
	  var childOwner = '';
	  if (element && element._owner && element._owner !== ReactCurrentOwner.current) {
	    // Give the component that originally created this child.
	    childOwner = ' It was passed a child from ' + element._owner.getName() + '.';
	  }

	  process.env.NODE_ENV !== 'production' ? warning(false, 'Each child in an array or iterator should have a unique "key" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.%s', currentComponentErrorInfo, childOwner, ReactComponentTreeHook.getCurrentStackAddendum(element)) : void 0;
	}

	/**
	 * Ensure that every element either is passed in a static location, in an
	 * array with an explicit keys property defined, or in an object literal
	 * with valid key property.
	 *
	 * @internal
	 * @param {ReactNode} node Statically passed child of any type.
	 * @param {*} parentType node's parent's type.
	 */
	function validateChildKeys(node, parentType) {
	  if (typeof node !== 'object') {
	    return;
	  }
	  if (Array.isArray(node)) {
	    for (var i = 0; i < node.length; i++) {
	      var child = node[i];
	      if (ReactElement.isValidElement(child)) {
	        validateExplicitKey(child, parentType);
	      }
	    }
	  } else if (ReactElement.isValidElement(node)) {
	    // This element was passed in a valid location.
	    if (node._store) {
	      node._store.validated = true;
	    }
	  } else if (node) {
	    var iteratorFn = getIteratorFn(node);
	    // Entry iterators provide implicit keys.
	    if (iteratorFn) {
	      if (iteratorFn !== node.entries) {
	        var iterator = iteratorFn.call(node);
	        var step;
	        while (!(step = iterator.next()).done) {
	          if (ReactElement.isValidElement(step.value)) {
	            validateExplicitKey(step.value, parentType);
	          }
	        }
	      }
	    }
	  }
	}

	/**
	 * Given an element, validate that its props follow the propTypes definition,
	 * provided by the type.
	 *
	 * @param {ReactElement} element
	 */
	function validatePropTypes(element) {
	  var componentClass = element.type;
	  if (typeof componentClass !== 'function') {
	    return;
	  }
	  var name = componentClass.displayName || componentClass.name;
	  if (componentClass.propTypes) {
	    checkReactTypeSpec(componentClass.propTypes, element.props, 'prop', name, element, null);
	  }
	  if (typeof componentClass.getDefaultProps === 'function') {
	    process.env.NODE_ENV !== 'production' ? warning(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0;
	  }
	}

	var ReactElementValidator = {
	  createElement: function (type, props, children) {
	    var validType = typeof type === 'string' || typeof type === 'function';
	    // We warn in this case but don't throw. We expect the element creation to
	    // succeed and there will likely be errors in render.
	    if (!validType) {
	      if (typeof type !== 'function' && typeof type !== 'string') {
	        var info = '';
	        if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
	          info += ' You likely forgot to export your component from the file ' + "it's defined in.";
	        }

	        var sourceInfo = getSourceInfoErrorAddendum(props);
	        if (sourceInfo) {
	          info += sourceInfo;
	        } else {
	          info += getDeclarationErrorAddendum();
	        }

	        info += ReactComponentTreeHook.getCurrentStackAddendum();

	        var currentSource = props !== null && props !== undefined && props.__source !== undefined ? props.__source : null;
	        ReactComponentTreeHook.pushNonStandardWarningStack(true, currentSource);
	        process.env.NODE_ENV !== 'production' ? warning(false, 'React.createElement: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', type == null ? type : typeof type, info) : void 0;
	        ReactComponentTreeHook.popNonStandardWarningStack();
	      }
	    }

	    var element = ReactElement.createElement.apply(this, arguments);

	    // The result can be nullish if a mock or a custom function is used.
	    // TODO: Drop this when these are no longer allowed as the type argument.
	    if (element == null) {
	      return element;
	    }

	    // Skip key warning if the type isn't valid since our key validation logic
	    // doesn't expect a non-string/function type and can throw confusing errors.
	    // We don't want exception behavior to differ between dev and prod.
	    // (Rendering will throw with a helpful message and as soon as the type is
	    // fixed, the key warnings will appear.)
	    if (validType) {
	      for (var i = 2; i < arguments.length; i++) {
	        validateChildKeys(arguments[i], type);
	      }
	    }

	    validatePropTypes(element);

	    return element;
	  },

	  createFactory: function (type) {
	    var validatedFactory = ReactElementValidator.createElement.bind(null, type);
	    // Legacy hook TODO: Warn if this is accessed
	    validatedFactory.type = type;

	    if (process.env.NODE_ENV !== 'production') {
	      if (canDefineProperty) {
	        Object.defineProperty(validatedFactory, 'type', {
	          enumerable: false,
	          get: function () {
	            lowPriorityWarning(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.');
	            Object.defineProperty(this, 'type', {
	              value: type
	            });
	            return type;
	          }
	        });
	      }
	    }

	    return validatedFactory;
	  },

	  cloneElement: function (element, props, children) {
	    var newElement = ReactElement.cloneElement.apply(this, arguments);
	    for (var i = 2; i < arguments.length; i++) {
	      validateChildKeys(arguments[i], newElement.type);
	    }
	    validatePropTypes(newElement);
	    return newElement;
	  }
	};

	module.exports = ReactElementValidator;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 51 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2016-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(33);

	var ReactCurrentOwner = __webpack_require__(44);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	function isNative(fn) {
	  // Based on isNative() from Lodash
	  var funcToString = Function.prototype.toString;
	  var hasOwnProperty = Object.prototype.hasOwnProperty;
	  var reIsNative = RegExp('^' + funcToString
	  // Take an example native function source for comparison
	  .call(hasOwnProperty
	  // Strip regex characters so we can use it for regex
	  ).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&'
	  // Remove hasOwnProperty from the template to make it generic
	  ).replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');
	  try {
	    var source = funcToString.call(fn);
	    return reIsNative.test(source);
	  } catch (err) {
	    return false;
	  }
	}

	var canUseCollections =
	// Array.from
	typeof Array.from === 'function' &&
	// Map
	typeof Map === 'function' && isNative(Map) &&
	// Map.prototype.keys
	Map.prototype != null && typeof Map.prototype.keys === 'function' && isNative(Map.prototype.keys) &&
	// Set
	typeof Set === 'function' && isNative(Set) &&
	// Set.prototype.keys
	Set.prototype != null && typeof Set.prototype.keys === 'function' && isNative(Set.prototype.keys);

	var setItem;
	var getItem;
	var removeItem;
	var getItemIDs;
	var addRoot;
	var removeRoot;
	var getRootIDs;

	if (canUseCollections) {
	  var itemMap = new Map();
	  var rootIDSet = new Set();

	  setItem = function (id, item) {
	    itemMap.set(id, item);
	  };
	  getItem = function (id) {
	    return itemMap.get(id);
	  };
	  removeItem = function (id) {
	    itemMap['delete'](id);
	  };
	  getItemIDs = function () {
	    return Array.from(itemMap.keys());
	  };

	  addRoot = function (id) {
	    rootIDSet.add(id);
	  };
	  removeRoot = function (id) {
	    rootIDSet['delete'](id);
	  };
	  getRootIDs = function () {
	    return Array.from(rootIDSet.keys());
	  };
	} else {
	  var itemByKey = {};
	  var rootByKey = {};

	  // Use non-numeric keys to prevent V8 performance issues:
	  // https://github.com/facebook/react/pull/7232
	  var getKeyFromID = function (id) {
	    return '.' + id;
	  };
	  var getIDFromKey = function (key) {
	    return parseInt(key.substr(1), 10);
	  };

	  setItem = function (id, item) {
	    var key = getKeyFromID(id);
	    itemByKey[key] = item;
	  };
	  getItem = function (id) {
	    var key = getKeyFromID(id);
	    return itemByKey[key];
	  };
	  removeItem = function (id) {
	    var key = getKeyFromID(id);
	    delete itemByKey[key];
	  };
	  getItemIDs = function () {
	    return Object.keys(itemByKey).map(getIDFromKey);
	  };

	  addRoot = function (id) {
	    var key = getKeyFromID(id);
	    rootByKey[key] = true;
	  };
	  removeRoot = function (id) {
	    var key = getKeyFromID(id);
	    delete rootByKey[key];
	  };
	  getRootIDs = function () {
	    return Object.keys(rootByKey).map(getIDFromKey);
	  };
	}

	var unmountedIDs = [];

	function purgeDeep(id) {
	  var item = getItem(id);
	  if (item) {
	    var childIDs = item.childIDs;

	    removeItem(id);
	    childIDs.forEach(purgeDeep);
	  }
	}

	function describeComponentFrame(name, source, ownerName) {
	  return '\n    in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
	}

	function getDisplayName(element) {
	  if (element == null) {
	    return '#empty';
	  } else if (typeof element === 'string' || typeof element === 'number') {
	    return '#text';
	  } else if (typeof element.type === 'string') {
	    return element.type;
	  } else {
	    return element.type.displayName || element.type.name || 'Unknown';
	  }
	}

	function describeID(id) {
	  var name = ReactComponentTreeHook.getDisplayName(id);
	  var element = ReactComponentTreeHook.getElement(id);
	  var ownerID = ReactComponentTreeHook.getOwnerID(id);
	  var ownerName;
	  if (ownerID) {
	    ownerName = ReactComponentTreeHook.getDisplayName(ownerID);
	  }
	  process.env.NODE_ENV !== 'production' ? warning(element, 'ReactComponentTreeHook: Missing React element for debugID %s when ' + 'building stack', id) : void 0;
	  return describeComponentFrame(name, element && element._source, ownerName);
	}

	var ReactComponentTreeHook = {
	  onSetChildren: function (id, nextChildIDs) {
	    var item = getItem(id);
	    !item ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Item must have been set') : _prodInvariant('144') : void 0;
	    item.childIDs = nextChildIDs;

	    for (var i = 0; i < nextChildIDs.length; i++) {
	      var nextChildID = nextChildIDs[i];
	      var nextChild = getItem(nextChildID);
	      !nextChild ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected hook events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('140') : void 0;
	      !(nextChild.childIDs != null || typeof nextChild.element !== 'object' || nextChild.element == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetChildren() to fire for a container child before its parent includes it in onSetChildren().') : _prodInvariant('141') : void 0;
	      !nextChild.isMounted ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;
	      if (nextChild.parentID == null) {
	        nextChild.parentID = id;
	        // TODO: This shouldn't be necessary but mounting a new root during in
	        // componentWillMount currently causes not-yet-mounted components to
	        // be purged from our tree data so their parent id is missing.
	      }
	      !(nextChild.parentID === id) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onBeforeMountComponent() parent and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('142', nextChildID, nextChild.parentID, id) : void 0;
	    }
	  },
	  onBeforeMountComponent: function (id, element, parentID) {
	    var item = {
	      element: element,
	      parentID: parentID,
	      text: null,
	      childIDs: [],
	      isMounted: false,
	      updateCount: 0
	    };
	    setItem(id, item);
	  },
	  onBeforeUpdateComponent: function (id, element) {
	    var item = getItem(id);
	    if (!item || !item.isMounted) {
	      // We may end up here as a result of setState() in componentWillUnmount().
	      // In this case, ignore the element.
	      return;
	    }
	    item.element = element;
	  },
	  onMountComponent: function (id) {
	    var item = getItem(id);
	    !item ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Item must have been set') : _prodInvariant('144') : void 0;
	    item.isMounted = true;
	    var isRoot = item.parentID === 0;
	    if (isRoot) {
	      addRoot(id);
	    }
	  },
	  onUpdateComponent: function (id) {
	    var item = getItem(id);
	    if (!item || !item.isMounted) {
	      // We may end up here as a result of setState() in componentWillUnmount().
	      // In this case, ignore the element.
	      return;
	    }
	    item.updateCount++;
	  },
	  onUnmountComponent: function (id) {
	    var item = getItem(id);
	    if (item) {
	      // We need to check if it exists.
	      // `item` might not exist if it is inside an error boundary, and a sibling
	      // error boundary child threw while mounting. Then this instance never
	      // got a chance to mount, but it still gets an unmounting event during
	      // the error boundary cleanup.
	      item.isMounted = false;
	      var isRoot = item.parentID === 0;
	      if (isRoot) {
	        removeRoot(id);
	      }
	    }
	    unmountedIDs.push(id);
	  },
	  purgeUnmountedComponents: function () {
	    if (ReactComponentTreeHook._preventPurging) {
	      // Should only be used for testing.
	      return;
	    }

	    for (var i = 0; i < unmountedIDs.length; i++) {
	      var id = unmountedIDs[i];
	      purgeDeep(id);
	    }
	    unmountedIDs.length = 0;
	  },
	  isMounted: function (id) {
	    var item = getItem(id);
	    return item ? item.isMounted : false;
	  },
	  getCurrentStackAddendum: function (topElement) {
	    var info = '';
	    if (topElement) {
	      var name = getDisplayName(topElement);
	      var owner = topElement._owner;
	      info += describeComponentFrame(name, topElement._source, owner && owner.getName());
	    }

	    var currentOwner = ReactCurrentOwner.current;
	    var id = currentOwner && currentOwner._debugID;

	    info += ReactComponentTreeHook.getStackAddendumByID(id);
	    return info;
	  },
	  getStackAddendumByID: function (id) {
	    var info = '';
	    while (id) {
	      info += describeID(id);
	      id = ReactComponentTreeHook.getParentID(id);
	    }
	    return info;
	  },
	  getChildIDs: function (id) {
	    var item = getItem(id);
	    return item ? item.childIDs : [];
	  },
	  getDisplayName: function (id) {
	    var element = ReactComponentTreeHook.getElement(id);
	    if (!element) {
	      return null;
	    }
	    return getDisplayName(element);
	  },
	  getElement: function (id) {
	    var item = getItem(id);
	    return item ? item.element : null;
	  },
	  getOwnerID: function (id) {
	    var element = ReactComponentTreeHook.getElement(id);
	    if (!element || !element._owner) {
	      return null;
	    }
	    return element._owner._debugID;
	  },
	  getParentID: function (id) {
	    var item = getItem(id);
	    return item ? item.parentID : null;
	  },
	  getSource: function (id) {
	    var item = getItem(id);
	    var element = item ? item.element : null;
	    var source = element != null ? element._source : null;
	    return source;
	  },
	  getText: function (id) {
	    var element = ReactComponentTreeHook.getElement(id);
	    if (typeof element === 'string') {
	      return element;
	    } else if (typeof element === 'number') {
	      return '' + element;
	    } else {
	      return null;
	    }
	  },
	  getUpdateCount: function (id) {
	    var item = getItem(id);
	    return item ? item.updateCount : 0;
	  },


	  getRootIDs: getRootIDs,
	  getRegisteredIDs: getItemIDs,

	  pushNonStandardWarningStack: function (isCreatingElement, currentSource) {
	    if (typeof console.reactStack !== 'function') {
	      return;
	    }

	    var stack = [];
	    var currentOwner = ReactCurrentOwner.current;
	    var id = currentOwner && currentOwner._debugID;

	    try {
	      if (isCreatingElement) {
	        stack.push({
	          name: id ? ReactComponentTreeHook.getDisplayName(id) : null,
	          fileName: currentSource ? currentSource.fileName : null,
	          lineNumber: currentSource ? currentSource.lineNumber : null
	        });
	      }

	      while (id) {
	        var element = ReactComponentTreeHook.getElement(id);
	        var parentID = ReactComponentTreeHook.getParentID(id);
	        var ownerID = ReactComponentTreeHook.getOwnerID(id);
	        var ownerName = ownerID ? ReactComponentTreeHook.getDisplayName(ownerID) : null;
	        var source = element && element._source;
	        stack.push({
	          name: ownerName,
	          fileName: source ? source.fileName : null,
	          lineNumber: source ? source.lineNumber : null
	        });
	        id = parentID;
	      }
	    } catch (err) {
	      // Internal state is messed up.
	      // Stop building the stack (it's just a nice to have).
	    }

	    console.reactStack(stack);
	  },
	  popNonStandardWarningStack: function () {
	    if (typeof console.reactStackEnd !== 'function') {
	      return;
	    }
	    console.reactStackEnd();
	  }
	};

	module.exports = ReactComponentTreeHook;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 52 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(33);

	var ReactPropTypeLocationNames = __webpack_require__(53);
	var ReactPropTypesSecret = __webpack_require__(54);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	var ReactComponentTreeHook;

	if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'test') {
	  // Temporary hack.
	  // Inline requires don't work well with Jest:
	  // https://github.com/facebook/react/issues/7240
	  // Remove the inline requires when we don't need them anymore:
	  // https://github.com/facebook/react/pull/7178
	  ReactComponentTreeHook = __webpack_require__(51);
	}

	var loggedTypeFailures = {};

	/**
	 * Assert that the values match with the type specs.
	 * Error messages are memorized and will only be shown once.
	 *
	 * @param {object} typeSpecs Map of name to a ReactPropType
	 * @param {object} values Runtime values that need to be type-checked
	 * @param {string} location e.g. "prop", "context", "child context"
	 * @param {string} componentName Name of the component for error messages.
	 * @param {?object} element The React element that is being type-checked
	 * @param {?number} debugID The React component instance that is being type-checked
	 * @private
	 */
	function checkReactTypeSpec(typeSpecs, values, location, componentName, element, debugID) {
	  for (var typeSpecName in typeSpecs) {
	    if (typeSpecs.hasOwnProperty(typeSpecName)) {
	      var error;
	      // Prop type validation may throw. In case they do, we don't want to
	      // fail the render phase where it didn't fail before. So we log it.
	      // After these have been cleaned up, we'll let them throw.
	      try {
	        // This is intentionally an invariant that gets caught. It's the same
	        // behavior as without this statement except with a better message.
	        !(typeof typeSpecs[typeSpecName] === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : _prodInvariant('84', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : void 0;
	        error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
	      } catch (ex) {
	        error = ex;
	      }
	      process.env.NODE_ENV !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName, typeof error) : void 0;
	      if (error instanceof Error && !(error.message in loggedTypeFailures)) {
	        // Only monitor this failure once because there tends to be a lot of the
	        // same error.
	        loggedTypeFailures[error.message] = true;

	        var componentStackInfo = '';

	        if (process.env.NODE_ENV !== 'production') {
	          if (!ReactComponentTreeHook) {
	            ReactComponentTreeHook = __webpack_require__(51);
	          }
	          if (debugID !== null) {
	            componentStackInfo = ReactComponentTreeHook.getStackAddendumByID(debugID);
	          } else if (element !== null) {
	            componentStackInfo = ReactComponentTreeHook.getCurrentStackAddendum(element);
	          }
	        }

	        process.env.NODE_ENV !== 'production' ? warning(false, 'Failed %s type: %s%s', location, error.message, componentStackInfo) : void 0;
	      }
	    }
	  }
	}

	module.exports = checkReactTypeSpec;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 53 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var ReactPropTypeLocationNames = {};

	if (process.env.NODE_ENV !== 'production') {
	  ReactPropTypeLocationNames = {
	    prop: 'prop',
	    context: 'context',
	    childContext: 'child context'
	  };
	}

	module.exports = ReactPropTypeLocationNames;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 54 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';

	module.exports = ReactPropTypesSecret;

/***/ },
/* 55 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _require = __webpack_require__(43),
	    isValidElement = _require.isValidElement;

	var factory = __webpack_require__(56);

	module.exports = factory(isValidElement);

/***/ },
/* 56 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	'use strict';

	// React 15.5 references this module, and assumes PropTypes are still callable in production.
	// Therefore we re-export development-only version with all the PropTypes checks here.
	// However if one is migrating to the `prop-types` npm library, they will go through the
	// `index.js` entry point, and it will branch depending on the environment.
	var factory = __webpack_require__(57);
	module.exports = function(isValidElement) {
	  // It is still allowed in 15.5.
	  var throwOnDirectAccess = false;
	  return factory(isValidElement, throwOnDirectAccess);
	};


/***/ },
/* 57 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	'use strict';

	var emptyFunction = __webpack_require__(36);
	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);
	var assign = __webpack_require__(31);

	var ReactPropTypesSecret = __webpack_require__(58);
	var checkPropTypes = __webpack_require__(59);

	module.exports = function(isValidElement, throwOnDirectAccess) {
	  /* global Symbol */
	  var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
	  var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.

	  /**
	   * Returns the iterator method function contained on the iterable object.
	   *
	   * Be sure to invoke the function with the iterable as context:
	   *
	   *     var iteratorFn = getIteratorFn(myIterable);
	   *     if (iteratorFn) {
	   *       var iterator = iteratorFn.call(myIterable);
	   *       ...
	   *     }
	   *
	   * @param {?object} maybeIterable
	   * @return {?function}
	   */
	  function getIteratorFn(maybeIterable) {
	    var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
	    if (typeof iteratorFn === 'function') {
	      return iteratorFn;
	    }
	  }

	  /**
	   * Collection of methods that allow declaration and validation of props that are
	   * supplied to React components. Example usage:
	   *
	   *   var Props = require('ReactPropTypes');
	   *   var MyArticle = React.createClass({
	   *     propTypes: {
	   *       // An optional string prop named "description".
	   *       description: Props.string,
	   *
	   *       // A required enum prop named "category".
	   *       category: Props.oneOf(['News','Photos']).isRequired,
	   *
	   *       // A prop named "dialog" that requires an instance of Dialog.
	   *       dialog: Props.instanceOf(Dialog).isRequired
	   *     },
	   *     render: function() { ... }
	   *   });
	   *
	   * A more formal specification of how these methods are used:
	   *
	   *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
	   *   decl := ReactPropTypes.{type}(.isRequired)?
	   *
	   * Each and every declaration produces a function with the same signature. This
	   * allows the creation of custom validation functions. For example:
	   *
	   *  var MyLink = React.createClass({
	   *    propTypes: {
	   *      // An optional string or URI prop named "href".
	   *      href: function(props, propName, componentName) {
	   *        var propValue = props[propName];
	   *        if (propValue != null && typeof propValue !== 'string' &&
	   *            !(propValue instanceof URI)) {
	   *          return new Error(
	   *            'Expected a string or an URI for ' + propName + ' in ' +
	   *            componentName
	   *          );
	   *        }
	   *      }
	   *    },
	   *    render: function() {...}
	   *  });
	   *
	   * @internal
	   */

	  var ANONYMOUS = '<<anonymous>>';

	  // Important!
	  // Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
	  var ReactPropTypes = {
	    array: createPrimitiveTypeChecker('array'),
	    bool: createPrimitiveTypeChecker('boolean'),
	    func: createPrimitiveTypeChecker('function'),
	    number: createPrimitiveTypeChecker('number'),
	    object: createPrimitiveTypeChecker('object'),
	    string: createPrimitiveTypeChecker('string'),
	    symbol: createPrimitiveTypeChecker('symbol'),

	    any: createAnyTypeChecker(),
	    arrayOf: createArrayOfTypeChecker,
	    element: createElementTypeChecker(),
	    instanceOf: createInstanceTypeChecker,
	    node: createNodeChecker(),
	    objectOf: createObjectOfTypeChecker,
	    oneOf: createEnumTypeChecker,
	    oneOfType: createUnionTypeChecker,
	    shape: createShapeTypeChecker,
	    exact: createStrictShapeTypeChecker,
	  };

	  /**
	   * inlined Object.is polyfill to avoid requiring consumers ship their own
	   * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
	   */
	  /*eslint-disable no-self-compare*/
	  function is(x, y) {
	    // SameValue algorithm
	    if (x === y) {
	      // Steps 1-5, 7-10
	      // Steps 6.b-6.e: +0 != -0
	      return x !== 0 || 1 / x === 1 / y;
	    } else {
	      // Step 6.a: NaN == NaN
	      return x !== x && y !== y;
	    }
	  }
	  /*eslint-enable no-self-compare*/

	  /**
	   * We use an Error-like object for backward compatibility as people may call
	   * PropTypes directly and inspect their output. However, we don't use real
	   * Errors anymore. We don't inspect their stack anyway, and creating them
	   * is prohibitively expensive if they are created too often, such as what
	   * happens in oneOfType() for any type before the one that matched.
	   */
	  function PropTypeError(message) {
	    this.message = message;
	    this.stack = '';
	  }
	  // Make `instanceof Error` still work for returned errors.
	  PropTypeError.prototype = Error.prototype;

	  function createChainableTypeChecker(validate) {
	    if (process.env.NODE_ENV !== 'production') {
	      var manualPropTypeCallCache = {};
	      var manualPropTypeWarningCount = 0;
	    }
	    function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
	      componentName = componentName || ANONYMOUS;
	      propFullName = propFullName || propName;

	      if (secret !== ReactPropTypesSecret) {
	        if (throwOnDirectAccess) {
	          // New behavior only for users of `prop-types` package
	          invariant(
	            false,
	            'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
	            'Use `PropTypes.checkPropTypes()` to call them. ' +
	            'Read more at http://fb.me/use-check-prop-types'
	          );
	        } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') {
	          // Old behavior for people using React.PropTypes
	          var cacheKey = componentName + ':' + propName;
	          if (
	            !manualPropTypeCallCache[cacheKey] &&
	            // Avoid spamming the console because they are often not actionable except for lib authors
	            manualPropTypeWarningCount < 3
	          ) {
	            warning(
	              false,
	              'You are manually calling a React.PropTypes validation ' +
	              'function for the `%s` prop on `%s`. This is deprecated ' +
	              'and will throw in the standalone `prop-types` package. ' +
	              'You may be seeing this warning due to a third-party PropTypes ' +
	              'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.',
	              propFullName,
	              componentName
	            );
	            manualPropTypeCallCache[cacheKey] = true;
	            manualPropTypeWarningCount++;
	          }
	        }
	      }
	      if (props[propName] == null) {
	        if (isRequired) {
	          if (props[propName] === null) {
	            return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
	          }
	          return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
	        }
	        return null;
	      } else {
	        return validate(props, propName, componentName, location, propFullName);
	      }
	    }

	    var chainedCheckType = checkType.bind(null, false);
	    chainedCheckType.isRequired = checkType.bind(null, true);

	    return chainedCheckType;
	  }

	  function createPrimitiveTypeChecker(expectedType) {
	    function validate(props, propName, componentName, location, propFullName, secret) {
	      var propValue = props[propName];
	      var propType = getPropType(propValue);
	      if (propType !== expectedType) {
	        // `propValue` being instance of, say, date/regexp, pass the 'object'
	        // check, but we can offer a more precise error message here rather than
	        // 'of type `object`'.
	        var preciseType = getPreciseType(propValue);

	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));
	      }
	      return null;
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createAnyTypeChecker() {
	    return createChainableTypeChecker(emptyFunction.thatReturnsNull);
	  }

	  function createArrayOfTypeChecker(typeChecker) {
	    function validate(props, propName, componentName, location, propFullName) {
	      if (typeof typeChecker !== 'function') {
	        return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
	      }
	      var propValue = props[propName];
	      if (!Array.isArray(propValue)) {
	        var propType = getPropType(propValue);
	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
	      }
	      for (var i = 0; i < propValue.length; i++) {
	        var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);
	        if (error instanceof Error) {
	          return error;
	        }
	      }
	      return null;
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createElementTypeChecker() {
	    function validate(props, propName, componentName, location, propFullName) {
	      var propValue = props[propName];
	      if (!isValidElement(propValue)) {
	        var propType = getPropType(propValue);
	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
	      }
	      return null;
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createInstanceTypeChecker(expectedClass) {
	    function validate(props, propName, componentName, location, propFullName) {
	      if (!(props[propName] instanceof expectedClass)) {
	        var expectedClassName = expectedClass.name || ANONYMOUS;
	        var actualClassName = getClassName(props[propName]);
	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
	      }
	      return null;
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createEnumTypeChecker(expectedValues) {
	    if (!Array.isArray(expectedValues)) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.') : void 0;
	      return emptyFunction.thatReturnsNull;
	    }

	    function validate(props, propName, componentName, location, propFullName) {
	      var propValue = props[propName];
	      for (var i = 0; i < expectedValues.length; i++) {
	        if (is(propValue, expectedValues[i])) {
	          return null;
	        }
	      }

	      var valuesString = JSON.stringify(expectedValues);
	      return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createObjectOfTypeChecker(typeChecker) {
	    function validate(props, propName, componentName, location, propFullName) {
	      if (typeof typeChecker !== 'function') {
	        return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
	      }
	      var propValue = props[propName];
	      var propType = getPropType(propValue);
	      if (propType !== 'object') {
	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
	      }
	      for (var key in propValue) {
	        if (propValue.hasOwnProperty(key)) {
	          var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
	          if (error instanceof Error) {
	            return error;
	          }
	        }
	      }
	      return null;
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createUnionTypeChecker(arrayOfTypeCheckers) {
	    if (!Array.isArray(arrayOfTypeCheckers)) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.') : void 0;
	      return emptyFunction.thatReturnsNull;
	    }

	    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
	      var checker = arrayOfTypeCheckers[i];
	      if (typeof checker !== 'function') {
	        warning(
	          false,
	          'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +
	          'received %s at index %s.',
	          getPostfixForTypeWarning(checker),
	          i
	        );
	        return emptyFunction.thatReturnsNull;
	      }
	    }

	    function validate(props, propName, componentName, location, propFullName) {
	      for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
	        var checker = arrayOfTypeCheckers[i];
	        if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) {
	          return null;
	        }
	      }

	      return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createNodeChecker() {
	    function validate(props, propName, componentName, location, propFullName) {
	      if (!isNode(props[propName])) {
	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
	      }
	      return null;
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createShapeTypeChecker(shapeTypes) {
	    function validate(props, propName, componentName, location, propFullName) {
	      var propValue = props[propName];
	      var propType = getPropType(propValue);
	      if (propType !== 'object') {
	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
	      }
	      for (var key in shapeTypes) {
	        var checker = shapeTypes[key];
	        if (!checker) {
	          continue;
	        }
	        var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
	        if (error) {
	          return error;
	        }
	      }
	      return null;
	    }
	    return createChainableTypeChecker(validate);
	  }

	  function createStrictShapeTypeChecker(shapeTypes) {
	    function validate(props, propName, componentName, location, propFullName) {
	      var propValue = props[propName];
	      var propType = getPropType(propValue);
	      if (propType !== 'object') {
	        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
	      }
	      // We need to check all keys in case some are required but missing from
	      // props.
	      var allKeys = assign({}, props[propName], shapeTypes);
	      for (var key in allKeys) {
	        var checker = shapeTypes[key];
	        if (!checker) {
	          return new PropTypeError(
	            'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +
	            '\nBad object: ' + JSON.stringify(props[propName], null, '  ') +
	            '\nValid keys: ' +  JSON.stringify(Object.keys(shapeTypes), null, '  ')
	          );
	        }
	        var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
	        if (error) {
	          return error;
	        }
	      }
	      return null;
	    }

	    return createChainableTypeChecker(validate);
	  }

	  function isNode(propValue) {
	    switch (typeof propValue) {
	      case 'number':
	      case 'string':
	      case 'undefined':
	        return true;
	      case 'boolean':
	        return !propValue;
	      case 'object':
	        if (Array.isArray(propValue)) {
	          return propValue.every(isNode);
	        }
	        if (propValue === null || isValidElement(propValue)) {
	          return true;
	        }

	        var iteratorFn = getIteratorFn(propValue);
	        if (iteratorFn) {
	          var iterator = iteratorFn.call(propValue);
	          var step;
	          if (iteratorFn !== propValue.entries) {
	            while (!(step = iterator.next()).done) {
	              if (!isNode(step.value)) {
	                return false;
	              }
	            }
	          } else {
	            // Iterator will provide entry [k,v] tuples rather than values.
	            while (!(step = iterator.next()).done) {
	              var entry = step.value;
	              if (entry) {
	                if (!isNode(entry[1])) {
	                  return false;
	                }
	              }
	            }
	          }
	        } else {
	          return false;
	        }

	        return true;
	      default:
	        return false;
	    }
	  }

	  function isSymbol(propType, propValue) {
	    // Native Symbol.
	    if (propType === 'symbol') {
	      return true;
	    }

	    // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
	    if (propValue['@@toStringTag'] === 'Symbol') {
	      return true;
	    }

	    // Fallback for non-spec compliant Symbols which are polyfilled.
	    if (typeof Symbol === 'function' && propValue instanceof Symbol) {
	      return true;
	    }

	    return false;
	  }

	  // Equivalent of `typeof` but with special handling for array and regexp.
	  function getPropType(propValue) {
	    var propType = typeof propValue;
	    if (Array.isArray(propValue)) {
	      return 'array';
	    }
	    if (propValue instanceof RegExp) {
	      // Old webkits (at least until Android 4.0) return 'function' rather than
	      // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
	      // passes PropTypes.object.
	      return 'object';
	    }
	    if (isSymbol(propType, propValue)) {
	      return 'symbol';
	    }
	    return propType;
	  }

	  // This handles more types than `getPropType`. Only used for error messages.
	  // See `createPrimitiveTypeChecker`.
	  function getPreciseType(propValue) {
	    if (typeof propValue === 'undefined' || propValue === null) {
	      return '' + propValue;
	    }
	    var propType = getPropType(propValue);
	    if (propType === 'object') {
	      if (propValue instanceof Date) {
	        return 'date';
	      } else if (propValue instanceof RegExp) {
	        return 'regexp';
	      }
	    }
	    return propType;
	  }

	  // Returns a string that is postfixed to a warning about an invalid type.
	  // For example, "undefined" or "of type array"
	  function getPostfixForTypeWarning(value) {
	    var type = getPreciseType(value);
	    switch (type) {
	      case 'array':
	      case 'object':
	        return 'an ' + type;
	      case 'boolean':
	      case 'date':
	      case 'regexp':
	        return 'a ' + type;
	      default:
	        return type;
	    }
	  }

	  // Returns class name of the object, if any.
	  function getClassName(propValue) {
	    if (!propValue.constructor || !propValue.constructor.name) {
	      return ANONYMOUS;
	    }
	    return propValue.constructor.name;
	  }

	  ReactPropTypes.checkPropTypes = checkPropTypes;
	  ReactPropTypes.PropTypes = ReactPropTypes;

	  return ReactPropTypes;
	};

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 58 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	'use strict';

	var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';

	module.exports = ReactPropTypesSecret;


/***/ },
/* 59 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	'use strict';

	if (process.env.NODE_ENV !== 'production') {
	  var invariant = __webpack_require__(39);
	  var warning = __webpack_require__(35);
	  var ReactPropTypesSecret = __webpack_require__(58);
	  var loggedTypeFailures = {};
	}

	/**
	 * Assert that the values match with the type specs.
	 * Error messages are memorized and will only be shown once.
	 *
	 * @param {object} typeSpecs Map of name to a ReactPropType
	 * @param {object} values Runtime values that need to be type-checked
	 * @param {string} location e.g. "prop", "context", "child context"
	 * @param {string} componentName Name of the component for error messages.
	 * @param {?Function} getStack Returns the component stack.
	 * @private
	 */
	function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
	  if (process.env.NODE_ENV !== 'production') {
	    for (var typeSpecName in typeSpecs) {
	      if (typeSpecs.hasOwnProperty(typeSpecName)) {
	        var error;
	        // Prop type validation may throw. In case they do, we don't want to
	        // fail the render phase where it didn't fail before. So we log it.
	        // After these have been cleaned up, we'll let them throw.
	        try {
	          // This is intentionally an invariant that gets caught. It's the same
	          // behavior as without this statement except with a better message.
	          invariant(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'the `prop-types` package, but received `%s`.', componentName || 'React class', location, typeSpecName, typeof typeSpecs[typeSpecName]);
	          error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
	        } catch (ex) {
	          error = ex;
	        }
	        warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error);
	        if (error instanceof Error && !(error.message in loggedTypeFailures)) {
	          // Only monitor this failure once because there tends to be a lot of the
	          // same error.
	          loggedTypeFailures[error.message] = true;

	          var stack = getStack ? getStack() : '';

	          warning(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : '');
	        }
	      }
	    }
	  }
	}

	module.exports = checkPropTypes;

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 60 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	module.exports = '15.6.2';

/***/ },
/* 61 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _require = __webpack_require__(32),
	    Component = _require.Component;

	var _require2 = __webpack_require__(43),
	    isValidElement = _require2.isValidElement;

	var ReactNoopUpdateQueue = __webpack_require__(34);
	var factory = __webpack_require__(62);

	module.exports = factory(Component, isValidElement, ReactNoopUpdateQueue);

/***/ },
/* 62 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright 2013-present, Facebook, Inc.
	 * All rights reserved.
	 *
	 * This source code is licensed under the BSD-style license found in the
	 * LICENSE file in the root directory of this source tree. An additional grant
	 * of patent rights can be found in the PATENTS file in the same directory.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var emptyObject = __webpack_require__(38);
	var _invariant = __webpack_require__(39);

	if (process.env.NODE_ENV !== 'production') {
	  var warning = __webpack_require__(35);
	}

	var MIXINS_KEY = 'mixins';

	// Helper function to allow the creation of anonymous functions which do not
	// have .name set to the name of the variable being assigned to.
	function identity(fn) {
	  return fn;
	}

	var ReactPropTypeLocationNames;
	if (process.env.NODE_ENV !== 'production') {
	  ReactPropTypeLocationNames = {
	    prop: 'prop',
	    context: 'context',
	    childContext: 'child context',
	  };
	} else {
	  ReactPropTypeLocationNames = {};
	}

	function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) {
	  /**
	   * Policies that describe methods in `ReactClassInterface`.
	   */


	  var injectedMixins = [];

	  /**
	   * Composite components are higher-level components that compose other composite
	   * or host components.
	   *
	   * To create a new type of `ReactClass`, pass a specification of
	   * your new class to `React.createClass`. The only requirement of your class
	   * specification is that you implement a `render` method.
	   *
	   *   var MyComponent = React.createClass({
	   *     render: function() {
	   *       return <div>Hello World</div>;
	   *     }
	   *   });
	   *
	   * The class specification supports a specific protocol of methods that have
	   * special meaning (e.g. `render`). See `ReactClassInterface` for
	   * more the comprehensive protocol. Any other properties and methods in the
	   * class specification will be available on the prototype.
	   *
	   * @interface ReactClassInterface
	   * @internal
	   */
	  var ReactClassInterface = {

	    /**
	     * An array of Mixin objects to include when defining your component.
	     *
	     * @type {array}
	     * @optional
	     */
	    mixins: 'DEFINE_MANY',

	    /**
	     * An object containing properties and methods that should be defined on
	     * the component's constructor instead of its prototype (static methods).
	     *
	     * @type {object}
	     * @optional
	     */
	    statics: 'DEFINE_MANY',

	    /**
	     * Definition of prop types for this component.
	     *
	     * @type {object}
	     * @optional
	     */
	    propTypes: 'DEFINE_MANY',

	    /**
	     * Definition of context types for this component.
	     *
	     * @type {object}
	     * @optional
	     */
	    contextTypes: 'DEFINE_MANY',

	    /**
	     * Definition of context types this component sets for its children.
	     *
	     * @type {object}
	     * @optional
	     */
	    childContextTypes: 'DEFINE_MANY',

	    // ==== Definition methods ====

	    /**
	     * Invoked when the component is mounted. Values in the mapping will be set on
	     * `this.props` if that prop is not specified (i.e. using an `in` check).
	     *
	     * This method is invoked before `getInitialState` and therefore cannot rely
	     * on `this.state` or use `this.setState`.
	     *
	     * @return {object}
	     * @optional
	     */
	    getDefaultProps: 'DEFINE_MANY_MERGED',

	    /**
	     * Invoked once before the component is mounted. The return value will be used
	     * as the initial value of `this.state`.
	     *
	     *   getInitialState: function() {
	     *     return {
	     *       isOn: false,
	     *       fooBaz: new BazFoo()
	     *     }
	     *   }
	     *
	     * @return {object}
	     * @optional
	     */
	    getInitialState: 'DEFINE_MANY_MERGED',

	    /**
	     * @return {object}
	     * @optional
	     */
	    getChildContext: 'DEFINE_MANY_MERGED',

	    /**
	     * Uses props from `this.props` and state from `this.state` to render the
	     * structure of the component.
	     *
	     * No guarantees are made about when or how often this method is invoked, so
	     * it must not have side effects.
	     *
	     *   render: function() {
	     *     var name = this.props.name;
	     *     return <div>Hello, {name}!</div>;
	     *   }
	     *
	     * @return {ReactComponent}
	     * @nosideeffects
	     * @required
	     */
	    render: 'DEFINE_ONCE',

	    // ==== Delegate methods ====

	    /**
	     * Invoked when the component is initially created and about to be mounted.
	     * This may have side effects, but any external subscriptions or data created
	     * by this method must be cleaned up in `componentWillUnmount`.
	     *
	     * @optional
	     */
	    componentWillMount: 'DEFINE_MANY',

	    /**
	     * Invoked when the component has been mounted and has a DOM representation.
	     * However, there is no guarantee that the DOM node is in the document.
	     *
	     * Use this as an opportunity to operate on the DOM when the component has
	     * been mounted (initialized and rendered) for the first time.
	     *
	     * @param {DOMElement} rootNode DOM element representing the component.
	     * @optional
	     */
	    componentDidMount: 'DEFINE_MANY',

	    /**
	     * Invoked before the component receives new props.
	     *
	     * Use this as an opportunity to react to a prop transition by updating the
	     * state using `this.setState`. Current props are accessed via `this.props`.
	     *
	     *   componentWillReceiveProps: function(nextProps, nextContext) {
	     *     this.setState({
	     *       likesIncreasing: nextProps.likeCount > this.props.likeCount
	     *     });
	     *   }
	     *
	     * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
	     * transition may cause a state change, but the opposite is not true. If you
	     * need it, you are probably looking for `componentWillUpdate`.
	     *
	     * @param {object} nextProps
	     * @optional
	     */
	    componentWillReceiveProps: 'DEFINE_MANY',

	    /**
	     * Invoked while deciding if the component should be updated as a result of
	     * receiving new props, state and/or context.
	     *
	     * Use this as an opportunity to `return false` when you're certain that the
	     * transition to the new props/state/context will not require a component
	     * update.
	     *
	     *   shouldComponentUpdate: function(nextProps, nextState, nextContext) {
	     *     return !equal(nextProps, this.props) ||
	     *       !equal(nextState, this.state) ||
	     *       !equal(nextContext, this.context);
	     *   }
	     *
	     * @param {object} nextProps
	     * @param {?object} nextState
	     * @param {?object} nextContext
	     * @return {boolean} True if the component should update.
	     * @optional
	     */
	    shouldComponentUpdate: 'DEFINE_ONCE',

	    /**
	     * Invoked when the component is about to update due to a transition from
	     * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
	     * and `nextContext`.
	     *
	     * Use this as an opportunity to perform preparation before an update occurs.
	     *
	     * NOTE: You **cannot** use `this.setState()` in this method.
	     *
	     * @param {object} nextProps
	     * @param {?object} nextState
	     * @param {?object} nextContext
	     * @param {ReactReconcileTransaction} transaction
	     * @optional
	     */
	    componentWillUpdate: 'DEFINE_MANY',

	    /**
	     * Invoked when the component's DOM representation has been updated.
	     *
	     * Use this as an opportunity to operate on the DOM when the component has
	     * been updated.
	     *
	     * @param {object} prevProps
	     * @param {?object} prevState
	     * @param {?object} prevContext
	     * @param {DOMElement} rootNode DOM element representing the component.
	     * @optional
	     */
	    componentDidUpdate: 'DEFINE_MANY',

	    /**
	     * Invoked when the component is about to be removed from its parent and have
	     * its DOM representation destroyed.
	     *
	     * Use this as an opportunity to deallocate any external resources.
	     *
	     * NOTE: There is no `componentDidUnmount` since your component will have been
	     * destroyed by that point.
	     *
	     * @optional
	     */
	    componentWillUnmount: 'DEFINE_MANY',

	    // ==== Advanced methods ====

	    /**
	     * Updates the component's currently mounted DOM representation.
	     *
	     * By default, this implements React's rendering and reconciliation algorithm.
	     * Sophisticated clients may wish to override this.
	     *
	     * @param {ReactReconcileTransaction} transaction
	     * @internal
	     * @overridable
	     */
	    updateComponent: 'OVERRIDE_BASE'

	  };

	  /**
	   * Mapping from class specification keys to special processing functions.
	   *
	   * Although these are declared like instance properties in the specification
	   * when defining classes using `React.createClass`, they are actually static
	   * and are accessible on the constructor instead of the prototype. Despite
	   * being static, they must be defined outside of the "statics" key under
	   * which all other static methods are defined.
	   */
	  var RESERVED_SPEC_KEYS = {
	    displayName: function (Constructor, displayName) {
	      Constructor.displayName = displayName;
	    },
	    mixins: function (Constructor, mixins) {
	      if (mixins) {
	        for (var i = 0; i < mixins.length; i++) {
	          mixSpecIntoComponent(Constructor, mixins[i]);
	        }
	      }
	    },
	    childContextTypes: function (Constructor, childContextTypes) {
	      if (process.env.NODE_ENV !== 'production') {
	        validateTypeDef(Constructor, childContextTypes, 'childContext');
	      }
	      Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes);
	    },
	    contextTypes: function (Constructor, contextTypes) {
	      if (process.env.NODE_ENV !== 'production') {
	        validateTypeDef(Constructor, contextTypes, 'context');
	      }
	      Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes);
	    },
	    /**
	     * Special case getDefaultProps which should move into statics but requires
	     * automatic merging.
	     */
	    getDefaultProps: function (Constructor, getDefaultProps) {
	      if (Constructor.getDefaultProps) {
	        Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps);
	      } else {
	        Constructor.getDefaultProps = getDefaultProps;
	      }
	    },
	    propTypes: function (Constructor, propTypes) {
	      if (process.env.NODE_ENV !== 'production') {
	        validateTypeDef(Constructor, propTypes, 'prop');
	      }
	      Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes);
	    },
	    statics: function (Constructor, statics) {
	      mixStaticSpecIntoComponent(Constructor, statics);
	    },
	    autobind: function () {} };

	  function validateTypeDef(Constructor, typeDef, location) {
	    for (var propName in typeDef) {
	      if (typeDef.hasOwnProperty(propName)) {
	        // use a warning instead of an _invariant so components
	        // don't show up in prod but only in __DEV__
	        process.env.NODE_ENV !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0;
	      }
	    }
	  }

	  function validateMethodOverride(isAlreadyDefined, name) {
	    var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null;

	    // Disallow overriding of base class methods unless explicitly allowed.
	    if (ReactClassMixin.hasOwnProperty(name)) {
	      _invariant(specPolicy === 'OVERRIDE_BASE', 'ReactClassInterface: You are attempting to override ' + '`%s` from your class specification. Ensure that your method names ' + 'do not overlap with React methods.', name);
	    }

	    // Disallow defining methods more than once unless explicitly allowed.
	    if (isAlreadyDefined) {
	      _invariant(specPolicy === 'DEFINE_MANY' || specPolicy === 'DEFINE_MANY_MERGED', 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name);
	    }
	  }

	  /**
	   * Mixin helper which handles policy validation and reserved
	   * specification keys when building React classes.
	   */
	  function mixSpecIntoComponent(Constructor, spec) {
	    if (!spec) {
	      if (process.env.NODE_ENV !== 'production') {
	        var typeofSpec = typeof spec;
	        var isMixinValid = typeofSpec === 'object' && spec !== null;

	        process.env.NODE_ENV !== 'production' ? warning(isMixinValid, '%s: You\'re attempting to include a mixin that is either null ' + 'or not an object. Check the mixins included by the component, ' + 'as well as any mixins they include themselves. ' + 'Expected object but got %s.', Constructor.displayName || 'ReactClass', spec === null ? null : typeofSpec) : void 0;
	      }

	      return;
	    }

	    _invariant(typeof spec !== 'function', 'ReactClass: You\'re attempting to ' + 'use a component class or function as a mixin. Instead, just use a ' + 'regular object.');
	    _invariant(!isValidElement(spec), 'ReactClass: You\'re attempting to ' + 'use a component as a mixin. Instead, just use a regular object.');

	    var proto = Constructor.prototype;
	    var autoBindPairs = proto.__reactAutoBindPairs;

	    // By handling mixins before any other properties, we ensure the same
	    // chaining order is applied to methods with DEFINE_MANY policy, whether
	    // mixins are listed before or after these methods in the spec.
	    if (spec.hasOwnProperty(MIXINS_KEY)) {
	      RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
	    }

	    for (var name in spec) {
	      if (!spec.hasOwnProperty(name)) {
	        continue;
	      }

	      if (name === MIXINS_KEY) {
	        // We have already handled mixins in a special case above.
	        continue;
	      }

	      var property = spec[name];
	      var isAlreadyDefined = proto.hasOwnProperty(name);
	      validateMethodOverride(isAlreadyDefined, name);

	      if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
	        RESERVED_SPEC_KEYS[name](Constructor, property);
	      } else {
	        // Setup methods on prototype:
	        // The following member methods should not be automatically bound:
	        // 1. Expected ReactClass methods (in the "interface").
	        // 2. Overridden methods (that were mixed in).
	        var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
	        var isFunction = typeof property === 'function';
	        var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;

	        if (shouldAutoBind) {
	          autoBindPairs.push(name, property);
	          proto[name] = property;
	        } else {
	          if (isAlreadyDefined) {
	            var specPolicy = ReactClassInterface[name];

	            // These cases should already be caught by validateMethodOverride.
	            _invariant(isReactClassMethod && (specPolicy === 'DEFINE_MANY_MERGED' || specPolicy === 'DEFINE_MANY'), 'ReactClass: Unexpected spec policy %s for key %s ' + 'when mixing in component specs.', specPolicy, name);

	            // For methods which are defined more than once, call the existing
	            // methods before calling the new property, merging if appropriate.
	            if (specPolicy === 'DEFINE_MANY_MERGED') {
	              proto[name] = createMergedResultFunction(proto[name], property);
	            } else if (specPolicy === 'DEFINE_MANY') {
	              proto[name] = createChainedFunction(proto[name], property);
	            }
	          } else {
	            proto[name] = property;
	            if (process.env.NODE_ENV !== 'production') {
	              // Add verbose displayName to the function, which helps when looking
	              // at profiling tools.
	              if (typeof property === 'function' && spec.displayName) {
	                proto[name].displayName = spec.displayName + '_' + name;
	              }
	            }
	          }
	        }
	      }
	    }
	  }

	  function mixStaticSpecIntoComponent(Constructor, statics) {
	    if (!statics) {
	      return;
	    }
	    for (var name in statics) {
	      var property = statics[name];
	      if (!statics.hasOwnProperty(name)) {
	        continue;
	      }

	      var isReserved = name in RESERVED_SPEC_KEYS;
	      _invariant(!isReserved, 'ReactClass: You are attempting to define a reserved ' + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + 'as an instance property instead; it will still be accessible on the ' + 'constructor.', name);

	      var isInherited = name in Constructor;
	      _invariant(!isInherited, 'ReactClass: You are attempting to define ' + '`%s` on your component more than once. This conflict may be ' + 'due to a mixin.', name);
	      Constructor[name] = property;
	    }
	  }

	  /**
	   * Merge two objects, but throw if both contain the same key.
	   *
	   * @param {object} one The first object, which is mutated.
	   * @param {object} two The second object
	   * @return {object} one after it has been mutated to contain everything in two.
	   */
	  function mergeIntoWithNoDuplicateKeys(one, two) {
	    _invariant(one && two && typeof one === 'object' && typeof two === 'object', 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.');

	    for (var key in two) {
	      if (two.hasOwnProperty(key)) {
	        _invariant(one[key] === undefined, 'mergeIntoWithNoDuplicateKeys(): ' + 'Tried to merge two objects with the same key: `%s`. This conflict ' + 'may be due to a mixin; in particular, this may be caused by two ' + 'getInitialState() or getDefaultProps() methods returning objects ' + 'with clashing keys.', key);
	        one[key] = two[key];
	      }
	    }
	    return one;
	  }

	  /**
	   * Creates a function that invokes two functions and merges their return values.
	   *
	   * @param {function} one Function to invoke first.
	   * @param {function} two Function to invoke second.
	   * @return {function} Function that invokes the two argument functions.
	   * @private
	   */
	  function createMergedResultFunction(one, two) {
	    return function mergedResult() {
	      var a = one.apply(this, arguments);
	      var b = two.apply(this, arguments);
	      if (a == null) {
	        return b;
	      } else if (b == null) {
	        return a;
	      }
	      var c = {};
	      mergeIntoWithNoDuplicateKeys(c, a);
	      mergeIntoWithNoDuplicateKeys(c, b);
	      return c;
	    };
	  }

	  /**
	   * Creates a function that invokes two functions and ignores their return vales.
	   *
	   * @param {function} one Function to invoke first.
	   * @param {function} two Function to invoke second.
	   * @return {function} Function that invokes the two argument functions.
	   * @private
	   */
	  function createChainedFunction(one, two) {
	    return function chainedFunction() {
	      one.apply(this, arguments);
	      two.apply(this, arguments);
	    };
	  }

	  /**
	   * Binds a method to the component.
	   *
	   * @param {object} component Component whose method is going to be bound.
	   * @param {function} method Method to be bound.
	   * @return {function} The bound method.
	   */
	  function bindAutoBindMethod(component, method) {
	    var boundMethod = method.bind(component);
	    if (process.env.NODE_ENV !== 'production') {
	      boundMethod.__reactBoundContext = component;
	      boundMethod.__reactBoundMethod = method;
	      boundMethod.__reactBoundArguments = null;
	      var componentName = component.constructor.displayName;
	      var _bind = boundMethod.bind;
	      boundMethod.bind = function (newThis) {
	        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
	          args[_key - 1] = arguments[_key];
	        }

	        // User is trying to bind() an autobound method; we effectively will
	        // ignore the value of "this" that the user is trying to use, so
	        // let's warn.
	        if (newThis !== component && newThis !== null) {
	          process.env.NODE_ENV !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0;
	        } else if (!args.length) {
	          process.env.NODE_ENV !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0;
	          return boundMethod;
	        }
	        var reboundMethod = _bind.apply(boundMethod, arguments);
	        reboundMethod.__reactBoundContext = component;
	        reboundMethod.__reactBoundMethod = method;
	        reboundMethod.__reactBoundArguments = args;
	        return reboundMethod;
	      };
	    }
	    return boundMethod;
	  }

	  /**
	   * Binds all auto-bound methods in a component.
	   *
	   * @param {object} component Component whose method is going to be bound.
	   */
	  function bindAutoBindMethods(component) {
	    var pairs = component.__reactAutoBindPairs;
	    for (var i = 0; i < pairs.length; i += 2) {
	      var autoBindKey = pairs[i];
	      var method = pairs[i + 1];
	      component[autoBindKey] = bindAutoBindMethod(component, method);
	    }
	  }

	  var IsMountedMixin = {
	    componentDidMount: function () {
	      this.__isMounted = true;
	    },
	    componentWillUnmount: function () {
	      this.__isMounted = false;
	    }
	  };

	  /**
	   * Add more to the ReactClass base class. These are all legacy features and
	   * therefore not already part of the modern ReactComponent.
	   */
	  var ReactClassMixin = {

	    /**
	     * TODO: This will be deprecated because state should always keep a consistent
	     * type signature and the only use case for this, is to avoid that.
	     */
	    replaceState: function (newState, callback) {
	      this.updater.enqueueReplaceState(this, newState, callback);
	    },

	    /**
	     * Checks whether or not this composite component is mounted.
	     * @return {boolean} True if mounted, false otherwise.
	     * @protected
	     * @final
	     */
	    isMounted: function () {
	      if (process.env.NODE_ENV !== 'production') {
	        process.env.NODE_ENV !== 'production' ? warning(this.__didWarnIsMounted, '%s: isMounted is deprecated. Instead, make sure to clean up ' + 'subscriptions and pending requests in componentWillUnmount to ' + 'prevent memory leaks.', this.constructor && this.constructor.displayName || this.name || 'Component') : void 0;
	        this.__didWarnIsMounted = true;
	      }
	      return !!this.__isMounted;
	    }
	  };

	  var ReactClassComponent = function () {};
	  _assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);

	  /**
	   * Creates a composite component class given a class specification.
	   * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass
	   *
	   * @param {object} spec Class specification (which must define `render`).
	   * @return {function} Component constructor function.
	   * @public
	   */
	  function createClass(spec) {
	    // To keep our warnings more understandable, we'll use a little hack here to
	    // ensure that Constructor.name !== 'Constructor'. This makes sure we don't
	    // unnecessarily identify a class without displayName as 'Constructor'.
	    var Constructor = identity(function (props, context, updater) {
	      // This constructor gets overridden by mocks. The argument is used
	      // by mocks to assert on what gets mounted.

	      if (process.env.NODE_ENV !== 'production') {
	        process.env.NODE_ENV !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0;
	      }

	      // Wire up auto-binding
	      if (this.__reactAutoBindPairs.length) {
	        bindAutoBindMethods(this);
	      }

	      this.props = props;
	      this.context = context;
	      this.refs = emptyObject;
	      this.updater = updater || ReactNoopUpdateQueue;

	      this.state = null;

	      // ReactClasses doesn't have constructors. Instead, they use the
	      // getInitialState and componentWillMount methods for initialization.

	      var initialState = this.getInitialState ? this.getInitialState() : null;
	      if (process.env.NODE_ENV !== 'production') {
	        // We allow auto-mocks to proceed as if they're returning null.
	        if (initialState === undefined && this.getInitialState._isMockFunction) {
	          // This is probably bad practice. Consider warning here and
	          // deprecating this convenience.
	          initialState = null;
	        }
	      }
	      _invariant(typeof initialState === 'object' && !Array.isArray(initialState), '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent');

	      this.state = initialState;
	    });
	    Constructor.prototype = new ReactClassComponent();
	    Constructor.prototype.constructor = Constructor;
	    Constructor.prototype.__reactAutoBindPairs = [];

	    injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));

	    mixSpecIntoComponent(Constructor, IsMountedMixin);
	    mixSpecIntoComponent(Constructor, spec);

	    // Initialize the defaultProps property after all mixins have been merged.
	    if (Constructor.getDefaultProps) {
	      Constructor.defaultProps = Constructor.getDefaultProps();
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      // This is a tag to indicate that the use of these method names is ok,
	      // since it's used with createClass. If it's not, then it's likely a
	      // mistake so we'll warn you to use the static property, property
	      // initializer or constructor respectively.
	      if (Constructor.getDefaultProps) {
	        Constructor.getDefaultProps.isReactClassApproved = {};
	      }
	      if (Constructor.prototype.getInitialState) {
	        Constructor.prototype.getInitialState.isReactClassApproved = {};
	      }
	    }

	    _invariant(Constructor.prototype.render, 'createClass(...): Class specification must implement a `render` method.');

	    if (process.env.NODE_ENV !== 'production') {
	      process.env.NODE_ENV !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0;
	      process.env.NODE_ENV !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0;
	    }

	    // Reduce time spent doing lookups by setting these on the prototype.
	    for (var methodName in ReactClassInterface) {
	      if (!Constructor.prototype[methodName]) {
	        Constructor.prototype[methodName] = null;
	      }
	    }

	    return Constructor;
	  }

	  return createClass;
	}

	module.exports = factory;

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 63 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */
	'use strict';

	var _prodInvariant = __webpack_require__(33);

	var ReactElement = __webpack_require__(43);

	var invariant = __webpack_require__(39);

	/**
	 * Returns the first child in a collection of children and verifies that there
	 * is only one child in the collection.
	 *
	 * See https://facebook.github.io/react/docs/top-level-api.html#react.children.only
	 *
	 * The current implementation of this function assumes that a single child gets
	 * passed without a wrapper, but the purpose of this helper function is to
	 * abstract away the particular structure of children.
	 *
	 * @param {?object} children Child collection structure.
	 * @return {ReactElement} The first and only `ReactElement` contained in the
	 * structure.
	 */
	function onlyChild(children) {
	  !ReactElement.isValidElement(children) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'React.Children.only expected to receive a single React element child.') : _prodInvariant('143') : void 0;
	  return children;
	}

	module.exports = onlyChild;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 64 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	module.exports = __webpack_require__(65);


/***/ },
/* 65 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/

	'use strict';

	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactDefaultInjection = __webpack_require__(70);
	var ReactMount = __webpack_require__(199);
	var ReactReconciler = __webpack_require__(91);
	var ReactUpdates = __webpack_require__(88);
	var ReactVersion = __webpack_require__(204);

	var findDOMNode = __webpack_require__(205);
	var getHostComponentFromComposite = __webpack_require__(206);
	var renderSubtreeIntoContainer = __webpack_require__(207);
	var warning = __webpack_require__(35);

	ReactDefaultInjection.inject();

	var ReactDOM = {
	  findDOMNode: findDOMNode,
	  render: ReactMount.render,
	  unmountComponentAtNode: ReactMount.unmountComponentAtNode,
	  version: ReactVersion,

	  /* eslint-disable camelcase */
	  unstable_batchedUpdates: ReactUpdates.batchedUpdates,
	  unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
	  /* eslint-enable camelcase */
	};

	// Inject the runtime into a devtools global hook regardless of browser.
	// Allows for debugging when the hook is injected on the page.
	if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
	  __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
	    ComponentTree: {
	      getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,
	      getNodeFromInstance: function (inst) {
	        // inst is an internal instance (but could be a composite)
	        if (inst._renderedComponent) {
	          inst = getHostComponentFromComposite(inst);
	        }
	        if (inst) {
	          return ReactDOMComponentTree.getNodeFromInstance(inst);
	        } else {
	          return null;
	        }
	      }
	    },
	    Mount: ReactMount,
	    Reconciler: ReactReconciler
	  });
	}

	if (process.env.NODE_ENV !== 'production') {
	  var ExecutionEnvironment = __webpack_require__(80);
	  if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
	    // First check if devtools is not installed
	    if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
	      // If we're in Chrome or Firefox, provide a download link if not installed.
	      if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
	        // Firefox does not have the issue with devtools loaded over file://
	        var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;
	        console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');
	      }
	    }

	    var testFunc = function testFn() {};
	    process.env.NODE_ENV !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, "It looks like you're using a minified copy of the development build " + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;

	    // If we're in IE8, check to see if we are in compatibility mode and provide
	    // information on preventing compatibility mode
	    var ieCompatibilityMode = document.documentMode && document.documentMode < 8;

	    process.env.NODE_ENV !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv="X-UA-Compatible" content="IE=edge" />') : void 0;

	    var expectedFeatures = [
	    // shims
	    Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.trim];

	    for (var i = 0; i < expectedFeatures.length; i++) {
	      if (!expectedFeatures[i]) {
	        process.env.NODE_ENV !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;
	        break;
	      }
	    }
	  }
	}

	if (process.env.NODE_ENV !== 'production') {
	  var ReactInstrumentation = __webpack_require__(94);
	  var ReactDOMUnknownPropertyHook = __webpack_require__(208);
	  var ReactDOMNullInputValuePropHook = __webpack_require__(209);
	  var ReactDOMInvalidARIAHook = __webpack_require__(210);

	  ReactInstrumentation.debugTool.addHook(ReactDOMUnknownPropertyHook);
	  ReactInstrumentation.debugTool.addHook(ReactDOMNullInputValuePropHook);
	  ReactInstrumentation.debugTool.addHook(ReactDOMInvalidARIAHook);
	}

	module.exports = ReactDOM;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 66 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var DOMProperty = __webpack_require__(68);
	var ReactDOMComponentFlags = __webpack_require__(69);

	var invariant = __webpack_require__(39);

	var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
	var Flags = ReactDOMComponentFlags;

	var internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);

	/**
	 * Check if a given node should be cached.
	 */
	function shouldPrecacheNode(node, nodeID) {
	  return node.nodeType === 1 && node.getAttribute(ATTR_NAME) === String(nodeID) || node.nodeType === 8 && node.nodeValue === ' react-text: ' + nodeID + ' ' || node.nodeType === 8 && node.nodeValue === ' react-empty: ' + nodeID + ' ';
	}

	/**
	 * Drill down (through composites and empty components) until we get a host or
	 * host text component.
	 *
	 * This is pretty polymorphic but unavoidable with the current structure we have
	 * for `_renderedChildren`.
	 */
	function getRenderedHostOrTextFromComponent(component) {
	  var rendered;
	  while (rendered = component._renderedComponent) {
	    component = rendered;
	  }
	  return component;
	}

	/**
	 * Populate `_hostNode` on the rendered host/text component with the given
	 * DOM node. The passed `inst` can be a composite.
	 */
	function precacheNode(inst, node) {
	  var hostInst = getRenderedHostOrTextFromComponent(inst);
	  hostInst._hostNode = node;
	  node[internalInstanceKey] = hostInst;
	}

	function uncacheNode(inst) {
	  var node = inst._hostNode;
	  if (node) {
	    delete node[internalInstanceKey];
	    inst._hostNode = null;
	  }
	}

	/**
	 * Populate `_hostNode` on each child of `inst`, assuming that the children
	 * match up with the DOM (element) children of `node`.
	 *
	 * We cache entire levels at once to avoid an n^2 problem where we access the
	 * children of a node sequentially and have to walk from the start to our target
	 * node every time.
	 *
	 * Since we update `_renderedChildren` and the actual DOM at (slightly)
	 * different times, we could race here and see a newer `_renderedChildren` than
	 * the DOM nodes we see. To avoid this, ReactMultiChild calls
	 * `prepareToManageChildren` before we change `_renderedChildren`, at which
	 * time the container's child nodes are always cached (until it unmounts).
	 */
	function precacheChildNodes(inst, node) {
	  if (inst._flags & Flags.hasCachedChildNodes) {
	    return;
	  }
	  var children = inst._renderedChildren;
	  var childNode = node.firstChild;
	  outer: for (var name in children) {
	    if (!children.hasOwnProperty(name)) {
	      continue;
	    }
	    var childInst = children[name];
	    var childID = getRenderedHostOrTextFromComponent(childInst)._domID;
	    if (childID === 0) {
	      // We're currently unmounting this child in ReactMultiChild; skip it.
	      continue;
	    }
	    // We assume the child nodes are in the same order as the child instances.
	    for (; childNode !== null; childNode = childNode.nextSibling) {
	      if (shouldPrecacheNode(childNode, childID)) {
	        precacheNode(childInst, childNode);
	        continue outer;
	      }
	    }
	    // We reached the end of the DOM children without finding an ID match.
	     true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : _prodInvariant('32', childID) : void 0;
	  }
	  inst._flags |= Flags.hasCachedChildNodes;
	}

	/**
	 * Given a DOM node, return the closest ReactDOMComponent or
	 * ReactDOMTextComponent instance ancestor.
	 */
	function getClosestInstanceFromNode(node) {
	  if (node[internalInstanceKey]) {
	    return node[internalInstanceKey];
	  }

	  // Walk up the tree until we find an ancestor whose instance we have cached.
	  var parents = [];
	  while (!node[internalInstanceKey]) {
	    parents.push(node);
	    if (node.parentNode) {
	      node = node.parentNode;
	    } else {
	      // Top of the tree. This node must not be part of a React tree (or is
	      // unmounted, potentially).
	      return null;
	    }
	  }

	  var closest;
	  var inst;
	  for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
	    closest = inst;
	    if (parents.length) {
	      precacheChildNodes(inst, node);
	    }
	  }

	  return closest;
	}

	/**
	 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
	 * instance, or null if the node was not rendered by this React.
	 */
	function getInstanceFromNode(node) {
	  var inst = getClosestInstanceFromNode(node);
	  if (inst != null && inst._hostNode === node) {
	    return inst;
	  } else {
	    return null;
	  }
	}

	/**
	 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
	 * DOM node.
	 */
	function getNodeFromInstance(inst) {
	  // Without this first invariant, passing a non-DOM-component triggers the next
	  // invariant for a missing parent, which is super confusing.
	  !(inst._hostNode !== undefined) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;

	  if (inst._hostNode) {
	    return inst._hostNode;
	  }

	  // Walk up the tree until we find an ancestor whose DOM node we have cached.
	  var parents = [];
	  while (!inst._hostNode) {
	    parents.push(inst);
	    !inst._hostParent ? process.env.NODE_ENV !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') : _prodInvariant('34') : void 0;
	    inst = inst._hostParent;
	  }

	  // Now parents contains each ancestor that does *not* have a cached native
	  // node, and `inst` is the deepest ancestor that does.
	  for (; parents.length; inst = parents.pop()) {
	    precacheChildNodes(inst, inst._hostNode);
	  }

	  return inst._hostNode;
	}

	var ReactDOMComponentTree = {
	  getClosestInstanceFromNode: getClosestInstanceFromNode,
	  getInstanceFromNode: getInstanceFromNode,
	  getNodeFromInstance: getNodeFromInstance,
	  precacheChildNodes: precacheChildNodes,
	  precacheNode: precacheNode,
	  uncacheNode: uncacheNode
	};

	module.exports = ReactDOMComponentTree;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 67 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */
	'use strict';

	/**
	 * WARNING: DO NOT manually require this module.
	 * This is a replacement for `invariant(...)` used by the error code system
	 * and will _only_ be required by the corresponding babel pass.
	 * It always throws.
	 */

	function reactProdInvariant(code) {
	  var argCount = arguments.length - 1;

	  var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;

	  for (var argIdx = 0; argIdx < argCount; argIdx++) {
	    message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
	  }

	  message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';

	  var error = new Error(message);
	  error.name = 'Invariant Violation';
	  error.framesToPop = 1; // we don't care about reactProdInvariant's own frame

	  throw error;
	}

	module.exports = reactProdInvariant;

/***/ },
/* 68 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	function checkMask(value, bitmask) {
	  return (value & bitmask) === bitmask;
	}

	var DOMPropertyInjection = {
	  /**
	   * Mapping from normalized, camelcased property names to a configuration that
	   * specifies how the associated DOM property should be accessed or rendered.
	   */
	  MUST_USE_PROPERTY: 0x1,
	  HAS_BOOLEAN_VALUE: 0x4,
	  HAS_NUMERIC_VALUE: 0x8,
	  HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,
	  HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,

	  /**
	   * Inject some specialized knowledge about the DOM. This takes a config object
	   * with the following properties:
	   *
	   * isCustomAttribute: function that given an attribute name will return true
	   * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*
	   * attributes where it's impossible to enumerate all of the possible
	   * attribute names,
	   *
	   * Properties: object mapping DOM property name to one of the
	   * DOMPropertyInjection constants or null. If your attribute isn't in here,
	   * it won't get written to the DOM.
	   *
	   * DOMAttributeNames: object mapping React attribute name to the DOM
	   * attribute name. Attribute names not specified use the **lowercase**
	   * normalized name.
	   *
	   * DOMAttributeNamespaces: object mapping React attribute name to the DOM
	   * attribute namespace URL. (Attribute names not specified use no namespace.)
	   *
	   * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.
	   * Property names not specified use the normalized name.
	   *
	   * DOMMutationMethods: Properties that require special mutation methods. If
	   * `value` is undefined, the mutation method should unset the property.
	   *
	   * @param {object} domPropertyConfig the config as described above.
	   */
	  injectDOMPropertyConfig: function (domPropertyConfig) {
	    var Injection = DOMPropertyInjection;
	    var Properties = domPropertyConfig.Properties || {};
	    var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};
	    var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};
	    var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};
	    var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};

	    if (domPropertyConfig.isCustomAttribute) {
	      DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute);
	    }

	    for (var propName in Properties) {
	      !!DOMProperty.properties.hasOwnProperty(propName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property \'%s\' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.', propName) : _prodInvariant('48', propName) : void 0;

	      var lowerCased = propName.toLowerCase();
	      var propConfig = Properties[propName];

	      var propertyInfo = {
	        attributeName: lowerCased,
	        attributeNamespace: null,
	        propertyName: propName,
	        mutationMethod: null,

	        mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),
	        hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),
	        hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),
	        hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),
	        hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE)
	      };
	      !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : _prodInvariant('50', propName) : void 0;

	      if (process.env.NODE_ENV !== 'production') {
	        DOMProperty.getPossibleStandardName[lowerCased] = propName;
	      }

	      if (DOMAttributeNames.hasOwnProperty(propName)) {
	        var attributeName = DOMAttributeNames[propName];
	        propertyInfo.attributeName = attributeName;
	        if (process.env.NODE_ENV !== 'production') {
	          DOMProperty.getPossibleStandardName[attributeName] = propName;
	        }
	      }

	      if (DOMAttributeNamespaces.hasOwnProperty(propName)) {
	        propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];
	      }

	      if (DOMPropertyNames.hasOwnProperty(propName)) {
	        propertyInfo.propertyName = DOMPropertyNames[propName];
	      }

	      if (DOMMutationMethods.hasOwnProperty(propName)) {
	        propertyInfo.mutationMethod = DOMMutationMethods[propName];
	      }

	      DOMProperty.properties[propName] = propertyInfo;
	    }
	  }
	};

	/* eslint-disable max-len */
	var ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';
	/* eslint-enable max-len */

	/**
	 * DOMProperty exports lookup objects that can be used like functions:
	 *
	 *   > DOMProperty.isValid['id']
	 *   true
	 *   > DOMProperty.isValid['foobar']
	 *   undefined
	 *
	 * Although this may be confusing, it performs better in general.
	 *
	 * @see http://jsperf.com/key-exists
	 * @see http://jsperf.com/key-missing
	 */
	var DOMProperty = {
	  ID_ATTRIBUTE_NAME: 'data-reactid',
	  ROOT_ATTRIBUTE_NAME: 'data-reactroot',

	  ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,
	  ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040',

	  /**
	   * Map from property "standard name" to an object with info about how to set
	   * the property in the DOM. Each object contains:
	   *
	   * attributeName:
	   *   Used when rendering markup or with `*Attribute()`.
	   * attributeNamespace
	   * propertyName:
	   *   Used on DOM node instances. (This includes properties that mutate due to
	   *   external factors.)
	   * mutationMethod:
	   *   If non-null, used instead of the property or `setAttribute()` after
	   *   initial render.
	   * mustUseProperty:
	   *   Whether the property must be accessed and mutated as an object property.
	   * hasBooleanValue:
	   *   Whether the property should be removed when set to a falsey value.
	   * hasNumericValue:
	   *   Whether the property must be numeric or parse as a numeric and should be
	   *   removed when set to a falsey value.
	   * hasPositiveNumericValue:
	   *   Whether the property must be positive numeric or parse as a positive
	   *   numeric and should be removed when set to a falsey value.
	   * hasOverloadedBooleanValue:
	   *   Whether the property can be used as a flag as well as with a value.
	   *   Removed when strictly equal to false; present without a value when
	   *   strictly equal to true; present with a value otherwise.
	   */
	  properties: {},

	  /**
	   * Mapping from lowercase property names to the properly cased version, used
	   * to warn in the case of missing properties. Available only in __DEV__.
	   *
	   * autofocus is predefined, because adding it to the property whitelist
	   * causes unintended side effects.
	   *
	   * @type {Object}
	   */
	  getPossibleStandardName: process.env.NODE_ENV !== 'production' ? { autofocus: 'autoFocus' } : null,

	  /**
	   * All of the isCustomAttribute() functions that have been injected.
	   */
	  _isCustomAttributeFunctions: [],

	  /**
	   * Checks whether a property name is a custom attribute.
	   * @method
	   */
	  isCustomAttribute: function (attributeName) {
	    for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {
	      var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];
	      if (isCustomAttributeFn(attributeName)) {
	        return true;
	      }
	    }
	    return false;
	  },

	  injection: DOMPropertyInjection
	};

	module.exports = DOMProperty;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 69 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2015-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactDOMComponentFlags = {
	  hasCachedChildNodes: 1 << 0
	};

	module.exports = ReactDOMComponentFlags;

/***/ },
/* 70 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ARIADOMPropertyConfig = __webpack_require__(71);
	var BeforeInputEventPlugin = __webpack_require__(72);
	var ChangeEventPlugin = __webpack_require__(87);
	var DefaultEventPluginOrder = __webpack_require__(105);
	var EnterLeaveEventPlugin = __webpack_require__(106);
	var HTMLDOMPropertyConfig = __webpack_require__(111);
	var ReactComponentBrowserEnvironment = __webpack_require__(112);
	var ReactDOMComponent = __webpack_require__(125);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactDOMEmptyComponent = __webpack_require__(170);
	var ReactDOMTreeTraversal = __webpack_require__(171);
	var ReactDOMTextComponent = __webpack_require__(172);
	var ReactDefaultBatchingStrategy = __webpack_require__(173);
	var ReactEventListener = __webpack_require__(174);
	var ReactInjection = __webpack_require__(177);
	var ReactReconcileTransaction = __webpack_require__(178);
	var SVGDOMPropertyConfig = __webpack_require__(186);
	var SelectEventPlugin = __webpack_require__(187);
	var SimpleEventPlugin = __webpack_require__(188);

	var alreadyInjected = false;

	function inject() {
	  if (alreadyInjected) {
	    // TODO: This is currently true because these injections are shared between
	    // the client and the server package. They should be built independently
	    // and not share any injection state. Then this problem will be solved.
	    return;
	  }
	  alreadyInjected = true;

	  ReactInjection.EventEmitter.injectReactEventListener(ReactEventListener);

	  /**
	   * Inject modules for resolving DOM hierarchy and plugin ordering.
	   */
	  ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);
	  ReactInjection.EventPluginUtils.injectComponentTree(ReactDOMComponentTree);
	  ReactInjection.EventPluginUtils.injectTreeTraversal(ReactDOMTreeTraversal);

	  /**
	   * Some important event plugins included by default (without having to require
	   * them).
	   */
	  ReactInjection.EventPluginHub.injectEventPluginsByName({
	    SimpleEventPlugin: SimpleEventPlugin,
	    EnterLeaveEventPlugin: EnterLeaveEventPlugin,
	    ChangeEventPlugin: ChangeEventPlugin,
	    SelectEventPlugin: SelectEventPlugin,
	    BeforeInputEventPlugin: BeforeInputEventPlugin
	  });

	  ReactInjection.HostComponent.injectGenericComponentClass(ReactDOMComponent);

	  ReactInjection.HostComponent.injectTextComponentClass(ReactDOMTextComponent);

	  ReactInjection.DOMProperty.injectDOMPropertyConfig(ARIADOMPropertyConfig);
	  ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
	  ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);

	  ReactInjection.EmptyComponent.injectEmptyComponentFactory(function (instantiate) {
	    return new ReactDOMEmptyComponent(instantiate);
	  });

	  ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction);
	  ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy);

	  ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
	}

	module.exports = {
	  inject: inject
	};

/***/ },
/* 71 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ARIADOMPropertyConfig = {
	  Properties: {
	    // Global States and Properties
	    'aria-current': 0, // state
	    'aria-details': 0,
	    'aria-disabled': 0, // state
	    'aria-hidden': 0, // state
	    'aria-invalid': 0, // state
	    'aria-keyshortcuts': 0,
	    'aria-label': 0,
	    'aria-roledescription': 0,
	    // Widget Attributes
	    'aria-autocomplete': 0,
	    'aria-checked': 0,
	    'aria-expanded': 0,
	    'aria-haspopup': 0,
	    'aria-level': 0,
	    'aria-modal': 0,
	    'aria-multiline': 0,
	    'aria-multiselectable': 0,
	    'aria-orientation': 0,
	    'aria-placeholder': 0,
	    'aria-pressed': 0,
	    'aria-readonly': 0,
	    'aria-required': 0,
	    'aria-selected': 0,
	    'aria-sort': 0,
	    'aria-valuemax': 0,
	    'aria-valuemin': 0,
	    'aria-valuenow': 0,
	    'aria-valuetext': 0,
	    // Live Region Attributes
	    'aria-atomic': 0,
	    'aria-busy': 0,
	    'aria-live': 0,
	    'aria-relevant': 0,
	    // Drag-and-Drop Attributes
	    'aria-dropeffect': 0,
	    'aria-grabbed': 0,
	    // Relationship Attributes
	    'aria-activedescendant': 0,
	    'aria-colcount': 0,
	    'aria-colindex': 0,
	    'aria-colspan': 0,
	    'aria-controls': 0,
	    'aria-describedby': 0,
	    'aria-errormessage': 0,
	    'aria-flowto': 0,
	    'aria-labelledby': 0,
	    'aria-owns': 0,
	    'aria-posinset': 0,
	    'aria-rowcount': 0,
	    'aria-rowindex': 0,
	    'aria-rowspan': 0,
	    'aria-setsize': 0
	  },
	  DOMAttributeNames: {},
	  DOMPropertyNames: {}
	};

	module.exports = ARIADOMPropertyConfig;

/***/ },
/* 72 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var EventPropagators = __webpack_require__(73);
	var ExecutionEnvironment = __webpack_require__(80);
	var FallbackCompositionState = __webpack_require__(81);
	var SyntheticCompositionEvent = __webpack_require__(84);
	var SyntheticInputEvent = __webpack_require__(86);

	var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
	var START_KEYCODE = 229;

	var canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;

	var documentMode = null;
	if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
	  documentMode = document.documentMode;
	}

	// Webkit offers a very useful `textInput` event that can be used to
	// directly represent `beforeInput`. The IE `textinput` event is not as
	// useful, so we don't use it.
	var canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();

	// In IE9+, we have access to composition events, but the data supplied
	// by the native compositionend event may be incorrect. Japanese ideographic
	// spaces, for instance (\u3000) are not recorded correctly.
	var useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);

	/**
	 * Opera <= 12 includes TextEvent in window, but does not fire
	 * text input events. Rely on keypress instead.
	 */
	function isPresto() {
	  var opera = window.opera;
	  return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;
	}

	var SPACEBAR_CODE = 32;
	var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);

	// Events and their corresponding property names.
	var eventTypes = {
	  beforeInput: {
	    phasedRegistrationNames: {
	      bubbled: 'onBeforeInput',
	      captured: 'onBeforeInputCapture'
	    },
	    dependencies: ['topCompositionEnd', 'topKeyPress', 'topTextInput', 'topPaste']
	  },
	  compositionEnd: {
	    phasedRegistrationNames: {
	      bubbled: 'onCompositionEnd',
	      captured: 'onCompositionEndCapture'
	    },
	    dependencies: ['topBlur', 'topCompositionEnd', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
	  },
	  compositionStart: {
	    phasedRegistrationNames: {
	      bubbled: 'onCompositionStart',
	      captured: 'onCompositionStartCapture'
	    },
	    dependencies: ['topBlur', 'topCompositionStart', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
	  },
	  compositionUpdate: {
	    phasedRegistrationNames: {
	      bubbled: 'onCompositionUpdate',
	      captured: 'onCompositionUpdateCapture'
	    },
	    dependencies: ['topBlur', 'topCompositionUpdate', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
	  }
	};

	// Track whether we've ever handled a keypress on the space key.
	var hasSpaceKeypress = false;

	/**
	 * Return whether a native keypress event is assumed to be a command.
	 * This is required because Firefox fires `keypress` events for key commands
	 * (cut, copy, select-all, etc.) even though no character is inserted.
	 */
	function isKeypressCommand(nativeEvent) {
	  return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
	  // ctrlKey && altKey is equivalent to AltGr, and is not a command.
	  !(nativeEvent.ctrlKey && nativeEvent.altKey);
	}

	/**
	 * Translate native top level events into event types.
	 *
	 * @param {string} topLevelType
	 * @return {object}
	 */
	function getCompositionEventType(topLevelType) {
	  switch (topLevelType) {
	    case 'topCompositionStart':
	      return eventTypes.compositionStart;
	    case 'topCompositionEnd':
	      return eventTypes.compositionEnd;
	    case 'topCompositionUpdate':
	      return eventTypes.compositionUpdate;
	  }
	}

	/**
	 * Does our fallback best-guess model think this event signifies that
	 * composition has begun?
	 *
	 * @param {string} topLevelType
	 * @param {object} nativeEvent
	 * @return {boolean}
	 */
	function isFallbackCompositionStart(topLevelType, nativeEvent) {
	  return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE;
	}

	/**
	 * Does our fallback mode think that this event is the end of composition?
	 *
	 * @param {string} topLevelType
	 * @param {object} nativeEvent
	 * @return {boolean}
	 */
	function isFallbackCompositionEnd(topLevelType, nativeEvent) {
	  switch (topLevelType) {
	    case 'topKeyUp':
	      // Command keys insert or clear IME input.
	      return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
	    case 'topKeyDown':
	      // Expect IME keyCode on each keydown. If we get any other
	      // code we must have exited earlier.
	      return nativeEvent.keyCode !== START_KEYCODE;
	    case 'topKeyPress':
	    case 'topMouseDown':
	    case 'topBlur':
	      // Events are not possible without cancelling IME.
	      return true;
	    default:
	      return false;
	  }
	}

	/**
	 * Google Input Tools provides composition data via a CustomEvent,
	 * with the `data` property populated in the `detail` object. If this
	 * is available on the event object, use it. If not, this is a plain
	 * composition event and we have nothing special to extract.
	 *
	 * @param {object} nativeEvent
	 * @return {?string}
	 */
	function getDataFromCustomEvent(nativeEvent) {
	  var detail = nativeEvent.detail;
	  if (typeof detail === 'object' && 'data' in detail) {
	    return detail.data;
	  }
	  return null;
	}

	// Track the current IME composition fallback object, if any.
	var currentComposition = null;

	/**
	 * @return {?object} A SyntheticCompositionEvent.
	 */
	function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	  var eventType;
	  var fallbackData;

	  if (canUseCompositionEvent) {
	    eventType = getCompositionEventType(topLevelType);
	  } else if (!currentComposition) {
	    if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
	      eventType = eventTypes.compositionStart;
	    }
	  } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
	    eventType = eventTypes.compositionEnd;
	  }

	  if (!eventType) {
	    return null;
	  }

	  if (useFallbackCompositionData) {
	    // The current composition is stored statically and must not be
	    // overwritten while composition continues.
	    if (!currentComposition && eventType === eventTypes.compositionStart) {
	      currentComposition = FallbackCompositionState.getPooled(nativeEventTarget);
	    } else if (eventType === eventTypes.compositionEnd) {
	      if (currentComposition) {
	        fallbackData = currentComposition.getData();
	      }
	    }
	  }

	  var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);

	  if (fallbackData) {
	    // Inject data generated from fallback path into the synthetic event.
	    // This matches the property of native CompositionEventInterface.
	    event.data = fallbackData;
	  } else {
	    var customData = getDataFromCustomEvent(nativeEvent);
	    if (customData !== null) {
	      event.data = customData;
	    }
	  }

	  EventPropagators.accumulateTwoPhaseDispatches(event);
	  return event;
	}

	/**
	 * @param {string} topLevelType Record from `EventConstants`.
	 * @param {object} nativeEvent Native browser event.
	 * @return {?string} The string corresponding to this `beforeInput` event.
	 */
	function getNativeBeforeInputChars(topLevelType, nativeEvent) {
	  switch (topLevelType) {
	    case 'topCompositionEnd':
	      return getDataFromCustomEvent(nativeEvent);
	    case 'topKeyPress':
	      /**
	       * If native `textInput` events are available, our goal is to make
	       * use of them. However, there is a special case: the spacebar key.
	       * In Webkit, preventing default on a spacebar `textInput` event
	       * cancels character insertion, but it *also* causes the browser
	       * to fall back to its default spacebar behavior of scrolling the
	       * page.
	       *
	       * Tracking at:
	       * https://code.google.com/p/chromium/issues/detail?id=355103
	       *
	       * To avoid this issue, use the keypress event as if no `textInput`
	       * event is available.
	       */
	      var which = nativeEvent.which;
	      if (which !== SPACEBAR_CODE) {
	        return null;
	      }

	      hasSpaceKeypress = true;
	      return SPACEBAR_CHAR;

	    case 'topTextInput':
	      // Record the characters to be added to the DOM.
	      var chars = nativeEvent.data;

	      // If it's a spacebar character, assume that we have already handled
	      // it at the keypress level and bail immediately. Android Chrome
	      // doesn't give us keycodes, so we need to blacklist it.
	      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
	        return null;
	      }

	      return chars;

	    default:
	      // For other native event types, do nothing.
	      return null;
	  }
	}

	/**
	 * For browsers that do not provide the `textInput` event, extract the
	 * appropriate string to use for SyntheticInputEvent.
	 *
	 * @param {string} topLevelType Record from `EventConstants`.
	 * @param {object} nativeEvent Native browser event.
	 * @return {?string} The fallback string for this `beforeInput` event.
	 */
	function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
	  // If we are currently composing (IME) and using a fallback to do so,
	  // try to extract the composed characters from the fallback object.
	  // If composition event is available, we extract a string only at
	  // compositionevent, otherwise extract it at fallback events.
	  if (currentComposition) {
	    if (topLevelType === 'topCompositionEnd' || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
	      var chars = currentComposition.getData();
	      FallbackCompositionState.release(currentComposition);
	      currentComposition = null;
	      return chars;
	    }
	    return null;
	  }

	  switch (topLevelType) {
	    case 'topPaste':
	      // If a paste event occurs after a keypress, throw out the input
	      // chars. Paste events should not lead to BeforeInput events.
	      return null;
	    case 'topKeyPress':
	      /**
	       * As of v27, Firefox may fire keypress events even when no character
	       * will be inserted. A few possibilities:
	       *
	       * - `which` is `0`. Arrow keys, Esc key, etc.
	       *
	       * - `which` is the pressed key code, but no char is available.
	       *   Ex: 'AltGr + d` in Polish. There is no modified character for
	       *   this key combination and no character is inserted into the
	       *   document, but FF fires the keypress for char code `100` anyway.
	       *   No `input` event will occur.
	       *
	       * - `which` is the pressed key code, but a command combination is
	       *   being used. Ex: `Cmd+C`. No character is inserted, and no
	       *   `input` event will occur.
	       */
	      if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
	        return String.fromCharCode(nativeEvent.which);
	      }
	      return null;
	    case 'topCompositionEnd':
	      return useFallbackCompositionData ? null : nativeEvent.data;
	    default:
	      return null;
	  }
	}

	/**
	 * Extract a SyntheticInputEvent for `beforeInput`, based on either native
	 * `textInput` or fallback behavior.
	 *
	 * @return {?object} A SyntheticInputEvent.
	 */
	function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	  var chars;

	  if (canUseTextInputEvent) {
	    chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
	  } else {
	    chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
	  }

	  // If no characters are being inserted, no BeforeInput event should
	  // be fired.
	  if (!chars) {
	    return null;
	  }

	  var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);

	  event.data = chars;
	  EventPropagators.accumulateTwoPhaseDispatches(event);
	  return event;
	}

	/**
	 * Create an `onBeforeInput` event to match
	 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
	 *
	 * This event plugin is based on the native `textInput` event
	 * available in Chrome, Safari, Opera, and IE. This event fires after
	 * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
	 *
	 * `beforeInput` is spec'd but not implemented in any browsers, and
	 * the `input` event does not provide any useful information about what has
	 * actually been added, contrary to the spec. Thus, `textInput` is the best
	 * available event to identify the characters that have actually been inserted
	 * into the target node.
	 *
	 * This plugin is also responsible for emitting `composition` events, thus
	 * allowing us to share composition fallback code for both `beforeInput` and
	 * `composition` event types.
	 */
	var BeforeInputEventPlugin = {
	  eventTypes: eventTypes,

	  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	    return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];
	  }
	};

	module.exports = BeforeInputEventPlugin;

/***/ },
/* 73 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var EventPluginHub = __webpack_require__(74);
	var EventPluginUtils = __webpack_require__(76);

	var accumulateInto = __webpack_require__(78);
	var forEachAccumulated = __webpack_require__(79);
	var warning = __webpack_require__(35);

	var getListener = EventPluginHub.getListener;

	/**
	 * Some event types have a notion of different registration names for different
	 * "phases" of propagation. This finds listeners by a given phase.
	 */
	function listenerAtPhase(inst, event, propagationPhase) {
	  var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
	  return getListener(inst, registrationName);
	}

	/**
	 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
	 * here, allows us to not have to bind or create functions for each event.
	 * Mutating the event's members allows us to not have to create a wrapping
	 * "dispatch" object that pairs the event with the listener.
	 */
	function accumulateDirectionalDispatches(inst, phase, event) {
	  if (process.env.NODE_ENV !== 'production') {
	    process.env.NODE_ENV !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;
	  }
	  var listener = listenerAtPhase(inst, event, phase);
	  if (listener) {
	    event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
	    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
	  }
	}

	/**
	 * Collect dispatches (must be entirely collected before dispatching - see unit
	 * tests). Lazily allocate the array to conserve memory.  We must loop through
	 * each event and perform the traversal for each one. We cannot perform a
	 * single traversal for the entire collection of events because each event may
	 * have a different target.
	 */
	function accumulateTwoPhaseDispatchesSingle(event) {
	  if (event && event.dispatchConfig.phasedRegistrationNames) {
	    EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
	  }
	}

	/**
	 * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
	 */
	function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
	  if (event && event.dispatchConfig.phasedRegistrationNames) {
	    var targetInst = event._targetInst;
	    var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;
	    EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
	  }
	}

	/**
	 * Accumulates without regard to direction, does not look for phased
	 * registration names. Same as `accumulateDirectDispatchesSingle` but without
	 * requiring that the `dispatchMarker` be the same as the dispatched ID.
	 */
	function accumulateDispatches(inst, ignoredDirection, event) {
	  if (event && event.dispatchConfig.registrationName) {
	    var registrationName = event.dispatchConfig.registrationName;
	    var listener = getListener(inst, registrationName);
	    if (listener) {
	      event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
	      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
	    }
	  }
	}

	/**
	 * Accumulates dispatches on an `SyntheticEvent`, but only for the
	 * `dispatchMarker`.
	 * @param {SyntheticEvent} event
	 */
	function accumulateDirectDispatchesSingle(event) {
	  if (event && event.dispatchConfig.registrationName) {
	    accumulateDispatches(event._targetInst, null, event);
	  }
	}

	function accumulateTwoPhaseDispatches(events) {
	  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
	}

	function accumulateTwoPhaseDispatchesSkipTarget(events) {
	  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
	}

	function accumulateEnterLeaveDispatches(leave, enter, from, to) {
	  EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
	}

	function accumulateDirectDispatches(events) {
	  forEachAccumulated(events, accumulateDirectDispatchesSingle);
	}

	/**
	 * A small set of propagation patterns, each of which will accept a small amount
	 * of information, and generate a set of "dispatch ready event objects" - which
	 * are sets of events that have already been annotated with a set of dispatched
	 * listener functions/ids. The API is designed this way to discourage these
	 * propagation strategies from actually executing the dispatches, since we
	 * always want to collect the entire set of dispatches before executing event a
	 * single one.
	 *
	 * @constructor EventPropagators
	 */
	var EventPropagators = {
	  accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
	  accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
	  accumulateDirectDispatches: accumulateDirectDispatches,
	  accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches
	};

	module.exports = EventPropagators;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 74 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var EventPluginRegistry = __webpack_require__(75);
	var EventPluginUtils = __webpack_require__(76);
	var ReactErrorUtils = __webpack_require__(77);

	var accumulateInto = __webpack_require__(78);
	var forEachAccumulated = __webpack_require__(79);
	var invariant = __webpack_require__(39);

	/**
	 * Internal store for event listeners
	 */
	var listenerBank = {};

	/**
	 * Internal queue of events that have accumulated their dispatches and are
	 * waiting to have their dispatches executed.
	 */
	var eventQueue = null;

	/**
	 * Dispatches an event and releases it back into the pool, unless persistent.
	 *
	 * @param {?object} event Synthetic event to be dispatched.
	 * @param {boolean} simulated If the event is simulated (changes exn behavior)
	 * @private
	 */
	var executeDispatchesAndRelease = function (event, simulated) {
	  if (event) {
	    EventPluginUtils.executeDispatchesInOrder(event, simulated);

	    if (!event.isPersistent()) {
	      event.constructor.release(event);
	    }
	  }
	};
	var executeDispatchesAndReleaseSimulated = function (e) {
	  return executeDispatchesAndRelease(e, true);
	};
	var executeDispatchesAndReleaseTopLevel = function (e) {
	  return executeDispatchesAndRelease(e, false);
	};

	var getDictionaryKey = function (inst) {
	  // Prevents V8 performance issue:
	  // https://github.com/facebook/react/pull/7232
	  return '.' + inst._rootNodeID;
	};

	function isInteractive(tag) {
	  return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
	}

	function shouldPreventMouseEvent(name, type, props) {
	  switch (name) {
	    case 'onClick':
	    case 'onClickCapture':
	    case 'onDoubleClick':
	    case 'onDoubleClickCapture':
	    case 'onMouseDown':
	    case 'onMouseDownCapture':
	    case 'onMouseMove':
	    case 'onMouseMoveCapture':
	    case 'onMouseUp':
	    case 'onMouseUpCapture':
	      return !!(props.disabled && isInteractive(type));
	    default:
	      return false;
	  }
	}

	/**
	 * This is a unified interface for event plugins to be installed and configured.
	 *
	 * Event plugins can implement the following properties:
	 *
	 *   `extractEvents` {function(string, DOMEventTarget, string, object): *}
	 *     Required. When a top-level event is fired, this method is expected to
	 *     extract synthetic events that will in turn be queued and dispatched.
	 *
	 *   `eventTypes` {object}
	 *     Optional, plugins that fire events must publish a mapping of registration
	 *     names that are used to register listeners. Values of this mapping must
	 *     be objects that contain `registrationName` or `phasedRegistrationNames`.
	 *
	 *   `executeDispatch` {function(object, function, string)}
	 *     Optional, allows plugins to override how an event gets dispatched. By
	 *     default, the listener is simply invoked.
	 *
	 * Each plugin that is injected into `EventsPluginHub` is immediately operable.
	 *
	 * @public
	 */
	var EventPluginHub = {
	  /**
	   * Methods for injecting dependencies.
	   */
	  injection: {
	    /**
	     * @param {array} InjectedEventPluginOrder
	     * @public
	     */
	    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,

	    /**
	     * @param {object} injectedNamesToPlugins Map from names to plugin modules.
	     */
	    injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName
	  },

	  /**
	   * Stores `listener` at `listenerBank[registrationName][key]`. Is idempotent.
	   *
	   * @param {object} inst The instance, which is the source of events.
	   * @param {string} registrationName Name of listener (e.g. `onClick`).
	   * @param {function} listener The callback to store.
	   */
	  putListener: function (inst, registrationName, listener) {
	    !(typeof listener === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : _prodInvariant('94', registrationName, typeof listener) : void 0;

	    var key = getDictionaryKey(inst);
	    var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});
	    bankForRegistrationName[key] = listener;

	    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
	    if (PluginModule && PluginModule.didPutListener) {
	      PluginModule.didPutListener(inst, registrationName, listener);
	    }
	  },

	  /**
	   * @param {object} inst The instance, which is the source of events.
	   * @param {string} registrationName Name of listener (e.g. `onClick`).
	   * @return {?function} The stored callback.
	   */
	  getListener: function (inst, registrationName) {
	    // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
	    // live here; needs to be moved to a better place soon
	    var bankForRegistrationName = listenerBank[registrationName];
	    if (shouldPreventMouseEvent(registrationName, inst._currentElement.type, inst._currentElement.props)) {
	      return null;
	    }
	    var key = getDictionaryKey(inst);
	    return bankForRegistrationName && bankForRegistrationName[key];
	  },

	  /**
	   * Deletes a listener from the registration bank.
	   *
	   * @param {object} inst The instance, which is the source of events.
	   * @param {string} registrationName Name of listener (e.g. `onClick`).
	   */
	  deleteListener: function (inst, registrationName) {
	    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
	    if (PluginModule && PluginModule.willDeleteListener) {
	      PluginModule.willDeleteListener(inst, registrationName);
	    }

	    var bankForRegistrationName = listenerBank[registrationName];
	    // TODO: This should never be null -- when is it?
	    if (bankForRegistrationName) {
	      var key = getDictionaryKey(inst);
	      delete bankForRegistrationName[key];
	    }
	  },

	  /**
	   * Deletes all listeners for the DOM element with the supplied ID.
	   *
	   * @param {object} inst The instance, which is the source of events.
	   */
	  deleteAllListeners: function (inst) {
	    var key = getDictionaryKey(inst);
	    for (var registrationName in listenerBank) {
	      if (!listenerBank.hasOwnProperty(registrationName)) {
	        continue;
	      }

	      if (!listenerBank[registrationName][key]) {
	        continue;
	      }

	      var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
	      if (PluginModule && PluginModule.willDeleteListener) {
	        PluginModule.willDeleteListener(inst, registrationName);
	      }

	      delete listenerBank[registrationName][key];
	    }
	  },

	  /**
	   * Allows registered plugins an opportunity to extract events from top-level
	   * native browser events.
	   *
	   * @return {*} An accumulation of synthetic events.
	   * @internal
	   */
	  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	    var events;
	    var plugins = EventPluginRegistry.plugins;
	    for (var i = 0; i < plugins.length; i++) {
	      // Not every plugin in the ordering may be loaded at runtime.
	      var possiblePlugin = plugins[i];
	      if (possiblePlugin) {
	        var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
	        if (extractedEvents) {
	          events = accumulateInto(events, extractedEvents);
	        }
	      }
	    }
	    return events;
	  },

	  /**
	   * Enqueues a synthetic event that should be dispatched when
	   * `processEventQueue` is invoked.
	   *
	   * @param {*} events An accumulation of synthetic events.
	   * @internal
	   */
	  enqueueEvents: function (events) {
	    if (events) {
	      eventQueue = accumulateInto(eventQueue, events);
	    }
	  },

	  /**
	   * Dispatches all synthetic events on the event queue.
	   *
	   * @internal
	   */
	  processEventQueue: function (simulated) {
	    // Set `eventQueue` to null before processing it so that we can tell if more
	    // events get enqueued while processing.
	    var processingEventQueue = eventQueue;
	    eventQueue = null;
	    if (simulated) {
	      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);
	    } else {
	      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
	    }
	    !!eventQueue ? process.env.NODE_ENV !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : _prodInvariant('95') : void 0;
	    // This would be a good time to rethrow if any of the event handlers threw.
	    ReactErrorUtils.rethrowCaughtError();
	  },

	  /**
	   * These are needed for tests only. Do not use!
	   */
	  __purge: function () {
	    listenerBank = {};
	  },

	  __getListenerBank: function () {
	    return listenerBank;
	  }
	};

	module.exports = EventPluginHub;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 75 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	/**
	 * Injectable ordering of event plugins.
	 */
	var eventPluginOrder = null;

	/**
	 * Injectable mapping from names to event plugin modules.
	 */
	var namesToPlugins = {};

	/**
	 * Recomputes the plugin list using the injected plugins and plugin ordering.
	 *
	 * @private
	 */
	function recomputePluginOrdering() {
	  if (!eventPluginOrder) {
	    // Wait until an `eventPluginOrder` is injected.
	    return;
	  }
	  for (var pluginName in namesToPlugins) {
	    var pluginModule = namesToPlugins[pluginName];
	    var pluginIndex = eventPluginOrder.indexOf(pluginName);
	    !(pluginIndex > -1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0;
	    if (EventPluginRegistry.plugins[pluginIndex]) {
	      continue;
	    }
	    !pluginModule.extractEvents ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0;
	    EventPluginRegistry.plugins[pluginIndex] = pluginModule;
	    var publishedEvents = pluginModule.eventTypes;
	    for (var eventName in publishedEvents) {
	      !publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('98', eventName, pluginName) : void 0;
	    }
	  }
	}

	/**
	 * Publishes an event so that it can be dispatched by the supplied plugin.
	 *
	 * @param {object} dispatchConfig Dispatch configuration for the event.
	 * @param {object} PluginModule Plugin publishing the event.
	 * @return {boolean} True if the event was successfully published.
	 * @private
	 */
	function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
	  !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0;
	  EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;

	  var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
	  if (phasedRegistrationNames) {
	    for (var phaseName in phasedRegistrationNames) {
	      if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
	        var phasedRegistrationName = phasedRegistrationNames[phaseName];
	        publishRegistrationName(phasedRegistrationName, pluginModule, eventName);
	      }
	    }
	    return true;
	  } else if (dispatchConfig.registrationName) {
	    publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName);
	    return true;
	  }
	  return false;
	}

	/**
	 * Publishes a registration name that is used to identify dispatched events and
	 * can be used with `EventPluginHub.putListener` to register listeners.
	 *
	 * @param {string} registrationName Registration name to add.
	 * @param {object} PluginModule Plugin publishing the event.
	 * @private
	 */
	function publishRegistrationName(registrationName, pluginModule, eventName) {
	  !!EventPluginRegistry.registrationNameModules[registrationName] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0;
	  EventPluginRegistry.registrationNameModules[registrationName] = pluginModule;
	  EventPluginRegistry.registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;

	  if (process.env.NODE_ENV !== 'production') {
	    var lowerCasedName = registrationName.toLowerCase();
	    EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;

	    if (registrationName === 'onDoubleClick') {
	      EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;
	    }
	  }
	}

	/**
	 * Registers plugins so that they can extract and dispatch events.
	 *
	 * @see {EventPluginHub}
	 */
	var EventPluginRegistry = {
	  /**
	   * Ordered list of injected plugins.
	   */
	  plugins: [],

	  /**
	   * Mapping from event name to dispatch config
	   */
	  eventNameDispatchConfigs: {},

	  /**
	   * Mapping from registration name to plugin module
	   */
	  registrationNameModules: {},

	  /**
	   * Mapping from registration name to event name
	   */
	  registrationNameDependencies: {},

	  /**
	   * Mapping from lowercase registration names to the properly cased version,
	   * used to warn in the case of missing event handlers. Available
	   * only in __DEV__.
	   * @type {Object}
	   */
	  possibleRegistrationNames: process.env.NODE_ENV !== 'production' ? {} : null,
	  // Trust the developer to only use possibleRegistrationNames in __DEV__

	  /**
	   * Injects an ordering of plugins (by plugin name). This allows the ordering
	   * to be decoupled from injection of the actual plugins so that ordering is
	   * always deterministic regardless of packaging, on-the-fly injection, etc.
	   *
	   * @param {array} InjectedEventPluginOrder
	   * @internal
	   * @see {EventPluginHub.injection.injectEventPluginOrder}
	   */
	  injectEventPluginOrder: function (injectedEventPluginOrder) {
	    !!eventPluginOrder ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : _prodInvariant('101') : void 0;
	    // Clone the ordering so it cannot be dynamically mutated.
	    eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);
	    recomputePluginOrdering();
	  },

	  /**
	   * Injects plugins to be used by `EventPluginHub`. The plugin names must be
	   * in the ordering injected by `injectEventPluginOrder`.
	   *
	   * Plugins can be injected as part of page initialization or on-the-fly.
	   *
	   * @param {object} injectedNamesToPlugins Map from names to plugin modules.
	   * @internal
	   * @see {EventPluginHub.injection.injectEventPluginsByName}
	   */
	  injectEventPluginsByName: function (injectedNamesToPlugins) {
	    var isOrderingDirty = false;
	    for (var pluginName in injectedNamesToPlugins) {
	      if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
	        continue;
	      }
	      var pluginModule = injectedNamesToPlugins[pluginName];
	      if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) {
	        !!namesToPlugins[pluginName] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0;
	        namesToPlugins[pluginName] = pluginModule;
	        isOrderingDirty = true;
	      }
	    }
	    if (isOrderingDirty) {
	      recomputePluginOrdering();
	    }
	  },

	  /**
	   * Looks up the plugin for the supplied event.
	   *
	   * @param {object} event A synthetic event.
	   * @return {?object} The plugin that created the supplied event.
	   * @internal
	   */
	  getPluginModuleForEvent: function (event) {
	    var dispatchConfig = event.dispatchConfig;
	    if (dispatchConfig.registrationName) {
	      return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null;
	    }
	    if (dispatchConfig.phasedRegistrationNames !== undefined) {
	      // pulling phasedRegistrationNames out of dispatchConfig helps Flow see
	      // that it is not undefined.
	      var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;

	      for (var phase in phasedRegistrationNames) {
	        if (!phasedRegistrationNames.hasOwnProperty(phase)) {
	          continue;
	        }
	        var pluginModule = EventPluginRegistry.registrationNameModules[phasedRegistrationNames[phase]];
	        if (pluginModule) {
	          return pluginModule;
	        }
	      }
	    }
	    return null;
	  },

	  /**
	   * Exposed for unit testing.
	   * @private
	   */
	  _resetEventPlugins: function () {
	    eventPluginOrder = null;
	    for (var pluginName in namesToPlugins) {
	      if (namesToPlugins.hasOwnProperty(pluginName)) {
	        delete namesToPlugins[pluginName];
	      }
	    }
	    EventPluginRegistry.plugins.length = 0;

	    var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs;
	    for (var eventName in eventNameDispatchConfigs) {
	      if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {
	        delete eventNameDispatchConfigs[eventName];
	      }
	    }

	    var registrationNameModules = EventPluginRegistry.registrationNameModules;
	    for (var registrationName in registrationNameModules) {
	      if (registrationNameModules.hasOwnProperty(registrationName)) {
	        delete registrationNameModules[registrationName];
	      }
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames;
	      for (var lowerCasedName in possibleRegistrationNames) {
	        if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) {
	          delete possibleRegistrationNames[lowerCasedName];
	        }
	      }
	    }
	  }
	};

	module.exports = EventPluginRegistry;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 76 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var ReactErrorUtils = __webpack_require__(77);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	/**
	 * Injected dependencies:
	 */

	/**
	 * - `ComponentTree`: [required] Module that can convert between React instances
	 *   and actual node references.
	 */
	var ComponentTree;
	var TreeTraversal;
	var injection = {
	  injectComponentTree: function (Injected) {
	    ComponentTree = Injected;
	    if (process.env.NODE_ENV !== 'production') {
	      process.env.NODE_ENV !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;
	    }
	  },
	  injectTreeTraversal: function (Injected) {
	    TreeTraversal = Injected;
	    if (process.env.NODE_ENV !== 'production') {
	      process.env.NODE_ENV !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;
	    }
	  }
	};

	function isEndish(topLevelType) {
	  return topLevelType === 'topMouseUp' || topLevelType === 'topTouchEnd' || topLevelType === 'topTouchCancel';
	}

	function isMoveish(topLevelType) {
	  return topLevelType === 'topMouseMove' || topLevelType === 'topTouchMove';
	}
	function isStartish(topLevelType) {
	  return topLevelType === 'topMouseDown' || topLevelType === 'topTouchStart';
	}

	var validateEventDispatches;
	if (process.env.NODE_ENV !== 'production') {
	  validateEventDispatches = function (event) {
	    var dispatchListeners = event._dispatchListeners;
	    var dispatchInstances = event._dispatchInstances;

	    var listenersIsArr = Array.isArray(dispatchListeners);
	    var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;

	    var instancesIsArr = Array.isArray(dispatchInstances);
	    var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;

	    process.env.NODE_ENV !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;
	  };
	}

	/**
	 * Dispatch the event to the listener.
	 * @param {SyntheticEvent} event SyntheticEvent to handle
	 * @param {boolean} simulated If the event is simulated (changes exn behavior)
	 * @param {function} listener Application-level callback
	 * @param {*} inst Internal component instance
	 */
	function executeDispatch(event, simulated, listener, inst) {
	  var type = event.type || 'unknown-event';
	  event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);
	  if (simulated) {
	    ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);
	  } else {
	    ReactErrorUtils.invokeGuardedCallback(type, listener, event);
	  }
	  event.currentTarget = null;
	}

	/**
	 * Standard/simple iteration through an event's collected dispatches.
	 */
	function executeDispatchesInOrder(event, simulated) {
	  var dispatchListeners = event._dispatchListeners;
	  var dispatchInstances = event._dispatchInstances;
	  if (process.env.NODE_ENV !== 'production') {
	    validateEventDispatches(event);
	  }
	  if (Array.isArray(dispatchListeners)) {
	    for (var i = 0; i < dispatchListeners.length; i++) {
	      if (event.isPropagationStopped()) {
	        break;
	      }
	      // Listeners and Instances are two parallel arrays that are always in sync.
	      executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);
	    }
	  } else if (dispatchListeners) {
	    executeDispatch(event, simulated, dispatchListeners, dispatchInstances);
	  }
	  event._dispatchListeners = null;
	  event._dispatchInstances = null;
	}

	/**
	 * Standard/simple iteration through an event's collected dispatches, but stops
	 * at the first dispatch execution returning true, and returns that id.
	 *
	 * @return {?string} id of the first dispatch execution who's listener returns
	 * true, or null if no listener returned true.
	 */
	function executeDispatchesInOrderStopAtTrueImpl(event) {
	  var dispatchListeners = event._dispatchListeners;
	  var dispatchInstances = event._dispatchInstances;
	  if (process.env.NODE_ENV !== 'production') {
	    validateEventDispatches(event);
	  }
	  if (Array.isArray(dispatchListeners)) {
	    for (var i = 0; i < dispatchListeners.length; i++) {
	      if (event.isPropagationStopped()) {
	        break;
	      }
	      // Listeners and Instances are two parallel arrays that are always in sync.
	      if (dispatchListeners[i](event, dispatchInstances[i])) {
	        return dispatchInstances[i];
	      }
	    }
	  } else if (dispatchListeners) {
	    if (dispatchListeners(event, dispatchInstances)) {
	      return dispatchInstances;
	    }
	  }
	  return null;
	}

	/**
	 * @see executeDispatchesInOrderStopAtTrueImpl
	 */
	function executeDispatchesInOrderStopAtTrue(event) {
	  var ret = executeDispatchesInOrderStopAtTrueImpl(event);
	  event._dispatchInstances = null;
	  event._dispatchListeners = null;
	  return ret;
	}

	/**
	 * Execution of a "direct" dispatch - there must be at most one dispatch
	 * accumulated on the event or it is considered an error. It doesn't really make
	 * sense for an event with multiple dispatches (bubbled) to keep track of the
	 * return values at each dispatch execution, but it does tend to make sense when
	 * dealing with "direct" dispatches.
	 *
	 * @return {*} The return value of executing the single dispatch.
	 */
	function executeDirectDispatch(event) {
	  if (process.env.NODE_ENV !== 'production') {
	    validateEventDispatches(event);
	  }
	  var dispatchListener = event._dispatchListeners;
	  var dispatchInstance = event._dispatchInstances;
	  !!Array.isArray(dispatchListener) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0;
	  event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;
	  var res = dispatchListener ? dispatchListener(event) : null;
	  event.currentTarget = null;
	  event._dispatchListeners = null;
	  event._dispatchInstances = null;
	  return res;
	}

	/**
	 * @param {SyntheticEvent} event
	 * @return {boolean} True iff number of dispatches accumulated is greater than 0.
	 */
	function hasDispatches(event) {
	  return !!event._dispatchListeners;
	}

	/**
	 * General utilities that are useful in creating custom Event Plugins.
	 */
	var EventPluginUtils = {
	  isEndish: isEndish,
	  isMoveish: isMoveish,
	  isStartish: isStartish,

	  executeDirectDispatch: executeDirectDispatch,
	  executeDispatchesInOrder: executeDispatchesInOrder,
	  executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
	  hasDispatches: hasDispatches,

	  getInstanceFromNode: function (node) {
	    return ComponentTree.getInstanceFromNode(node);
	  },
	  getNodeFromInstance: function (node) {
	    return ComponentTree.getNodeFromInstance(node);
	  },
	  isAncestor: function (a, b) {
	    return TreeTraversal.isAncestor(a, b);
	  },
	  getLowestCommonAncestor: function (a, b) {
	    return TreeTraversal.getLowestCommonAncestor(a, b);
	  },
	  getParentInstance: function (inst) {
	    return TreeTraversal.getParentInstance(inst);
	  },
	  traverseTwoPhase: function (target, fn, arg) {
	    return TreeTraversal.traverseTwoPhase(target, fn, arg);
	  },
	  traverseEnterLeave: function (from, to, fn, argFrom, argTo) {
	    return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);
	  },

	  injection: injection
	};

	module.exports = EventPluginUtils;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 77 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var caughtError = null;

	/**
	 * Call a function while guarding against errors that happens within it.
	 *
	 * @param {String} name of the guard to use for logging or debugging
	 * @param {Function} func The function to invoke
	 * @param {*} a First argument
	 * @param {*} b Second argument
	 */
	function invokeGuardedCallback(name, func, a) {
	  try {
	    func(a);
	  } catch (x) {
	    if (caughtError === null) {
	      caughtError = x;
	    }
	  }
	}

	var ReactErrorUtils = {
	  invokeGuardedCallback: invokeGuardedCallback,

	  /**
	   * Invoked by ReactTestUtils.Simulate so that any errors thrown by the event
	   * handler are sure to be rethrown by rethrowCaughtError.
	   */
	  invokeGuardedCallbackWithCatch: invokeGuardedCallback,

	  /**
	   * During execution of guarded functions we will capture the first error which
	   * we will rethrow to be handled by the top level error handler.
	   */
	  rethrowCaughtError: function () {
	    if (caughtError) {
	      var error = caughtError;
	      caughtError = null;
	      throw error;
	    }
	  }
	};

	if (process.env.NODE_ENV !== 'production') {
	  /**
	   * To help development we can get better devtools integration by simulating a
	   * real browser event.
	   */
	  if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
	    var fakeNode = document.createElement('react');
	    ReactErrorUtils.invokeGuardedCallback = function (name, func, a) {
	      var boundFunc = function () {
	        func(a);
	      };
	      var evtType = 'react-' + name;
	      fakeNode.addEventListener(evtType, boundFunc, false);
	      var evt = document.createEvent('Event');
	      evt.initEvent(evtType, false, false);
	      fakeNode.dispatchEvent(evt);
	      fakeNode.removeEventListener(evtType, boundFunc, false);
	    };
	  }
	}

	module.exports = ReactErrorUtils;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 78 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	/**
	 * Accumulates items that must not be null or undefined into the first one. This
	 * is used to conserve memory by avoiding array allocations, and thus sacrifices
	 * API cleanness. Since `current` can be null before being passed in and not
	 * null after this function, make sure to assign it back to `current`:
	 *
	 * `a = accumulateInto(a, b);`
	 *
	 * This API should be sparingly used. Try `accumulate` for something cleaner.
	 *
	 * @return {*|array<*>} An accumulation of items.
	 */

	function accumulateInto(current, next) {
	  !(next != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : _prodInvariant('30') : void 0;

	  if (current == null) {
	    return next;
	  }

	  // Both are not empty. Warning: Never call x.concat(y) when you are not
	  // certain that x is an Array (x could be a string with concat method).
	  if (Array.isArray(current)) {
	    if (Array.isArray(next)) {
	      current.push.apply(current, next);
	      return current;
	    }
	    current.push(next);
	    return current;
	  }

	  if (Array.isArray(next)) {
	    // A bit too dangerous to mutate `next`.
	    return [current].concat(next);
	  }

	  return [current, next];
	}

	module.exports = accumulateInto;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 79 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	/**
	 * @param {array} arr an "accumulation" of items which is either an Array or
	 * a single item. Useful when paired with the `accumulate` module. This is a
	 * simple utility that allows us to reason about a collection of items, but
	 * handling the case when there is exactly one item (and we do not need to
	 * allocate an array).
	 */

	function forEachAccumulated(arr, cb, scope) {
	  if (Array.isArray(arr)) {
	    arr.forEach(cb, scope);
	  } else if (arr) {
	    cb.call(scope, arr);
	  }
	}

	module.exports = forEachAccumulated;

/***/ },
/* 80 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);

	/**
	 * Simple, lightweight module assisting with the detection and context of
	 * Worker. Helps avoid circular dependencies and allows code to reason about
	 * whether or not they are in a Worker, even if they never include the main
	 * `ReactWorker` dependency.
	 */
	var ExecutionEnvironment = {

	  canUseDOM: canUseDOM,

	  canUseWorkers: typeof Worker !== 'undefined',

	  canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),

	  canUseViewport: canUseDOM && !!window.screen,

	  isInWorker: !canUseDOM // For now, this is true - might change in the future.

	};

	module.exports = ExecutionEnvironment;

/***/ },
/* 81 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var PooledClass = __webpack_require__(82);

	var getTextContentAccessor = __webpack_require__(83);

	/**
	 * This helper class stores information about text content of a target node,
	 * allowing comparison of content before and after a given event.
	 *
	 * Identify the node where selection currently begins, then observe
	 * both its text content and its current position in the DOM. Since the
	 * browser may natively replace the target node during composition, we can
	 * use its position to find its replacement.
	 *
	 * @param {DOMEventTarget} root
	 */
	function FallbackCompositionState(root) {
	  this._root = root;
	  this._startText = this.getText();
	  this._fallbackText = null;
	}

	_assign(FallbackCompositionState.prototype, {
	  destructor: function () {
	    this._root = null;
	    this._startText = null;
	    this._fallbackText = null;
	  },

	  /**
	   * Get current text of input.
	   *
	   * @return {string}
	   */
	  getText: function () {
	    if ('value' in this._root) {
	      return this._root.value;
	    }
	    return this._root[getTextContentAccessor()];
	  },

	  /**
	   * Determine the differing substring between the initially stored
	   * text content and the current content.
	   *
	   * @return {string}
	   */
	  getData: function () {
	    if (this._fallbackText) {
	      return this._fallbackText;
	    }

	    var start;
	    var startValue = this._startText;
	    var startLength = startValue.length;
	    var end;
	    var endValue = this.getText();
	    var endLength = endValue.length;

	    for (start = 0; start < startLength; start++) {
	      if (startValue[start] !== endValue[start]) {
	        break;
	      }
	    }

	    var minEnd = startLength - start;
	    for (end = 1; end <= minEnd; end++) {
	      if (startValue[startLength - end] !== endValue[endLength - end]) {
	        break;
	      }
	    }

	    var sliceTail = end > 1 ? 1 - end : undefined;
	    this._fallbackText = endValue.slice(start, sliceTail);
	    return this._fallbackText;
	  }
	});

	PooledClass.addPoolingTo(FallbackCompositionState);

	module.exports = FallbackCompositionState;

/***/ },
/* 82 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	/**
	 * Static poolers. Several custom versions for each potential number of
	 * arguments. A completely generic pooler is easy to implement, but would
	 * require accessing the `arguments` object. In each of these, `this` refers to
	 * the Class itself, not an instance. If any others are needed, simply add them
	 * here, or in their own files.
	 */
	var oneArgumentPooler = function (copyFieldsFrom) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, copyFieldsFrom);
	    return instance;
	  } else {
	    return new Klass(copyFieldsFrom);
	  }
	};

	var twoArgumentPooler = function (a1, a2) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, a1, a2);
	    return instance;
	  } else {
	    return new Klass(a1, a2);
	  }
	};

	var threeArgumentPooler = function (a1, a2, a3) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, a1, a2, a3);
	    return instance;
	  } else {
	    return new Klass(a1, a2, a3);
	  }
	};

	var fourArgumentPooler = function (a1, a2, a3, a4) {
	  var Klass = this;
	  if (Klass.instancePool.length) {
	    var instance = Klass.instancePool.pop();
	    Klass.call(instance, a1, a2, a3, a4);
	    return instance;
	  } else {
	    return new Klass(a1, a2, a3, a4);
	  }
	};

	var standardReleaser = function (instance) {
	  var Klass = this;
	  !(instance instanceof Klass) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0;
	  instance.destructor();
	  if (Klass.instancePool.length < Klass.poolSize) {
	    Klass.instancePool.push(instance);
	  }
	};

	var DEFAULT_POOL_SIZE = 10;
	var DEFAULT_POOLER = oneArgumentPooler;

	/**
	 * Augments `CopyConstructor` to be a poolable class, augmenting only the class
	 * itself (statically) not adding any prototypical fields. Any CopyConstructor
	 * you give this may have a `poolSize` property, and will look for a
	 * prototypical `destructor` on instances.
	 *
	 * @param {Function} CopyConstructor Constructor that can be used to reset.
	 * @param {Function} pooler Customizable pooler.
	 */
	var addPoolingTo = function (CopyConstructor, pooler) {
	  // Casting as any so that flow ignores the actual implementation and trusts
	  // it to match the type we declared
	  var NewKlass = CopyConstructor;
	  NewKlass.instancePool = [];
	  NewKlass.getPooled = pooler || DEFAULT_POOLER;
	  if (!NewKlass.poolSize) {
	    NewKlass.poolSize = DEFAULT_POOL_SIZE;
	  }
	  NewKlass.release = standardReleaser;
	  return NewKlass;
	};

	var PooledClass = {
	  addPoolingTo: addPoolingTo,
	  oneArgumentPooler: oneArgumentPooler,
	  twoArgumentPooler: twoArgumentPooler,
	  threeArgumentPooler: threeArgumentPooler,
	  fourArgumentPooler: fourArgumentPooler
	};

	module.exports = PooledClass;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 83 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ExecutionEnvironment = __webpack_require__(80);

	var contentKey = null;

	/**
	 * Gets the key used to access text content on a DOM node.
	 *
	 * @return {?string} Key used to access text content.
	 * @internal
	 */
	function getTextContentAccessor() {
	  if (!contentKey && ExecutionEnvironment.canUseDOM) {
	    // Prefer textContent to innerText because many browsers support both but
	    // SVG <text> elements don't support innerText even when <div> does.
	    contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
	  }
	  return contentKey;
	}

	module.exports = getTextContentAccessor;

/***/ },
/* 84 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticEvent = __webpack_require__(85);

	/**
	 * @interface Event
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
	 */
	var CompositionEventInterface = {
	  data: null
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticEvent.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);

	module.exports = SyntheticCompositionEvent;

/***/ },
/* 85 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var PooledClass = __webpack_require__(82);

	var emptyFunction = __webpack_require__(36);
	var warning = __webpack_require__(35);

	var didWarnForAddedNewProperty = false;
	var isProxySupported = typeof Proxy === 'function';

	var shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];

	/**
	 * @interface Event
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/
	 */
	var EventInterface = {
	  type: null,
	  target: null,
	  // currentTarget is set when dispatching; no use in copying it here
	  currentTarget: emptyFunction.thatReturnsNull,
	  eventPhase: null,
	  bubbles: null,
	  cancelable: null,
	  timeStamp: function (event) {
	    return event.timeStamp || Date.now();
	  },
	  defaultPrevented: null,
	  isTrusted: null
	};

	/**
	 * Synthetic events are dispatched by event plugins, typically in response to a
	 * top-level event delegation handler.
	 *
	 * These systems should generally use pooling to reduce the frequency of garbage
	 * collection. The system should check `isPersistent` to determine whether the
	 * event should be released into the pool after being dispatched. Users that
	 * need a persisted event should invoke `persist`.
	 *
	 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
	 * normalizing browser quirks. Subclasses do not necessarily have to implement a
	 * DOM interface; custom application-specific events can also subclass this.
	 *
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {*} targetInst Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @param {DOMEventTarget} nativeEventTarget Target node.
	 */
	function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
	  if (process.env.NODE_ENV !== 'production') {
	    // these have a getter/setter for warnings
	    delete this.nativeEvent;
	    delete this.preventDefault;
	    delete this.stopPropagation;
	  }

	  this.dispatchConfig = dispatchConfig;
	  this._targetInst = targetInst;
	  this.nativeEvent = nativeEvent;

	  var Interface = this.constructor.Interface;
	  for (var propName in Interface) {
	    if (!Interface.hasOwnProperty(propName)) {
	      continue;
	    }
	    if (process.env.NODE_ENV !== 'production') {
	      delete this[propName]; // this has a getter/setter for warnings
	    }
	    var normalize = Interface[propName];
	    if (normalize) {
	      this[propName] = normalize(nativeEvent);
	    } else {
	      if (propName === 'target') {
	        this.target = nativeEventTarget;
	      } else {
	        this[propName] = nativeEvent[propName];
	      }
	    }
	  }

	  var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
	  if (defaultPrevented) {
	    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;
	  } else {
	    this.isDefaultPrevented = emptyFunction.thatReturnsFalse;
	  }
	  this.isPropagationStopped = emptyFunction.thatReturnsFalse;
	  return this;
	}

	_assign(SyntheticEvent.prototype, {
	  preventDefault: function () {
	    this.defaultPrevented = true;
	    var event = this.nativeEvent;
	    if (!event) {
	      return;
	    }

	    if (event.preventDefault) {
	      event.preventDefault();
	      // eslint-disable-next-line valid-typeof
	    } else if (typeof event.returnValue !== 'unknown') {
	      event.returnValue = false;
	    }
	    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;
	  },

	  stopPropagation: function () {
	    var event = this.nativeEvent;
	    if (!event) {
	      return;
	    }

	    if (event.stopPropagation) {
	      event.stopPropagation();
	      // eslint-disable-next-line valid-typeof
	    } else if (typeof event.cancelBubble !== 'unknown') {
	      // The ChangeEventPlugin registers a "propertychange" event for
	      // IE. This event does not support bubbling or cancelling, and
	      // any references to cancelBubble throw "Member not found".  A
	      // typeof check of "unknown" circumvents this issue (and is also
	      // IE specific).
	      event.cancelBubble = true;
	    }

	    this.isPropagationStopped = emptyFunction.thatReturnsTrue;
	  },

	  /**
	   * We release all dispatched `SyntheticEvent`s after each event loop, adding
	   * them back into the pool. This allows a way to hold onto a reference that
	   * won't be added back into the pool.
	   */
	  persist: function () {
	    this.isPersistent = emptyFunction.thatReturnsTrue;
	  },

	  /**
	   * Checks if this event should be released back into the pool.
	   *
	   * @return {boolean} True if this should not be released, false otherwise.
	   */
	  isPersistent: emptyFunction.thatReturnsFalse,

	  /**
	   * `PooledClass` looks for `destructor` on each instance it releases.
	   */
	  destructor: function () {
	    var Interface = this.constructor.Interface;
	    for (var propName in Interface) {
	      if (process.env.NODE_ENV !== 'production') {
	        Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));
	      } else {
	        this[propName] = null;
	      }
	    }
	    for (var i = 0; i < shouldBeReleasedProperties.length; i++) {
	      this[shouldBeReleasedProperties[i]] = null;
	    }
	    if (process.env.NODE_ENV !== 'production') {
	      Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
	      Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction));
	      Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction));
	    }
	  }
	});

	SyntheticEvent.Interface = EventInterface;

	/**
	 * Helper to reduce boilerplate when creating subclasses.
	 *
	 * @param {function} Class
	 * @param {?object} Interface
	 */
	SyntheticEvent.augmentClass = function (Class, Interface) {
	  var Super = this;

	  var E = function () {};
	  E.prototype = Super.prototype;
	  var prototype = new E();

	  _assign(prototype, Class.prototype);
	  Class.prototype = prototype;
	  Class.prototype.constructor = Class;

	  Class.Interface = _assign({}, Super.Interface, Interface);
	  Class.augmentClass = Super.augmentClass;

	  PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);
	};

	/** Proxying after everything set on SyntheticEvent
	  * to resolve Proxy issue on some WebKit browsers
	  * in which some Event properties are set to undefined (GH#10010)
	  */
	if (process.env.NODE_ENV !== 'production') {
	  if (isProxySupported) {
	    /*eslint-disable no-func-assign */
	    SyntheticEvent = new Proxy(SyntheticEvent, {
	      construct: function (target, args) {
	        return this.apply(target, Object.create(target.prototype), args);
	      },
	      apply: function (constructor, that, args) {
	        return new Proxy(constructor.apply(that, args), {
	          set: function (target, prop, value) {
	            if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {
	              process.env.NODE_ENV !== 'production' ? warning(didWarnForAddedNewProperty || target.isPersistent(), "This synthetic event is reused for performance reasons. If you're " + "seeing this, you're adding a new property in the synthetic event object. " + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;
	              didWarnForAddedNewProperty = true;
	            }
	            target[prop] = value;
	            return true;
	          }
	        });
	      }
	    });
	    /*eslint-enable no-func-assign */
	  }
	}

	PooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);

	module.exports = SyntheticEvent;

	/**
	  * Helper to nullify syntheticEvent instance properties when destructing
	  *
	  * @param {object} SyntheticEvent
	  * @param {String} propName
	  * @return {object} defineProperty object
	  */
	function getPooledWarningPropertyDefinition(propName, getVal) {
	  var isFunction = typeof getVal === 'function';
	  return {
	    configurable: true,
	    set: set,
	    get: get
	  };

	  function set(val) {
	    var action = isFunction ? 'setting the method' : 'setting the property';
	    warn(action, 'This is effectively a no-op');
	    return val;
	  }

	  function get() {
	    var action = isFunction ? 'accessing the method' : 'accessing the property';
	    var result = isFunction ? 'This is a no-op function' : 'This is set to null';
	    warn(action, result);
	    return getVal;
	  }

	  function warn(action, result) {
	    var warningCondition = false;
	    process.env.NODE_ENV !== 'production' ? warning(warningCondition, "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;
	  }
	}
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 86 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticEvent = __webpack_require__(85);

	/**
	 * @interface Event
	 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
	 *      /#events-inputevents
	 */
	var InputEventInterface = {
	  data: null
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface);

	module.exports = SyntheticInputEvent;

/***/ },
/* 87 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var EventPluginHub = __webpack_require__(74);
	var EventPropagators = __webpack_require__(73);
	var ExecutionEnvironment = __webpack_require__(80);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactUpdates = __webpack_require__(88);
	var SyntheticEvent = __webpack_require__(85);

	var inputValueTracking = __webpack_require__(101);
	var getEventTarget = __webpack_require__(102);
	var isEventSupported = __webpack_require__(103);
	var isTextInputElement = __webpack_require__(104);

	var eventTypes = {
	  change: {
	    phasedRegistrationNames: {
	      bubbled: 'onChange',
	      captured: 'onChangeCapture'
	    },
	    dependencies: ['topBlur', 'topChange', 'topClick', 'topFocus', 'topInput', 'topKeyDown', 'topKeyUp', 'topSelectionChange']
	  }
	};

	function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
	  var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, target);
	  event.type = 'change';
	  EventPropagators.accumulateTwoPhaseDispatches(event);
	  return event;
	}
	/**
	 * For IE shims
	 */
	var activeElement = null;
	var activeElementInst = null;

	/**
	 * SECTION: handle `change` event
	 */
	function shouldUseChangeEvent(elem) {
	  var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
	  return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
	}

	var doesChangeEventBubble = false;
	if (ExecutionEnvironment.canUseDOM) {
	  // See `handleChange` comment below
	  doesChangeEventBubble = isEventSupported('change') && (!document.documentMode || document.documentMode > 8);
	}

	function manualDispatchChangeEvent(nativeEvent) {
	  var event = createAndAccumulateChangeEvent(activeElementInst, nativeEvent, getEventTarget(nativeEvent));

	  // If change and propertychange bubbled, we'd just bind to it like all the
	  // other events and have it go through ReactBrowserEventEmitter. Since it
	  // doesn't, we manually listen for the events and so we have to enqueue and
	  // process the abstract event manually.
	  //
	  // Batching is necessary here in order to ensure that all event handlers run
	  // before the next rerender (including event handlers attached to ancestor
	  // elements instead of directly on the input). Without this, controlled
	  // components don't work properly in conjunction with event bubbling because
	  // the component is rerendered and the value reverted before all the event
	  // handlers can run. See https://github.com/facebook/react/issues/708.
	  ReactUpdates.batchedUpdates(runEventInBatch, event);
	}

	function runEventInBatch(event) {
	  EventPluginHub.enqueueEvents(event);
	  EventPluginHub.processEventQueue(false);
	}

	function startWatchingForChangeEventIE8(target, targetInst) {
	  activeElement = target;
	  activeElementInst = targetInst;
	  activeElement.attachEvent('onchange', manualDispatchChangeEvent);
	}

	function stopWatchingForChangeEventIE8() {
	  if (!activeElement) {
	    return;
	  }
	  activeElement.detachEvent('onchange', manualDispatchChangeEvent);
	  activeElement = null;
	  activeElementInst = null;
	}

	function getInstIfValueChanged(targetInst, nativeEvent) {
	  var updated = inputValueTracking.updateValueIfChanged(targetInst);
	  var simulated = nativeEvent.simulated === true && ChangeEventPlugin._allowSimulatedPassThrough;

	  if (updated || simulated) {
	    return targetInst;
	  }
	}

	function getTargetInstForChangeEvent(topLevelType, targetInst) {
	  if (topLevelType === 'topChange') {
	    return targetInst;
	  }
	}

	function handleEventsForChangeEventIE8(topLevelType, target, targetInst) {
	  if (topLevelType === 'topFocus') {
	    // stopWatching() should be a noop here but we call it just in case we
	    // missed a blur event somehow.
	    stopWatchingForChangeEventIE8();
	    startWatchingForChangeEventIE8(target, targetInst);
	  } else if (topLevelType === 'topBlur') {
	    stopWatchingForChangeEventIE8();
	  }
	}

	/**
	 * SECTION: handle `input` event
	 */
	var isInputEventSupported = false;
	if (ExecutionEnvironment.canUseDOM) {
	  // IE9 claims to support the input event but fails to trigger it when
	  // deleting text, so we ignore its input events.

	  isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9);
	}

	/**
	 * (For IE <=9) Starts tracking propertychange events on the passed-in element
	 * and override the value property so that we can distinguish user events from
	 * value changes in JS.
	 */
	function startWatchingForValueChange(target, targetInst) {
	  activeElement = target;
	  activeElementInst = targetInst;
	  activeElement.attachEvent('onpropertychange', handlePropertyChange);
	}

	/**
	 * (For IE <=9) Removes the event listeners from the currently-tracked element,
	 * if any exists.
	 */
	function stopWatchingForValueChange() {
	  if (!activeElement) {
	    return;
	  }
	  activeElement.detachEvent('onpropertychange', handlePropertyChange);

	  activeElement = null;
	  activeElementInst = null;
	}

	/**
	 * (For IE <=9) Handles a propertychange event, sending a `change` event if
	 * the value of the active element has changed.
	 */
	function handlePropertyChange(nativeEvent) {
	  if (nativeEvent.propertyName !== 'value') {
	    return;
	  }
	  if (getInstIfValueChanged(activeElementInst, nativeEvent)) {
	    manualDispatchChangeEvent(nativeEvent);
	  }
	}

	function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) {
	  if (topLevelType === 'topFocus') {
	    // In IE8, we can capture almost all .value changes by adding a
	    // propertychange handler and looking for events with propertyName
	    // equal to 'value'
	    // In IE9, propertychange fires for most input events but is buggy and
	    // doesn't fire when text is deleted, but conveniently, selectionchange
	    // appears to fire in all of the remaining cases so we catch those and
	    // forward the event if the value has changed
	    // In either case, we don't want to call the event handler if the value
	    // is changed from JS so we redefine a setter for `.value` that updates
	    // our activeElementValue variable, allowing us to ignore those changes
	    //
	    // stopWatching() should be a noop here but we call it just in case we
	    // missed a blur event somehow.
	    stopWatchingForValueChange();
	    startWatchingForValueChange(target, targetInst);
	  } else if (topLevelType === 'topBlur') {
	    stopWatchingForValueChange();
	  }
	}

	// For IE8 and IE9.
	function getTargetInstForInputEventPolyfill(topLevelType, targetInst, nativeEvent) {
	  if (topLevelType === 'topSelectionChange' || topLevelType === 'topKeyUp' || topLevelType === 'topKeyDown') {
	    // On the selectionchange event, the target is just document which isn't
	    // helpful for us so just check activeElement instead.
	    //
	    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
	    // propertychange on the first input event after setting `value` from a
	    // script and fires only keydown, keypress, keyup. Catching keyup usually
	    // gets it and catching keydown lets us fire an event for the first
	    // keystroke if user does a key repeat (it'll be a little delayed: right
	    // before the second keystroke). Other input methods (e.g., paste) seem to
	    // fire selectionchange normally.
	    return getInstIfValueChanged(activeElementInst, nativeEvent);
	  }
	}

	/**
	 * SECTION: handle `click` event
	 */
	function shouldUseClickEvent(elem) {
	  // Use the `click` event to detect changes to checkbox and radio inputs.
	  // This approach works across all browsers, whereas `change` does not fire
	  // until `blur` in IE8.
	  var nodeName = elem.nodeName;
	  return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
	}

	function getTargetInstForClickEvent(topLevelType, targetInst, nativeEvent) {
	  if (topLevelType === 'topClick') {
	    return getInstIfValueChanged(targetInst, nativeEvent);
	  }
	}

	function getTargetInstForInputOrChangeEvent(topLevelType, targetInst, nativeEvent) {
	  if (topLevelType === 'topInput' || topLevelType === 'topChange') {
	    return getInstIfValueChanged(targetInst, nativeEvent);
	  }
	}

	function handleControlledInputBlur(inst, node) {
	  // TODO: In IE, inst is occasionally null. Why?
	  if (inst == null) {
	    return;
	  }

	  // Fiber and ReactDOM keep wrapper state in separate places
	  var state = inst._wrapperState || node._wrapperState;

	  if (!state || !state.controlled || node.type !== 'number') {
	    return;
	  }

	  // If controlled, assign the value attribute to the current value on blur
	  var value = '' + node.value;
	  if (node.getAttribute('value') !== value) {
	    node.setAttribute('value', value);
	  }
	}

	/**
	 * This plugin creates an `onChange` event that normalizes change events
	 * across form elements. This event fires at a time when it's possible to
	 * change the element's value without seeing a flicker.
	 *
	 * Supported elements are:
	 * - input (see `isTextInputElement`)
	 * - textarea
	 * - select
	 */
	var ChangeEventPlugin = {
	  eventTypes: eventTypes,

	  _allowSimulatedPassThrough: true,
	  _isInputEventSupported: isInputEventSupported,

	  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;

	    var getTargetInstFunc, handleEventFunc;
	    if (shouldUseChangeEvent(targetNode)) {
	      if (doesChangeEventBubble) {
	        getTargetInstFunc = getTargetInstForChangeEvent;
	      } else {
	        handleEventFunc = handleEventsForChangeEventIE8;
	      }
	    } else if (isTextInputElement(targetNode)) {
	      if (isInputEventSupported) {
	        getTargetInstFunc = getTargetInstForInputOrChangeEvent;
	      } else {
	        getTargetInstFunc = getTargetInstForInputEventPolyfill;
	        handleEventFunc = handleEventsForInputEventPolyfill;
	      }
	    } else if (shouldUseClickEvent(targetNode)) {
	      getTargetInstFunc = getTargetInstForClickEvent;
	    }

	    if (getTargetInstFunc) {
	      var inst = getTargetInstFunc(topLevelType, targetInst, nativeEvent);
	      if (inst) {
	        var event = createAndAccumulateChangeEvent(inst, nativeEvent, nativeEventTarget);
	        return event;
	      }
	    }

	    if (handleEventFunc) {
	      handleEventFunc(topLevelType, targetNode, targetInst);
	    }

	    // When blurring, set the value attribute for number inputs
	    if (topLevelType === 'topBlur') {
	      handleControlledInputBlur(targetInst, targetNode);
	    }
	  }
	};

	module.exports = ChangeEventPlugin;

/***/ },
/* 88 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67),
	    _assign = __webpack_require__(31);

	var CallbackQueue = __webpack_require__(89);
	var PooledClass = __webpack_require__(82);
	var ReactFeatureFlags = __webpack_require__(90);
	var ReactReconciler = __webpack_require__(91);
	var Transaction = __webpack_require__(100);

	var invariant = __webpack_require__(39);

	var dirtyComponents = [];
	var updateBatchNumber = 0;
	var asapCallbackQueue = CallbackQueue.getPooled();
	var asapEnqueued = false;

	var batchingStrategy = null;

	function ensureInjected() {
	  !(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching strategy') : _prodInvariant('123') : void 0;
	}

	var NESTED_UPDATES = {
	  initialize: function () {
	    this.dirtyComponentsLength = dirtyComponents.length;
	  },
	  close: function () {
	    if (this.dirtyComponentsLength !== dirtyComponents.length) {
	      // Additional updates were enqueued by componentDidUpdate handlers or
	      // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run
	      // these new updates so that if A's componentDidUpdate calls setState on
	      // B, B will update before the callback A's updater provided when calling
	      // setState.
	      dirtyComponents.splice(0, this.dirtyComponentsLength);
	      flushBatchedUpdates();
	    } else {
	      dirtyComponents.length = 0;
	    }
	  }
	};

	var UPDATE_QUEUEING = {
	  initialize: function () {
	    this.callbackQueue.reset();
	  },
	  close: function () {
	    this.callbackQueue.notifyAll();
	  }
	};

	var TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];

	function ReactUpdatesFlushTransaction() {
	  this.reinitializeTransaction();
	  this.dirtyComponentsLength = null;
	  this.callbackQueue = CallbackQueue.getPooled();
	  this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(
	  /* useCreateElement */true);
	}

	_assign(ReactUpdatesFlushTransaction.prototype, Transaction, {
	  getTransactionWrappers: function () {
	    return TRANSACTION_WRAPPERS;
	  },

	  destructor: function () {
	    this.dirtyComponentsLength = null;
	    CallbackQueue.release(this.callbackQueue);
	    this.callbackQueue = null;
	    ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);
	    this.reconcileTransaction = null;
	  },

	  perform: function (method, scope, a) {
	    // Essentially calls `this.reconcileTransaction.perform(method, scope, a)`
	    // with this transaction's wrappers around it.
	    return Transaction.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a);
	  }
	});

	PooledClass.addPoolingTo(ReactUpdatesFlushTransaction);

	function batchedUpdates(callback, a, b, c, d, e) {
	  ensureInjected();
	  return batchingStrategy.batchedUpdates(callback, a, b, c, d, e);
	}

	/**
	 * Array comparator for ReactComponents by mount ordering.
	 *
	 * @param {ReactComponent} c1 first component you're comparing
	 * @param {ReactComponent} c2 second component you're comparing
	 * @return {number} Return value usable by Array.prototype.sort().
	 */
	function mountOrderComparator(c1, c2) {
	  return c1._mountOrder - c2._mountOrder;
	}

	function runBatchedUpdates(transaction) {
	  var len = transaction.dirtyComponentsLength;
	  !(len === dirtyComponents.length) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected flush transaction\'s stored dirty-components length (%s) to match dirty-components array length (%s).', len, dirtyComponents.length) : _prodInvariant('124', len, dirtyComponents.length) : void 0;

	  // Since reconciling a component higher in the owner hierarchy usually (not
	  // always -- see shouldComponentUpdate()) will reconcile children, reconcile
	  // them before their children by sorting the array.
	  dirtyComponents.sort(mountOrderComparator);

	  // Any updates enqueued while reconciling must be performed after this entire
	  // batch. Otherwise, if dirtyComponents is [A, B] where A has children B and
	  // C, B could update twice in a single batch if C's render enqueues an update
	  // to B (since B would have already updated, we should skip it, and the only
	  // way we can know to do so is by checking the batch counter).
	  updateBatchNumber++;

	  for (var i = 0; i < len; i++) {
	    // If a component is unmounted before pending changes apply, it will still
	    // be here, but we assume that it has cleared its _pendingCallbacks and
	    // that performUpdateIfNecessary is a noop.
	    var component = dirtyComponents[i];

	    // If performUpdateIfNecessary happens to enqueue any new updates, we
	    // shouldn't execute the callbacks until the next render happens, so
	    // stash the callbacks first
	    var callbacks = component._pendingCallbacks;
	    component._pendingCallbacks = null;

	    var markerName;
	    if (ReactFeatureFlags.logTopLevelRenders) {
	      var namedComponent = component;
	      // Duck type TopLevelWrapper. This is probably always true.
	      if (component._currentElement.type.isReactTopLevelWrapper) {
	        namedComponent = component._renderedComponent;
	      }
	      markerName = 'React update: ' + namedComponent.getName();
	      console.time(markerName);
	    }

	    ReactReconciler.performUpdateIfNecessary(component, transaction.reconcileTransaction, updateBatchNumber);

	    if (markerName) {
	      console.timeEnd(markerName);
	    }

	    if (callbacks) {
	      for (var j = 0; j < callbacks.length; j++) {
	        transaction.callbackQueue.enqueue(callbacks[j], component.getPublicInstance());
	      }
	    }
	  }
	}

	var flushBatchedUpdates = function () {
	  // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents
	  // array and perform any updates enqueued by mount-ready handlers (i.e.,
	  // componentDidUpdate) but we need to check here too in order to catch
	  // updates enqueued by setState callbacks and asap calls.
	  while (dirtyComponents.length || asapEnqueued) {
	    if (dirtyComponents.length) {
	      var transaction = ReactUpdatesFlushTransaction.getPooled();
	      transaction.perform(runBatchedUpdates, null, transaction);
	      ReactUpdatesFlushTransaction.release(transaction);
	    }

	    if (asapEnqueued) {
	      asapEnqueued = false;
	      var queue = asapCallbackQueue;
	      asapCallbackQueue = CallbackQueue.getPooled();
	      queue.notifyAll();
	      CallbackQueue.release(queue);
	    }
	  }
	};

	/**
	 * Mark a component as needing a rerender, adding an optional callback to a
	 * list of functions which will be executed once the rerender occurs.
	 */
	function enqueueUpdate(component) {
	  ensureInjected();

	  // Various parts of our code (such as ReactCompositeComponent's
	  // _renderValidatedComponent) assume that calls to render aren't nested;
	  // verify that that's the case. (This is called by each top-level update
	  // function, like setState, forceUpdate, etc.; creation and
	  // destruction of top-level components is guarded in ReactMount.)

	  if (!batchingStrategy.isBatchingUpdates) {
	    batchingStrategy.batchedUpdates(enqueueUpdate, component);
	    return;
	  }

	  dirtyComponents.push(component);
	  if (component._updateBatchNumber == null) {
	    component._updateBatchNumber = updateBatchNumber + 1;
	  }
	}

	/**
	 * Enqueue a callback to be run at the end of the current batching cycle. Throws
	 * if no updates are currently being performed.
	 */
	function asap(callback, context) {
	  invariant(batchingStrategy.isBatchingUpdates, "ReactUpdates.asap: Can't enqueue an asap callback in a context where" + 'updates are not being batched.');
	  asapCallbackQueue.enqueue(callback, context);
	  asapEnqueued = true;
	}

	var ReactUpdatesInjection = {
	  injectReconcileTransaction: function (ReconcileTransaction) {
	    !ReconcileTransaction ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : _prodInvariant('126') : void 0;
	    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;
	  },

	  injectBatchingStrategy: function (_batchingStrategy) {
	    !_batchingStrategy ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : _prodInvariant('127') : void 0;
	    !(typeof _batchingStrategy.batchedUpdates === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : _prodInvariant('128') : void 0;
	    !(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : _prodInvariant('129') : void 0;
	    batchingStrategy = _batchingStrategy;
	  }
	};

	var ReactUpdates = {
	  /**
	   * React references `ReactReconcileTransaction` using this property in order
	   * to allow dependency injection.
	   *
	   * @internal
	   */
	  ReactReconcileTransaction: null,

	  batchedUpdates: batchedUpdates,
	  enqueueUpdate: enqueueUpdate,
	  flushBatchedUpdates: flushBatchedUpdates,
	  injection: ReactUpdatesInjection,
	  asap: asap
	};

	module.exports = ReactUpdates;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 89 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var PooledClass = __webpack_require__(82);

	var invariant = __webpack_require__(39);

	/**
	 * A specialized pseudo-event module to help keep track of components waiting to
	 * be notified when their DOM representations are available for use.
	 *
	 * This implements `PooledClass`, so you should never need to instantiate this.
	 * Instead, use `CallbackQueue.getPooled()`.
	 *
	 * @class ReactMountReady
	 * @implements PooledClass
	 * @internal
	 */

	var CallbackQueue = function () {
	  function CallbackQueue(arg) {
	    _classCallCheck(this, CallbackQueue);

	    this._callbacks = null;
	    this._contexts = null;
	    this._arg = arg;
	  }

	  /**
	   * Enqueues a callback to be invoked when `notifyAll` is invoked.
	   *
	   * @param {function} callback Invoked when `notifyAll` is invoked.
	   * @param {?object} context Context to call `callback` with.
	   * @internal
	   */


	  CallbackQueue.prototype.enqueue = function enqueue(callback, context) {
	    this._callbacks = this._callbacks || [];
	    this._callbacks.push(callback);
	    this._contexts = this._contexts || [];
	    this._contexts.push(context);
	  };

	  /**
	   * Invokes all enqueued callbacks and clears the queue. This is invoked after
	   * the DOM representation of a component has been created or updated.
	   *
	   * @internal
	   */


	  CallbackQueue.prototype.notifyAll = function notifyAll() {
	    var callbacks = this._callbacks;
	    var contexts = this._contexts;
	    var arg = this._arg;
	    if (callbacks && contexts) {
	      !(callbacks.length === contexts.length) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : _prodInvariant('24') : void 0;
	      this._callbacks = null;
	      this._contexts = null;
	      for (var i = 0; i < callbacks.length; i++) {
	        callbacks[i].call(contexts[i], arg);
	      }
	      callbacks.length = 0;
	      contexts.length = 0;
	    }
	  };

	  CallbackQueue.prototype.checkpoint = function checkpoint() {
	    return this._callbacks ? this._callbacks.length : 0;
	  };

	  CallbackQueue.prototype.rollback = function rollback(len) {
	    if (this._callbacks && this._contexts) {
	      this._callbacks.length = len;
	      this._contexts.length = len;
	    }
	  };

	  /**
	   * Resets the internal queue.
	   *
	   * @internal
	   */


	  CallbackQueue.prototype.reset = function reset() {
	    this._callbacks = null;
	    this._contexts = null;
	  };

	  /**
	   * `PooledClass` looks for this.
	   */


	  CallbackQueue.prototype.destructor = function destructor() {
	    this.reset();
	  };

	  return CallbackQueue;
	}();

	module.exports = PooledClass.addPoolingTo(CallbackQueue);
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 90 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var ReactFeatureFlags = {
	  // When true, call console.time() before and .timeEnd() after each top-level
	  // render (both initial renders and updates). Useful when looking at prod-mode
	  // timeline profiles in Chrome, for example.
	  logTopLevelRenders: false
	};

	module.exports = ReactFeatureFlags;

/***/ },
/* 91 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactRef = __webpack_require__(92);
	var ReactInstrumentation = __webpack_require__(94);

	var warning = __webpack_require__(35);

	/**
	 * Helper to call ReactRef.attachRefs with this composite component, split out
	 * to avoid allocations in the transaction mount-ready queue.
	 */
	function attachRefs() {
	  ReactRef.attachRefs(this, this._currentElement);
	}

	var ReactReconciler = {
	  /**
	   * Initializes the component, renders markup, and registers event listeners.
	   *
	   * @param {ReactComponent} internalInstance
	   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
	   * @param {?object} the containing host component instance
	   * @param {?object} info about the host container
	   * @return {?string} Rendered markup to be inserted into the DOM.
	   * @final
	   * @internal
	   */
	  mountComponent: function (internalInstance, transaction, hostParent, hostContainerInfo, context, parentDebugID) // 0 in production and for roots
	  {
	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onBeforeMountComponent(internalInstance._debugID, internalInstance._currentElement, parentDebugID);
	      }
	    }
	    var markup = internalInstance.mountComponent(transaction, hostParent, hostContainerInfo, context, parentDebugID);
	    if (internalInstance._currentElement && internalInstance._currentElement.ref != null) {
	      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
	    }
	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID);
	      }
	    }
	    return markup;
	  },

	  /**
	   * Returns a value that can be passed to
	   * ReactComponentEnvironment.replaceNodeWithMarkup.
	   */
	  getHostNode: function (internalInstance) {
	    return internalInstance.getHostNode();
	  },

	  /**
	   * Releases any resources allocated by `mountComponent`.
	   *
	   * @final
	   * @internal
	   */
	  unmountComponent: function (internalInstance, safely) {
	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onBeforeUnmountComponent(internalInstance._debugID);
	      }
	    }
	    ReactRef.detachRefs(internalInstance, internalInstance._currentElement);
	    internalInstance.unmountComponent(safely);
	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID);
	      }
	    }
	  },

	  /**
	   * Update a component using a new element.
	   *
	   * @param {ReactComponent} internalInstance
	   * @param {ReactElement} nextElement
	   * @param {ReactReconcileTransaction} transaction
	   * @param {object} context
	   * @internal
	   */
	  receiveComponent: function (internalInstance, nextElement, transaction, context) {
	    var prevElement = internalInstance._currentElement;

	    if (nextElement === prevElement && context === internalInstance._context) {
	      // Since elements are immutable after the owner is rendered,
	      // we can do a cheap identity compare here to determine if this is a
	      // superfluous reconcile. It's possible for state to be mutable but such
	      // change should trigger an update of the owner which would recreate
	      // the element. We explicitly check for the existence of an owner since
	      // it's possible for an element created outside a composite to be
	      // deeply mutated and reused.

	      // TODO: Bailing out early is just a perf optimization right?
	      // TODO: Removing the return statement should affect correctness?
	      return;
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, nextElement);
	      }
	    }

	    var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);

	    if (refsChanged) {
	      ReactRef.detachRefs(internalInstance, prevElement);
	    }

	    internalInstance.receiveComponent(nextElement, transaction, context);

	    if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) {
	      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);
	      }
	    }
	  },

	  /**
	   * Flush any dirty changes in a component.
	   *
	   * @param {ReactComponent} internalInstance
	   * @param {ReactReconcileTransaction} transaction
	   * @internal
	   */
	  performUpdateIfNecessary: function (internalInstance, transaction, updateBatchNumber) {
	    if (internalInstance._updateBatchNumber !== updateBatchNumber) {
	      // The component's enqueued batch number should always be the current
	      // batch or the following one.
	      process.env.NODE_ENV !== 'production' ? warning(internalInstance._updateBatchNumber == null || internalInstance._updateBatchNumber === updateBatchNumber + 1, 'performUpdateIfNecessary: Unexpected batch number (current %s, ' + 'pending %s)', updateBatchNumber, internalInstance._updateBatchNumber) : void 0;
	      return;
	    }
	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, internalInstance._currentElement);
	      }
	    }
	    internalInstance.performUpdateIfNecessary(transaction);
	    if (process.env.NODE_ENV !== 'production') {
	      if (internalInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);
	      }
	    }
	  }
	};

	module.exports = ReactReconciler;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 92 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var ReactOwner = __webpack_require__(93);

	var ReactRef = {};

	function attachRef(ref, component, owner) {
	  if (typeof ref === 'function') {
	    ref(component.getPublicInstance());
	  } else {
	    // Legacy ref
	    ReactOwner.addComponentAsRefTo(component, ref, owner);
	  }
	}

	function detachRef(ref, component, owner) {
	  if (typeof ref === 'function') {
	    ref(null);
	  } else {
	    // Legacy ref
	    ReactOwner.removeComponentAsRefFrom(component, ref, owner);
	  }
	}

	ReactRef.attachRefs = function (instance, element) {
	  if (element === null || typeof element !== 'object') {
	    return;
	  }
	  var ref = element.ref;
	  if (ref != null) {
	    attachRef(ref, instance, element._owner);
	  }
	};

	ReactRef.shouldUpdateRefs = function (prevElement, nextElement) {
	  // If either the owner or a `ref` has changed, make sure the newest owner
	  // has stored a reference to `this`, and the previous owner (if different)
	  // has forgotten the reference to `this`. We use the element instead
	  // of the public this.props because the post processing cannot determine
	  // a ref. The ref conceptually lives on the element.

	  // TODO: Should this even be possible? The owner cannot change because
	  // it's forbidden by shouldUpdateReactComponent. The ref can change
	  // if you swap the keys of but not the refs. Reconsider where this check
	  // is made. It probably belongs where the key checking and
	  // instantiateReactComponent is done.

	  var prevRef = null;
	  var prevOwner = null;
	  if (prevElement !== null && typeof prevElement === 'object') {
	    prevRef = prevElement.ref;
	    prevOwner = prevElement._owner;
	  }

	  var nextRef = null;
	  var nextOwner = null;
	  if (nextElement !== null && typeof nextElement === 'object') {
	    nextRef = nextElement.ref;
	    nextOwner = nextElement._owner;
	  }

	  return prevRef !== nextRef ||
	  // If owner changes but we have an unchanged function ref, don't update refs
	  typeof nextRef === 'string' && nextOwner !== prevOwner;
	};

	ReactRef.detachRefs = function (instance, element) {
	  if (element === null || typeof element !== 'object') {
	    return;
	  }
	  var ref = element.ref;
	  if (ref != null) {
	    detachRef(ref, instance, element._owner);
	  }
	};

	module.exports = ReactRef;

/***/ },
/* 93 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	/**
	 * @param {?object} object
	 * @return {boolean} True if `object` is a valid owner.
	 * @final
	 */
	function isValidOwner(object) {
	  return !!(object && typeof object.attachRef === 'function' && typeof object.detachRef === 'function');
	}

	/**
	 * ReactOwners are capable of storing references to owned components.
	 *
	 * All components are capable of //being// referenced by owner components, but
	 * only ReactOwner components are capable of //referencing// owned components.
	 * The named reference is known as a "ref".
	 *
	 * Refs are available when mounted and updated during reconciliation.
	 *
	 *   var MyComponent = React.createClass({
	 *     render: function() {
	 *       return (
	 *         <div onClick={this.handleClick}>
	 *           <CustomComponent ref="custom" />
	 *         </div>
	 *       );
	 *     },
	 *     handleClick: function() {
	 *       this.refs.custom.handleClick();
	 *     },
	 *     componentDidMount: function() {
	 *       this.refs.custom.initialize();
	 *     }
	 *   });
	 *
	 * Refs should rarely be used. When refs are used, they should only be done to
	 * control data that is not handled by React's data flow.
	 *
	 * @class ReactOwner
	 */
	var ReactOwner = {
	  /**
	   * Adds a component by ref to an owner component.
	   *
	   * @param {ReactComponent} component Component to reference.
	   * @param {string} ref Name by which to refer to the component.
	   * @param {ReactOwner} owner Component on which to record the ref.
	   * @final
	   * @internal
	   */
	  addComponentAsRefTo: function (component, ref, owner) {
	    !isValidOwner(owner) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('119') : void 0;
	    owner.attachRef(ref, component);
	  },

	  /**
	   * Removes a component by ref from an owner component.
	   *
	   * @param {ReactComponent} component Component to dereference.
	   * @param {string} ref Name of the ref to remove.
	   * @param {ReactOwner} owner Component on which the ref is recorded.
	   * @final
	   * @internal
	   */
	  removeComponentAsRefFrom: function (component, ref, owner) {
	    !isValidOwner(owner) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('120') : void 0;
	    var ownerPublicInstance = owner.getPublicInstance();
	    // Check that `component`'s owner is still alive and that `component` is still the current ref
	    // because we do not want to detach the ref if another component stole it.
	    if (ownerPublicInstance && ownerPublicInstance.refs[ref] === component.getPublicInstance()) {
	      owner.detachRef(ref);
	    }
	  }
	};

	module.exports = ReactOwner;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 94 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2016-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	// Trust the developer to only use ReactInstrumentation with a __DEV__ check

	var debugTool = null;

	if (process.env.NODE_ENV !== 'production') {
	  var ReactDebugTool = __webpack_require__(95);
	  debugTool = ReactDebugTool;
	}

	module.exports = { debugTool: debugTool };
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 95 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2016-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var ReactInvalidSetStateWarningHook = __webpack_require__(96);
	var ReactHostOperationHistoryHook = __webpack_require__(97);
	var ReactComponentTreeHook = __webpack_require__(51);
	var ExecutionEnvironment = __webpack_require__(80);

	var performanceNow = __webpack_require__(98);
	var warning = __webpack_require__(35);

	var hooks = [];
	var didHookThrowForEvent = {};

	function callHook(event, fn, context, arg1, arg2, arg3, arg4, arg5) {
	  try {
	    fn.call(context, arg1, arg2, arg3, arg4, arg5);
	  } catch (e) {
	    process.env.NODE_ENV !== 'production' ? warning(didHookThrowForEvent[event], 'Exception thrown by hook while handling %s: %s', event, e + '\n' + e.stack) : void 0;
	    didHookThrowForEvent[event] = true;
	  }
	}

	function emitEvent(event, arg1, arg2, arg3, arg4, arg5) {
	  for (var i = 0; i < hooks.length; i++) {
	    var hook = hooks[i];
	    var fn = hook[event];
	    if (fn) {
	      callHook(event, fn, hook, arg1, arg2, arg3, arg4, arg5);
	    }
	  }
	}

	var isProfiling = false;
	var flushHistory = [];
	var lifeCycleTimerStack = [];
	var currentFlushNesting = 0;
	var currentFlushMeasurements = [];
	var currentFlushStartTime = 0;
	var currentTimerDebugID = null;
	var currentTimerStartTime = 0;
	var currentTimerNestedFlushDuration = 0;
	var currentTimerType = null;

	var lifeCycleTimerHasWarned = false;

	function clearHistory() {
	  ReactComponentTreeHook.purgeUnmountedComponents();
	  ReactHostOperationHistoryHook.clearHistory();
	}

	function getTreeSnapshot(registeredIDs) {
	  return registeredIDs.reduce(function (tree, id) {
	    var ownerID = ReactComponentTreeHook.getOwnerID(id);
	    var parentID = ReactComponentTreeHook.getParentID(id);
	    tree[id] = {
	      displayName: ReactComponentTreeHook.getDisplayName(id),
	      text: ReactComponentTreeHook.getText(id),
	      updateCount: ReactComponentTreeHook.getUpdateCount(id),
	      childIDs: ReactComponentTreeHook.getChildIDs(id),
	      // Text nodes don't have owners but this is close enough.
	      ownerID: ownerID || parentID && ReactComponentTreeHook.getOwnerID(parentID) || 0,
	      parentID: parentID
	    };
	    return tree;
	  }, {});
	}

	function resetMeasurements() {
	  var previousStartTime = currentFlushStartTime;
	  var previousMeasurements = currentFlushMeasurements;
	  var previousOperations = ReactHostOperationHistoryHook.getHistory();

	  if (currentFlushNesting === 0) {
	    currentFlushStartTime = 0;
	    currentFlushMeasurements = [];
	    clearHistory();
	    return;
	  }

	  if (previousMeasurements.length || previousOperations.length) {
	    var registeredIDs = ReactComponentTreeHook.getRegisteredIDs();
	    flushHistory.push({
	      duration: performanceNow() - previousStartTime,
	      measurements: previousMeasurements || [],
	      operations: previousOperations || [],
	      treeSnapshot: getTreeSnapshot(registeredIDs)
	    });
	  }

	  clearHistory();
	  currentFlushStartTime = performanceNow();
	  currentFlushMeasurements = [];
	}

	function checkDebugID(debugID) {
	  var allowRoot = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

	  if (allowRoot && debugID === 0) {
	    return;
	  }
	  if (!debugID) {
	    process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDebugTool: debugID may not be empty.') : void 0;
	  }
	}

	function beginLifeCycleTimer(debugID, timerType) {
	  if (currentFlushNesting === 0) {
	    return;
	  }
	  if (currentTimerType && !lifeCycleTimerHasWarned) {
	    process.env.NODE_ENV !== 'production' ? warning(false, 'There is an internal error in the React performance measurement code. ' + 'Did not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;
	    lifeCycleTimerHasWarned = true;
	  }
	  currentTimerStartTime = performanceNow();
	  currentTimerNestedFlushDuration = 0;
	  currentTimerDebugID = debugID;
	  currentTimerType = timerType;
	}

	function endLifeCycleTimer(debugID, timerType) {
	  if (currentFlushNesting === 0) {
	    return;
	  }
	  if (currentTimerType !== timerType && !lifeCycleTimerHasWarned) {
	    process.env.NODE_ENV !== 'production' ? warning(false, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;
	    lifeCycleTimerHasWarned = true;
	  }
	  if (isProfiling) {
	    currentFlushMeasurements.push({
	      timerType: timerType,
	      instanceID: debugID,
	      duration: performanceNow() - currentTimerStartTime - currentTimerNestedFlushDuration
	    });
	  }
	  currentTimerStartTime = 0;
	  currentTimerNestedFlushDuration = 0;
	  currentTimerDebugID = null;
	  currentTimerType = null;
	}

	function pauseCurrentLifeCycleTimer() {
	  var currentTimer = {
	    startTime: currentTimerStartTime,
	    nestedFlushStartTime: performanceNow(),
	    debugID: currentTimerDebugID,
	    timerType: currentTimerType
	  };
	  lifeCycleTimerStack.push(currentTimer);
	  currentTimerStartTime = 0;
	  currentTimerNestedFlushDuration = 0;
	  currentTimerDebugID = null;
	  currentTimerType = null;
	}

	function resumeCurrentLifeCycleTimer() {
	  var _lifeCycleTimerStack$ = lifeCycleTimerStack.pop(),
	      startTime = _lifeCycleTimerStack$.startTime,
	      nestedFlushStartTime = _lifeCycleTimerStack$.nestedFlushStartTime,
	      debugID = _lifeCycleTimerStack$.debugID,
	      timerType = _lifeCycleTimerStack$.timerType;

	  var nestedFlushDuration = performanceNow() - nestedFlushStartTime;
	  currentTimerStartTime = startTime;
	  currentTimerNestedFlushDuration += nestedFlushDuration;
	  currentTimerDebugID = debugID;
	  currentTimerType = timerType;
	}

	var lastMarkTimeStamp = 0;
	var canUsePerformanceMeasure = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function';

	function shouldMark(debugID) {
	  if (!isProfiling || !canUsePerformanceMeasure) {
	    return false;
	  }
	  var element = ReactComponentTreeHook.getElement(debugID);
	  if (element == null || typeof element !== 'object') {
	    return false;
	  }
	  var isHostElement = typeof element.type === 'string';
	  if (isHostElement) {
	    return false;
	  }
	  return true;
	}

	function markBegin(debugID, markType) {
	  if (!shouldMark(debugID)) {
	    return;
	  }

	  var markName = debugID + '::' + markType;
	  lastMarkTimeStamp = performanceNow();
	  performance.mark(markName);
	}

	function markEnd(debugID, markType) {
	  if (!shouldMark(debugID)) {
	    return;
	  }

	  var markName = debugID + '::' + markType;
	  var displayName = ReactComponentTreeHook.getDisplayName(debugID) || 'Unknown';

	  // Chrome has an issue of dropping markers recorded too fast:
	  // https://bugs.chromium.org/p/chromium/issues/detail?id=640652
	  // To work around this, we will not report very small measurements.
	  // I determined the magic number by tweaking it back and forth.
	  // 0.05ms was enough to prevent the issue, but I set it to 0.1ms to be safe.
	  // When the bug is fixed, we can `measure()` unconditionally if we want to.
	  var timeStamp = performanceNow();
	  if (timeStamp - lastMarkTimeStamp > 0.1) {
	    var measurementName = displayName + ' [' + markType + ']';
	    performance.measure(measurementName, markName);
	  }

	  performance.clearMarks(markName);
	  if (measurementName) {
	    performance.clearMeasures(measurementName);
	  }
	}

	var ReactDebugTool = {
	  addHook: function (hook) {
	    hooks.push(hook);
	  },
	  removeHook: function (hook) {
	    for (var i = 0; i < hooks.length; i++) {
	      if (hooks[i] === hook) {
	        hooks.splice(i, 1);
	        i--;
	      }
	    }
	  },
	  isProfiling: function () {
	    return isProfiling;
	  },
	  beginProfiling: function () {
	    if (isProfiling) {
	      return;
	    }

	    isProfiling = true;
	    flushHistory.length = 0;
	    resetMeasurements();
	    ReactDebugTool.addHook(ReactHostOperationHistoryHook);
	  },
	  endProfiling: function () {
	    if (!isProfiling) {
	      return;
	    }

	    isProfiling = false;
	    resetMeasurements();
	    ReactDebugTool.removeHook(ReactHostOperationHistoryHook);
	  },
	  getFlushHistory: function () {
	    return flushHistory;
	  },
	  onBeginFlush: function () {
	    currentFlushNesting++;
	    resetMeasurements();
	    pauseCurrentLifeCycleTimer();
	    emitEvent('onBeginFlush');
	  },
	  onEndFlush: function () {
	    resetMeasurements();
	    currentFlushNesting--;
	    resumeCurrentLifeCycleTimer();
	    emitEvent('onEndFlush');
	  },
	  onBeginLifeCycleTimer: function (debugID, timerType) {
	    checkDebugID(debugID);
	    emitEvent('onBeginLifeCycleTimer', debugID, timerType);
	    markBegin(debugID, timerType);
	    beginLifeCycleTimer(debugID, timerType);
	  },
	  onEndLifeCycleTimer: function (debugID, timerType) {
	    checkDebugID(debugID);
	    endLifeCycleTimer(debugID, timerType);
	    markEnd(debugID, timerType);
	    emitEvent('onEndLifeCycleTimer', debugID, timerType);
	  },
	  onBeginProcessingChildContext: function () {
	    emitEvent('onBeginProcessingChildContext');
	  },
	  onEndProcessingChildContext: function () {
	    emitEvent('onEndProcessingChildContext');
	  },
	  onHostOperation: function (operation) {
	    checkDebugID(operation.instanceID);
	    emitEvent('onHostOperation', operation);
	  },
	  onSetState: function () {
	    emitEvent('onSetState');
	  },
	  onSetChildren: function (debugID, childDebugIDs) {
	    checkDebugID(debugID);
	    childDebugIDs.forEach(checkDebugID);
	    emitEvent('onSetChildren', debugID, childDebugIDs);
	  },
	  onBeforeMountComponent: function (debugID, element, parentDebugID) {
	    checkDebugID(debugID);
	    checkDebugID(parentDebugID, true);
	    emitEvent('onBeforeMountComponent', debugID, element, parentDebugID);
	    markBegin(debugID, 'mount');
	  },
	  onMountComponent: function (debugID) {
	    checkDebugID(debugID);
	    markEnd(debugID, 'mount');
	    emitEvent('onMountComponent', debugID);
	  },
	  onBeforeUpdateComponent: function (debugID, element) {
	    checkDebugID(debugID);
	    emitEvent('onBeforeUpdateComponent', debugID, element);
	    markBegin(debugID, 'update');
	  },
	  onUpdateComponent: function (debugID) {
	    checkDebugID(debugID);
	    markEnd(debugID, 'update');
	    emitEvent('onUpdateComponent', debugID);
	  },
	  onBeforeUnmountComponent: function (debugID) {
	    checkDebugID(debugID);
	    emitEvent('onBeforeUnmountComponent', debugID);
	    markBegin(debugID, 'unmount');
	  },
	  onUnmountComponent: function (debugID) {
	    checkDebugID(debugID);
	    markEnd(debugID, 'unmount');
	    emitEvent('onUnmountComponent', debugID);
	  },
	  onTestEvent: function () {
	    emitEvent('onTestEvent');
	  }
	};

	// TODO remove these when RN/www gets updated
	ReactDebugTool.addDevtool = ReactDebugTool.addHook;
	ReactDebugTool.removeDevtool = ReactDebugTool.removeHook;

	ReactDebugTool.addHook(ReactInvalidSetStateWarningHook);
	ReactDebugTool.addHook(ReactComponentTreeHook);
	var url = ExecutionEnvironment.canUseDOM && window.location.href || '';
	if (/[?&]react_perf\b/.test(url)) {
	  ReactDebugTool.beginProfiling();
	}

	module.exports = ReactDebugTool;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 96 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2016-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var warning = __webpack_require__(35);

	if (process.env.NODE_ENV !== 'production') {
	  var processingChildContext = false;

	  var warnInvalidSetState = function () {
	    process.env.NODE_ENV !== 'production' ? warning(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()') : void 0;
	  };
	}

	var ReactInvalidSetStateWarningHook = {
	  onBeginProcessingChildContext: function () {
	    processingChildContext = true;
	  },
	  onEndProcessingChildContext: function () {
	    processingChildContext = false;
	  },
	  onSetState: function () {
	    warnInvalidSetState();
	  }
	};

	module.exports = ReactInvalidSetStateWarningHook;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 97 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2016-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var history = [];

	var ReactHostOperationHistoryHook = {
	  onHostOperation: function (operation) {
	    history.push(operation);
	  },
	  clearHistory: function () {
	    if (ReactHostOperationHistoryHook._preventClearing) {
	      // Should only be used for tests.
	      return;
	    }

	    history = [];
	  },
	  getHistory: function () {
	    return history;
	  }
	};

	module.exports = ReactHostOperationHistoryHook;

/***/ },
/* 98 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	var performance = __webpack_require__(99);

	var performanceNow;

	/**
	 * Detect if we can use `window.performance.now()` and gracefully fallback to
	 * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now
	 * because of Facebook's testing infrastructure.
	 */
	if (performance.now) {
	  performanceNow = function performanceNow() {
	    return performance.now();
	  };
	} else {
	  performanceNow = function performanceNow() {
	    return Date.now();
	  };
	}

	module.exports = performanceNow;

/***/ },
/* 99 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	'use strict';

	var ExecutionEnvironment = __webpack_require__(80);

	var performance;

	if (ExecutionEnvironment.canUseDOM) {
	  performance = window.performance || window.msPerformance || window.webkitPerformance;
	}

	module.exports = performance || {};

/***/ },
/* 100 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	var OBSERVED_ERROR = {};

	/**
	 * `Transaction` creates a black box that is able to wrap any method such that
	 * certain invariants are maintained before and after the method is invoked
	 * (Even if an exception is thrown while invoking the wrapped method). Whoever
	 * instantiates a transaction can provide enforcers of the invariants at
	 * creation time. The `Transaction` class itself will supply one additional
	 * automatic invariant for you - the invariant that any transaction instance
	 * should not be run while it is already being run. You would typically create a
	 * single instance of a `Transaction` for reuse multiple times, that potentially
	 * is used to wrap several different methods. Wrappers are extremely simple -
	 * they only require implementing two methods.
	 *
	 * <pre>
	 *                       wrappers (injected at creation time)
	 *                                      +        +
	 *                                      |        |
	 *                    +-----------------|--------|--------------+
	 *                    |                 v        |              |
	 *                    |      +---------------+   |              |
	 *                    |   +--|    wrapper1   |---|----+         |
	 *                    |   |  +---------------+   v    |         |
	 *                    |   |          +-------------+  |         |
	 *                    |   |     +----|   wrapper2  |--------+   |
	 *                    |   |     |    +-------------+  |     |   |
	 *                    |   |     |                     |     |   |
	 *                    |   v     v                     v     v   | wrapper
	 *                    | +---+ +---+   +---------+   +---+ +---+ | invariants
	 * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained
	 * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
	 *                    | |   | |   |   |         |   |   | |   | |
	 *                    | |   | |   |   |         |   |   | |   | |
	 *                    | |   | |   |   |         |   |   | |   | |
	 *                    | +---+ +---+   +---------+   +---+ +---+ |
	 *                    |  initialize                    close    |
	 *                    +-----------------------------------------+
	 * </pre>
	 *
	 * Use cases:
	 * - Preserving the input selection ranges before/after reconciliation.
	 *   Restoring selection even in the event of an unexpected error.
	 * - Deactivating events while rearranging the DOM, preventing blurs/focuses,
	 *   while guaranteeing that afterwards, the event system is reactivated.
	 * - Flushing a queue of collected DOM mutations to the main UI thread after a
	 *   reconciliation takes place in a worker thread.
	 * - Invoking any collected `componentDidUpdate` callbacks after rendering new
	 *   content.
	 * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue
	 *   to preserve the `scrollTop` (an automatic scroll aware DOM).
	 * - (Future use case): Layout calculations before and after DOM updates.
	 *
	 * Transactional plugin API:
	 * - A module that has an `initialize` method that returns any precomputation.
	 * - and a `close` method that accepts the precomputation. `close` is invoked
	 *   when the wrapped process is completed, or has failed.
	 *
	 * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules
	 * that implement `initialize` and `close`.
	 * @return {Transaction} Single transaction for reuse in thread.
	 *
	 * @class Transaction
	 */
	var TransactionImpl = {
	  /**
	   * Sets up this instance so that it is prepared for collecting metrics. Does
	   * so such that this setup method may be used on an instance that is already
	   * initialized, in a way that does not consume additional memory upon reuse.
	   * That can be useful if you decide to make your subclass of this mixin a
	   * "PooledClass".
	   */
	  reinitializeTransaction: function () {
	    this.transactionWrappers = this.getTransactionWrappers();
	    if (this.wrapperInitData) {
	      this.wrapperInitData.length = 0;
	    } else {
	      this.wrapperInitData = [];
	    }
	    this._isInTransaction = false;
	  },

	  _isInTransaction: false,

	  /**
	   * @abstract
	   * @return {Array<TransactionWrapper>} Array of transaction wrappers.
	   */
	  getTransactionWrappers: null,

	  isInTransaction: function () {
	    return !!this._isInTransaction;
	  },

	  /* eslint-disable space-before-function-paren */

	  /**
	   * Executes the function within a safety window. Use this for the top level
	   * methods that result in large amounts of computation/mutations that would
	   * need to be safety checked. The optional arguments helps prevent the need
	   * to bind in many cases.
	   *
	   * @param {function} method Member of scope to call.
	   * @param {Object} scope Scope to invoke from.
	   * @param {Object?=} a Argument to pass to the method.
	   * @param {Object?=} b Argument to pass to the method.
	   * @param {Object?=} c Argument to pass to the method.
	   * @param {Object?=} d Argument to pass to the method.
	   * @param {Object?=} e Argument to pass to the method.
	   * @param {Object?=} f Argument to pass to the method.
	   *
	   * @return {*} Return value from `method`.
	   */
	  perform: function (method, scope, a, b, c, d, e, f) {
	    /* eslint-enable space-before-function-paren */
	    !!this.isInTransaction() ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Transaction.perform(...): Cannot initialize a transaction when there is already an outstanding transaction.') : _prodInvariant('27') : void 0;
	    var errorThrown;
	    var ret;
	    try {
	      this._isInTransaction = true;
	      // Catching errors makes debugging more difficult, so we start with
	      // errorThrown set to true before setting it to false after calling
	      // close -- if it's still set to true in the finally block, it means
	      // one of these calls threw.
	      errorThrown = true;
	      this.initializeAll(0);
	      ret = method.call(scope, a, b, c, d, e, f);
	      errorThrown = false;
	    } finally {
	      try {
	        if (errorThrown) {
	          // If `method` throws, prefer to show that stack trace over any thrown
	          // by invoking `closeAll`.
	          try {
	            this.closeAll(0);
	          } catch (err) {}
	        } else {
	          // Since `method` didn't throw, we don't want to silence the exception
	          // here.
	          this.closeAll(0);
	        }
	      } finally {
	        this._isInTransaction = false;
	      }
	    }
	    return ret;
	  },

	  initializeAll: function (startIndex) {
	    var transactionWrappers = this.transactionWrappers;
	    for (var i = startIndex; i < transactionWrappers.length; i++) {
	      var wrapper = transactionWrappers[i];
	      try {
	        // Catching errors makes debugging more difficult, so we start with the
	        // OBSERVED_ERROR state before overwriting it with the real return value
	        // of initialize -- if it's still set to OBSERVED_ERROR in the finally
	        // block, it means wrapper.initialize threw.
	        this.wrapperInitData[i] = OBSERVED_ERROR;
	        this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null;
	      } finally {
	        if (this.wrapperInitData[i] === OBSERVED_ERROR) {
	          // The initializer for wrapper i threw an error; initialize the
	          // remaining wrappers but silence any exceptions from them to ensure
	          // that the first error is the one to bubble up.
	          try {
	            this.initializeAll(i + 1);
	          } catch (err) {}
	        }
	      }
	    }
	  },

	  /**
	   * Invokes each of `this.transactionWrappers.close[i]` functions, passing into
	   * them the respective return values of `this.transactionWrappers.init[i]`
	   * (`close`rs that correspond to initializers that failed will not be
	   * invoked).
	   */
	  closeAll: function (startIndex) {
	    !this.isInTransaction() ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') : _prodInvariant('28') : void 0;
	    var transactionWrappers = this.transactionWrappers;
	    for (var i = startIndex; i < transactionWrappers.length; i++) {
	      var wrapper = transactionWrappers[i];
	      var initData = this.wrapperInitData[i];
	      var errorThrown;
	      try {
	        // Catching errors makes debugging more difficult, so we start with
	        // errorThrown set to true before setting it to false after calling
	        // close -- if it's still set to true in the finally block, it means
	        // wrapper.close threw.
	        errorThrown = true;
	        if (initData !== OBSERVED_ERROR && wrapper.close) {
	          wrapper.close.call(this, initData);
	        }
	        errorThrown = false;
	      } finally {
	        if (errorThrown) {
	          // The closer for wrapper i threw an error; close the remaining
	          // wrappers but silence any exceptions from them to ensure that the
	          // first error is the one to bubble up.
	          try {
	            this.closeAll(i + 1);
	          } catch (e) {}
	        }
	      }
	    }
	    this.wrapperInitData.length = 0;
	  }
	};

	module.exports = TransactionImpl;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 101 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactDOMComponentTree = __webpack_require__(66);

	function isCheckable(elem) {
	  var type = elem.type;
	  var nodeName = elem.nodeName;
	  return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
	}

	function getTracker(inst) {
	  return inst._wrapperState.valueTracker;
	}

	function attachTracker(inst, tracker) {
	  inst._wrapperState.valueTracker = tracker;
	}

	function detachTracker(inst) {
	  inst._wrapperState.valueTracker = null;
	}

	function getValueFromNode(node) {
	  var value;
	  if (node) {
	    value = isCheckable(node) ? '' + node.checked : node.value;
	  }
	  return value;
	}

	var inputValueTracking = {
	  // exposed for testing
	  _getTrackerFromNode: function (node) {
	    return getTracker(ReactDOMComponentTree.getInstanceFromNode(node));
	  },


	  track: function (inst) {
	    if (getTracker(inst)) {
	      return;
	    }

	    var node = ReactDOMComponentTree.getNodeFromInstance(inst);
	    var valueField = isCheckable(node) ? 'checked' : 'value';
	    var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);

	    var currentValue = '' + node[valueField];

	    // if someone has already defined a value or Safari, then bail
	    // and don't track value will cause over reporting of changes,
	    // but it's better then a hard failure
	    // (needed for certain tests that spyOn input values and Safari)
	    if (node.hasOwnProperty(valueField) || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
	      return;
	    }

	    Object.defineProperty(node, valueField, {
	      enumerable: descriptor.enumerable,
	      configurable: true,
	      get: function () {
	        return descriptor.get.call(this);
	      },
	      set: function (value) {
	        currentValue = '' + value;
	        descriptor.set.call(this, value);
	      }
	    });

	    attachTracker(inst, {
	      getValue: function () {
	        return currentValue;
	      },
	      setValue: function (value) {
	        currentValue = '' + value;
	      },
	      stopTracking: function () {
	        detachTracker(inst);
	        delete node[valueField];
	      }
	    });
	  },

	  updateValueIfChanged: function (inst) {
	    if (!inst) {
	      return false;
	    }
	    var tracker = getTracker(inst);

	    if (!tracker) {
	      inputValueTracking.track(inst);
	      return true;
	    }

	    var lastValue = tracker.getValue();
	    var nextValue = getValueFromNode(ReactDOMComponentTree.getNodeFromInstance(inst));

	    if (nextValue !== lastValue) {
	      tracker.setValue(nextValue);
	      return true;
	    }

	    return false;
	  },
	  stopTracking: function (inst) {
	    var tracker = getTracker(inst);
	    if (tracker) {
	      tracker.stopTracking();
	    }
	  }
	};

	module.exports = inputValueTracking;

/***/ },
/* 102 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * Gets the target node from a native browser event by accounting for
	 * inconsistencies in browser DOM APIs.
	 *
	 * @param {object} nativeEvent Native browser event.
	 * @return {DOMEventTarget} Target node.
	 */

	function getEventTarget(nativeEvent) {
	  var target = nativeEvent.target || nativeEvent.srcElement || window;

	  // Normalize SVG <use> element events #4963
	  if (target.correspondingUseElement) {
	    target = target.correspondingUseElement;
	  }

	  // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
	  // @see http://www.quirksmode.org/js/events_properties.html
	  return target.nodeType === 3 ? target.parentNode : target;
	}

	module.exports = getEventTarget;

/***/ },
/* 103 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ExecutionEnvironment = __webpack_require__(80);

	var useHasFeature;
	if (ExecutionEnvironment.canUseDOM) {
	  useHasFeature = document.implementation && document.implementation.hasFeature &&
	  // always returns true in newer browsers as per the standard.
	  // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
	  document.implementation.hasFeature('', '') !== true;
	}

	/**
	 * Checks if an event is supported in the current execution environment.
	 *
	 * NOTE: This will not work correctly for non-generic events such as `change`,
	 * `reset`, `load`, `error`, and `select`.
	 *
	 * Borrows from Modernizr.
	 *
	 * @param {string} eventNameSuffix Event name, e.g. "click".
	 * @param {?boolean} capture Check if the capture phase is supported.
	 * @return {boolean} True if the event is supported.
	 * @internal
	 * @license Modernizr 3.0.0pre (Custom Build) | MIT
	 */
	function isEventSupported(eventNameSuffix, capture) {
	  if (!ExecutionEnvironment.canUseDOM || capture && !('addEventListener' in document)) {
	    return false;
	  }

	  var eventName = 'on' + eventNameSuffix;
	  var isSupported = eventName in document;

	  if (!isSupported) {
	    var element = document.createElement('div');
	    element.setAttribute(eventName, 'return;');
	    isSupported = typeof element[eventName] === 'function';
	  }

	  if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {
	    // This is the only way to test support for the `wheel` event in IE9+.
	    isSupported = document.implementation.hasFeature('Events.wheel', '3.0');
	  }

	  return isSupported;
	}

	module.exports = isEventSupported;

/***/ },
/* 104 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	/**
	 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
	 */

	var supportedInputTypes = {
	  color: true,
	  date: true,
	  datetime: true,
	  'datetime-local': true,
	  email: true,
	  month: true,
	  number: true,
	  password: true,
	  range: true,
	  search: true,
	  tel: true,
	  text: true,
	  time: true,
	  url: true,
	  week: true
	};

	function isTextInputElement(elem) {
	  var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();

	  if (nodeName === 'input') {
	    return !!supportedInputTypes[elem.type];
	  }

	  if (nodeName === 'textarea') {
	    return true;
	  }

	  return false;
	}

	module.exports = isTextInputElement;

/***/ },
/* 105 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * Module that is injectable into `EventPluginHub`, that specifies a
	 * deterministic ordering of `EventPlugin`s. A convenient way to reason about
	 * plugins, without having to package every one of them. This is better than
	 * having plugins be ordered in the same order that they are injected because
	 * that ordering would be influenced by the packaging order.
	 * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
	 * preventing default on events is convenient in `SimpleEventPlugin` handlers.
	 */

	var DefaultEventPluginOrder = ['ResponderEventPlugin', 'SimpleEventPlugin', 'TapEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin'];

	module.exports = DefaultEventPluginOrder;

/***/ },
/* 106 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var EventPropagators = __webpack_require__(73);
	var ReactDOMComponentTree = __webpack_require__(66);
	var SyntheticMouseEvent = __webpack_require__(107);

	var eventTypes = {
	  mouseEnter: {
	    registrationName: 'onMouseEnter',
	    dependencies: ['topMouseOut', 'topMouseOver']
	  },
	  mouseLeave: {
	    registrationName: 'onMouseLeave',
	    dependencies: ['topMouseOut', 'topMouseOver']
	  }
	};

	var EnterLeaveEventPlugin = {
	  eventTypes: eventTypes,

	  /**
	   * For almost every interaction we care about, there will be both a top-level
	   * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
	   * we do not extract duplicate events. However, moving the mouse into the
	   * browser from outside will not fire a `mouseout` event. In this case, we use
	   * the `mouseover` top-level event.
	   */
	  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	    if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
	      return null;
	    }
	    if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
	      // Must not be a mouse in or mouse out - ignoring.
	      return null;
	    }

	    var win;
	    if (nativeEventTarget.window === nativeEventTarget) {
	      // `nativeEventTarget` is probably a window object.
	      win = nativeEventTarget;
	    } else {
	      // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
	      var doc = nativeEventTarget.ownerDocument;
	      if (doc) {
	        win = doc.defaultView || doc.parentWindow;
	      } else {
	        win = window;
	      }
	    }

	    var from;
	    var to;
	    if (topLevelType === 'topMouseOut') {
	      from = targetInst;
	      var related = nativeEvent.relatedTarget || nativeEvent.toElement;
	      to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;
	    } else {
	      // Moving to a node from outside the window.
	      from = null;
	      to = targetInst;
	    }

	    if (from === to) {
	      // Nothing pertains to our managed components.
	      return null;
	    }

	    var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);
	    var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);

	    var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);
	    leave.type = 'mouseleave';
	    leave.target = fromNode;
	    leave.relatedTarget = toNode;

	    var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);
	    enter.type = 'mouseenter';
	    enter.target = toNode;
	    enter.relatedTarget = fromNode;

	    EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);

	    return [leave, enter];
	  }
	};

	module.exports = EnterLeaveEventPlugin;

/***/ },
/* 107 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticUIEvent = __webpack_require__(108);
	var ViewportMetrics = __webpack_require__(109);

	var getEventModifierState = __webpack_require__(110);

	/**
	 * @interface MouseEvent
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/
	 */
	var MouseEventInterface = {
	  screenX: null,
	  screenY: null,
	  clientX: null,
	  clientY: null,
	  ctrlKey: null,
	  shiftKey: null,
	  altKey: null,
	  metaKey: null,
	  getModifierState: getEventModifierState,
	  button: function (event) {
	    // Webkit, Firefox, IE9+
	    // which:  1 2 3
	    // button: 0 1 2 (standard)
	    var button = event.button;
	    if ('which' in event) {
	      return button;
	    }
	    // IE<9
	    // which:  undefined
	    // button: 0 0 0
	    // button: 1 4 2 (onmouseup)
	    return button === 2 ? 2 : button === 4 ? 1 : 0;
	  },
	  buttons: null,
	  relatedTarget: function (event) {
	    return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);
	  },
	  // "Proprietary" Interface.
	  pageX: function (event) {
	    return 'pageX' in event ? event.pageX : event.clientX + ViewportMetrics.currentScrollLeft;
	  },
	  pageY: function (event) {
	    return 'pageY' in event ? event.pageY : event.clientY + ViewportMetrics.currentScrollTop;
	  }
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);

	module.exports = SyntheticMouseEvent;

/***/ },
/* 108 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticEvent = __webpack_require__(85);

	var getEventTarget = __webpack_require__(102);

	/**
	 * @interface UIEvent
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/
	 */
	var UIEventInterface = {
	  view: function (event) {
	    if (event.view) {
	      return event.view;
	    }

	    var target = getEventTarget(event);
	    if (target.window === target) {
	      // target is a window object
	      return target;
	    }

	    var doc = target.ownerDocument;
	    // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
	    if (doc) {
	      return doc.defaultView || doc.parentWindow;
	    } else {
	      return window;
	    }
	  },
	  detail: function (event) {
	    return event.detail || 0;
	  }
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticEvent}
	 */
	function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);

	module.exports = SyntheticUIEvent;

/***/ },
/* 109 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ViewportMetrics = {
	  currentScrollLeft: 0,

	  currentScrollTop: 0,

	  refreshScrollValues: function (scrollPosition) {
	    ViewportMetrics.currentScrollLeft = scrollPosition.x;
	    ViewportMetrics.currentScrollTop = scrollPosition.y;
	  }
	};

	module.exports = ViewportMetrics;

/***/ },
/* 110 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * Translation from modifier key to the associated property in the event.
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
	 */

	var modifierKeyToProp = {
	  Alt: 'altKey',
	  Control: 'ctrlKey',
	  Meta: 'metaKey',
	  Shift: 'shiftKey'
	};

	// IE8 does not implement getModifierState so we simply map it to the only
	// modifier keys exposed by the event itself, does not support Lock-keys.
	// Currently, all major browsers except Chrome seems to support Lock-keys.
	function modifierStateGetter(keyArg) {
	  var syntheticEvent = this;
	  var nativeEvent = syntheticEvent.nativeEvent;
	  if (nativeEvent.getModifierState) {
	    return nativeEvent.getModifierState(keyArg);
	  }
	  var keyProp = modifierKeyToProp[keyArg];
	  return keyProp ? !!nativeEvent[keyProp] : false;
	}

	function getEventModifierState(nativeEvent) {
	  return modifierStateGetter;
	}

	module.exports = getEventModifierState;

/***/ },
/* 111 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMProperty = __webpack_require__(68);

	var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;
	var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;
	var HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;
	var HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;
	var HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;

	var HTMLDOMPropertyConfig = {
	  isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')),
	  Properties: {
	    /**
	     * Standard Properties
	     */
	    accept: 0,
	    acceptCharset: 0,
	    accessKey: 0,
	    action: 0,
	    allowFullScreen: HAS_BOOLEAN_VALUE,
	    allowTransparency: 0,
	    alt: 0,
	    // specifies target context for links with `preload` type
	    as: 0,
	    async: HAS_BOOLEAN_VALUE,
	    autoComplete: 0,
	    // autoFocus is polyfilled/normalized by AutoFocusUtils
	    // autoFocus: HAS_BOOLEAN_VALUE,
	    autoPlay: HAS_BOOLEAN_VALUE,
	    capture: HAS_BOOLEAN_VALUE,
	    cellPadding: 0,
	    cellSpacing: 0,
	    charSet: 0,
	    challenge: 0,
	    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
	    cite: 0,
	    classID: 0,
	    className: 0,
	    cols: HAS_POSITIVE_NUMERIC_VALUE,
	    colSpan: 0,
	    content: 0,
	    contentEditable: 0,
	    contextMenu: 0,
	    controls: HAS_BOOLEAN_VALUE,
	    controlsList: 0,
	    coords: 0,
	    crossOrigin: 0,
	    data: 0, // For `<object />` acts as `src`.
	    dateTime: 0,
	    'default': HAS_BOOLEAN_VALUE,
	    defer: HAS_BOOLEAN_VALUE,
	    dir: 0,
	    disabled: HAS_BOOLEAN_VALUE,
	    download: HAS_OVERLOADED_BOOLEAN_VALUE,
	    draggable: 0,
	    encType: 0,
	    form: 0,
	    formAction: 0,
	    formEncType: 0,
	    formMethod: 0,
	    formNoValidate: HAS_BOOLEAN_VALUE,
	    formTarget: 0,
	    frameBorder: 0,
	    headers: 0,
	    height: 0,
	    hidden: HAS_BOOLEAN_VALUE,
	    high: 0,
	    href: 0,
	    hrefLang: 0,
	    htmlFor: 0,
	    httpEquiv: 0,
	    icon: 0,
	    id: 0,
	    inputMode: 0,
	    integrity: 0,
	    is: 0,
	    keyParams: 0,
	    keyType: 0,
	    kind: 0,
	    label: 0,
	    lang: 0,
	    list: 0,
	    loop: HAS_BOOLEAN_VALUE,
	    low: 0,
	    manifest: 0,
	    marginHeight: 0,
	    marginWidth: 0,
	    max: 0,
	    maxLength: 0,
	    media: 0,
	    mediaGroup: 0,
	    method: 0,
	    min: 0,
	    minLength: 0,
	    // Caution; `option.selected` is not updated if `select.multiple` is
	    // disabled with `removeAttribute`.
	    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
	    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
	    name: 0,
	    nonce: 0,
	    noValidate: HAS_BOOLEAN_VALUE,
	    open: HAS_BOOLEAN_VALUE,
	    optimum: 0,
	    pattern: 0,
	    placeholder: 0,
	    playsInline: HAS_BOOLEAN_VALUE,
	    poster: 0,
	    preload: 0,
	    profile: 0,
	    radioGroup: 0,
	    readOnly: HAS_BOOLEAN_VALUE,
	    referrerPolicy: 0,
	    rel: 0,
	    required: HAS_BOOLEAN_VALUE,
	    reversed: HAS_BOOLEAN_VALUE,
	    role: 0,
	    rows: HAS_POSITIVE_NUMERIC_VALUE,
	    rowSpan: HAS_NUMERIC_VALUE,
	    sandbox: 0,
	    scope: 0,
	    scoped: HAS_BOOLEAN_VALUE,
	    scrolling: 0,
	    seamless: HAS_BOOLEAN_VALUE,
	    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
	    shape: 0,
	    size: HAS_POSITIVE_NUMERIC_VALUE,
	    sizes: 0,
	    span: HAS_POSITIVE_NUMERIC_VALUE,
	    spellCheck: 0,
	    src: 0,
	    srcDoc: 0,
	    srcLang: 0,
	    srcSet: 0,
	    start: HAS_NUMERIC_VALUE,
	    step: 0,
	    style: 0,
	    summary: 0,
	    tabIndex: 0,
	    target: 0,
	    title: 0,
	    // Setting .type throws on non-<input> tags
	    type: 0,
	    useMap: 0,
	    value: 0,
	    width: 0,
	    wmode: 0,
	    wrap: 0,

	    /**
	     * RDFa Properties
	     */
	    about: 0,
	    datatype: 0,
	    inlist: 0,
	    prefix: 0,
	    // property is also supported for OpenGraph in meta tags.
	    property: 0,
	    resource: 0,
	    'typeof': 0,
	    vocab: 0,

	    /**
	     * Non-standard Properties
	     */
	    // autoCapitalize and autoCorrect are supported in Mobile Safari for
	    // keyboard hints.
	    autoCapitalize: 0,
	    autoCorrect: 0,
	    // autoSave allows WebKit/Blink to persist values of input fields on page reloads
	    autoSave: 0,
	    // color is for Safari mask-icon link
	    color: 0,
	    // itemProp, itemScope, itemType are for
	    // Microdata support. See http://schema.org/docs/gs.html
	    itemProp: 0,
	    itemScope: HAS_BOOLEAN_VALUE,
	    itemType: 0,
	    // itemID and itemRef are for Microdata support as well but
	    // only specified in the WHATWG spec document. See
	    // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api
	    itemID: 0,
	    itemRef: 0,
	    // results show looking glass icon and recent searches on input
	    // search fields in WebKit/Blink
	    results: 0,
	    // IE-only attribute that specifies security restrictions on an iframe
	    // as an alternative to the sandbox attribute on IE<10
	    security: 0,
	    // IE-only attribute that controls focus behavior
	    unselectable: 0
	  },
	  DOMAttributeNames: {
	    acceptCharset: 'accept-charset',
	    className: 'class',
	    htmlFor: 'for',
	    httpEquiv: 'http-equiv'
	  },
	  DOMPropertyNames: {},
	  DOMMutationMethods: {
	    value: function (node, value) {
	      if (value == null) {
	        return node.removeAttribute('value');
	      }

	      // Number inputs get special treatment due to some edge cases in
	      // Chrome. Let everything else assign the value attribute as normal.
	      // https://github.com/facebook/react/issues/7253#issuecomment-236074326
	      if (node.type !== 'number' || node.hasAttribute('value') === false) {
	        node.setAttribute('value', '' + value);
	      } else if (node.validity && !node.validity.badInput && node.ownerDocument.activeElement !== node) {
	        // Don't assign an attribute if validation reports bad
	        // input. Chrome will clear the value. Additionally, don't
	        // operate on inputs that have focus, otherwise Chrome might
	        // strip off trailing decimal places and cause the user's
	        // cursor position to jump to the beginning of the input.
	        //
	        // In ReactDOMInput, we have an onBlur event that will trigger
	        // this function again when focus is lost.
	        node.setAttribute('value', '' + value);
	      }
	    }
	  }
	};

	module.exports = HTMLDOMPropertyConfig;

/***/ },
/* 112 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMChildrenOperations = __webpack_require__(113);
	var ReactDOMIDOperations = __webpack_require__(124);

	/**
	 * Abstracts away all functionality of the reconciler that requires knowledge of
	 * the browser context. TODO: These callers should be refactored to avoid the
	 * need for this injection.
	 */
	var ReactComponentBrowserEnvironment = {
	  processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,

	  replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup
	};

	module.exports = ReactComponentBrowserEnvironment;

/***/ },
/* 113 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMLazyTree = __webpack_require__(114);
	var Danger = __webpack_require__(120);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactInstrumentation = __webpack_require__(94);

	var createMicrosoftUnsafeLocalFunction = __webpack_require__(117);
	var setInnerHTML = __webpack_require__(116);
	var setTextContent = __webpack_require__(118);

	function getNodeAfter(parentNode, node) {
	  // Special case for text components, which return [open, close] comments
	  // from getHostNode.
	  if (Array.isArray(node)) {
	    node = node[1];
	  }
	  return node ? node.nextSibling : parentNode.firstChild;
	}

	/**
	 * Inserts `childNode` as a child of `parentNode` at the `index`.
	 *
	 * @param {DOMElement} parentNode Parent node in which to insert.
	 * @param {DOMElement} childNode Child node to insert.
	 * @param {number} index Index at which to insert the child.
	 * @internal
	 */
	var insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) {
	  // We rely exclusively on `insertBefore(node, null)` instead of also using
	  // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so
	  // we are careful to use `null`.)
	  parentNode.insertBefore(childNode, referenceNode);
	});

	function insertLazyTreeChildAt(parentNode, childTree, referenceNode) {
	  DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);
	}

	function moveChild(parentNode, childNode, referenceNode) {
	  if (Array.isArray(childNode)) {
	    moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);
	  } else {
	    insertChildAt(parentNode, childNode, referenceNode);
	  }
	}

	function removeChild(parentNode, childNode) {
	  if (Array.isArray(childNode)) {
	    var closingComment = childNode[1];
	    childNode = childNode[0];
	    removeDelimitedText(parentNode, childNode, closingComment);
	    parentNode.removeChild(closingComment);
	  }
	  parentNode.removeChild(childNode);
	}

	function moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) {
	  var node = openingComment;
	  while (true) {
	    var nextNode = node.nextSibling;
	    insertChildAt(parentNode, node, referenceNode);
	    if (node === closingComment) {
	      break;
	    }
	    node = nextNode;
	  }
	}

	function removeDelimitedText(parentNode, startNode, closingComment) {
	  while (true) {
	    var node = startNode.nextSibling;
	    if (node === closingComment) {
	      // The closing comment is removed by ReactMultiChild.
	      break;
	    } else {
	      parentNode.removeChild(node);
	    }
	  }
	}

	function replaceDelimitedText(openingComment, closingComment, stringText) {
	  var parentNode = openingComment.parentNode;
	  var nodeAfterComment = openingComment.nextSibling;
	  if (nodeAfterComment === closingComment) {
	    // There are no text nodes between the opening and closing comments; insert
	    // a new one if stringText isn't empty.
	    if (stringText) {
	      insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment);
	    }
	  } else {
	    if (stringText) {
	      // Set the text content of the first node after the opening comment, and
	      // remove all following nodes up until the closing comment.
	      setTextContent(nodeAfterComment, stringText);
	      removeDelimitedText(parentNode, nodeAfterComment, closingComment);
	    } else {
	      removeDelimitedText(parentNode, openingComment, closingComment);
	    }
	  }

	  if (process.env.NODE_ENV !== 'production') {
	    ReactInstrumentation.debugTool.onHostOperation({
	      instanceID: ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID,
	      type: 'replace text',
	      payload: stringText
	    });
	  }
	}

	var dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup;
	if (process.env.NODE_ENV !== 'production') {
	  dangerouslyReplaceNodeWithMarkup = function (oldChild, markup, prevInstance) {
	    Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup);
	    if (prevInstance._debugID !== 0) {
	      ReactInstrumentation.debugTool.onHostOperation({
	        instanceID: prevInstance._debugID,
	        type: 'replace with',
	        payload: markup.toString()
	      });
	    } else {
	      var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node);
	      if (nextInstance._debugID !== 0) {
	        ReactInstrumentation.debugTool.onHostOperation({
	          instanceID: nextInstance._debugID,
	          type: 'mount',
	          payload: markup.toString()
	        });
	      }
	    }
	  };
	}

	/**
	 * Operations for updating with DOM children.
	 */
	var DOMChildrenOperations = {
	  dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,

	  replaceDelimitedText: replaceDelimitedText,

	  /**
	   * Updates a component's children by processing a series of updates. The
	   * update configurations are each expected to have a `parentNode` property.
	   *
	   * @param {array<object>} updates List of update configurations.
	   * @internal
	   */
	  processUpdates: function (parentNode, updates) {
	    if (process.env.NODE_ENV !== 'production') {
	      var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID;
	    }

	    for (var k = 0; k < updates.length; k++) {
	      var update = updates[k];
	      switch (update.type) {
	        case 'INSERT_MARKUP':
	          insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode));
	          if (process.env.NODE_ENV !== 'production') {
	            ReactInstrumentation.debugTool.onHostOperation({
	              instanceID: parentNodeDebugID,
	              type: 'insert child',
	              payload: {
	                toIndex: update.toIndex,
	                content: update.content.toString()
	              }
	            });
	          }
	          break;
	        case 'MOVE_EXISTING':
	          moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode));
	          if (process.env.NODE_ENV !== 'production') {
	            ReactInstrumentation.debugTool.onHostOperation({
	              instanceID: parentNodeDebugID,
	              type: 'move child',
	              payload: { fromIndex: update.fromIndex, toIndex: update.toIndex }
	            });
	          }
	          break;
	        case 'SET_MARKUP':
	          setInnerHTML(parentNode, update.content);
	          if (process.env.NODE_ENV !== 'production') {
	            ReactInstrumentation.debugTool.onHostOperation({
	              instanceID: parentNodeDebugID,
	              type: 'replace children',
	              payload: update.content.toString()
	            });
	          }
	          break;
	        case 'TEXT_CONTENT':
	          setTextContent(parentNode, update.content);
	          if (process.env.NODE_ENV !== 'production') {
	            ReactInstrumentation.debugTool.onHostOperation({
	              instanceID: parentNodeDebugID,
	              type: 'replace text',
	              payload: update.content.toString()
	            });
	          }
	          break;
	        case 'REMOVE_NODE':
	          removeChild(parentNode, update.fromNode);
	          if (process.env.NODE_ENV !== 'production') {
	            ReactInstrumentation.debugTool.onHostOperation({
	              instanceID: parentNodeDebugID,
	              type: 'remove child',
	              payload: { fromIndex: update.fromIndex }
	            });
	          }
	          break;
	      }
	    }
	  }
	};

	module.exports = DOMChildrenOperations;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 114 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2015-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMNamespaces = __webpack_require__(115);
	var setInnerHTML = __webpack_require__(116);

	var createMicrosoftUnsafeLocalFunction = __webpack_require__(117);
	var setTextContent = __webpack_require__(118);

	var ELEMENT_NODE_TYPE = 1;
	var DOCUMENT_FRAGMENT_NODE_TYPE = 11;

	/**
	 * In IE (8-11) and Edge, appending nodes with no children is dramatically
	 * faster than appending a full subtree, so we essentially queue up the
	 * .appendChild calls here and apply them so each node is added to its parent
	 * before any children are added.
	 *
	 * In other browsers, doing so is slower or neutral compared to the other order
	 * (in Firefox, twice as slow) so we only do this inversion in IE.
	 *
	 * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.
	 */
	var enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\bEdge\/\d/.test(navigator.userAgent);

	function insertTreeChildren(tree) {
	  if (!enableLazy) {
	    return;
	  }
	  var node = tree.node;
	  var children = tree.children;
	  if (children.length) {
	    for (var i = 0; i < children.length; i++) {
	      insertTreeBefore(node, children[i], null);
	    }
	  } else if (tree.html != null) {
	    setInnerHTML(node, tree.html);
	  } else if (tree.text != null) {
	    setTextContent(node, tree.text);
	  }
	}

	var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {
	  // DocumentFragments aren't actually part of the DOM after insertion so
	  // appending children won't update the DOM. We need to ensure the fragment
	  // is properly populated first, breaking out of our lazy approach for just
	  // this level. Also, some <object> plugins (like Flash Player) will read
	  // <param> nodes immediately upon insertion into the DOM, so <object>
	  // must also be populated prior to insertion into the DOM.
	  if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) {
	    insertTreeChildren(tree);
	    parentNode.insertBefore(tree.node, referenceNode);
	  } else {
	    parentNode.insertBefore(tree.node, referenceNode);
	    insertTreeChildren(tree);
	  }
	});

	function replaceChildWithTree(oldNode, newTree) {
	  oldNode.parentNode.replaceChild(newTree.node, oldNode);
	  insertTreeChildren(newTree);
	}

	function queueChild(parentTree, childTree) {
	  if (enableLazy) {
	    parentTree.children.push(childTree);
	  } else {
	    parentTree.node.appendChild(childTree.node);
	  }
	}

	function queueHTML(tree, html) {
	  if (enableLazy) {
	    tree.html = html;
	  } else {
	    setInnerHTML(tree.node, html);
	  }
	}

	function queueText(tree, text) {
	  if (enableLazy) {
	    tree.text = text;
	  } else {
	    setTextContent(tree.node, text);
	  }
	}

	function toString() {
	  return this.node.nodeName;
	}

	function DOMLazyTree(node) {
	  return {
	    node: node,
	    children: [],
	    html: null,
	    text: null,
	    toString: toString
	  };
	}

	DOMLazyTree.insertTreeBefore = insertTreeBefore;
	DOMLazyTree.replaceChildWithTree = replaceChildWithTree;
	DOMLazyTree.queueChild = queueChild;
	DOMLazyTree.queueHTML = queueHTML;
	DOMLazyTree.queueText = queueText;

	module.exports = DOMLazyTree;

/***/ },
/* 115 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMNamespaces = {
	  html: 'http://www.w3.org/1999/xhtml',
	  mathml: 'http://www.w3.org/1998/Math/MathML',
	  svg: 'http://www.w3.org/2000/svg'
	};

	module.exports = DOMNamespaces;

/***/ },
/* 116 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ExecutionEnvironment = __webpack_require__(80);
	var DOMNamespaces = __webpack_require__(115);

	var WHITESPACE_TEST = /^[ \r\n\t\f]/;
	var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;

	var createMicrosoftUnsafeLocalFunction = __webpack_require__(117);

	// SVG temp container for IE lacking innerHTML
	var reusableSVGContainer;

	/**
	 * Set the innerHTML property of a node, ensuring that whitespace is preserved
	 * even in IE8.
	 *
	 * @param {DOMElement} node
	 * @param {string} html
	 * @internal
	 */
	var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
	  // IE does not have innerHTML for SVG nodes, so instead we inject the
	  // new markup in a temp node and then move the child nodes across into
	  // the target node
	  if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {
	    reusableSVGContainer = reusableSVGContainer || document.createElement('div');
	    reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
	    var svgNode = reusableSVGContainer.firstChild;
	    while (svgNode.firstChild) {
	      node.appendChild(svgNode.firstChild);
	    }
	  } else {
	    node.innerHTML = html;
	  }
	});

	if (ExecutionEnvironment.canUseDOM) {
	  // IE8: When updating a just created node with innerHTML only leading
	  // whitespace is removed. When updating an existing node with innerHTML
	  // whitespace in root TextNodes is also collapsed.
	  // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html

	  // Feature detection; only IE8 is known to behave improperly like this.
	  var testElement = document.createElement('div');
	  testElement.innerHTML = ' ';
	  if (testElement.innerHTML === '') {
	    setInnerHTML = function (node, html) {
	      // Magic theory: IE8 supposedly differentiates between added and updated
	      // nodes when processing innerHTML, innerHTML on updated nodes suffers
	      // from worse whitespace behavior. Re-adding a node like this triggers
	      // the initial and more favorable whitespace behavior.
	      // TODO: What to do on a detached node?
	      if (node.parentNode) {
	        node.parentNode.replaceChild(node, node);
	      }

	      // We also implement a workaround for non-visible tags disappearing into
	      // thin air on IE8, this only happens if there is no visible text
	      // in-front of the non-visible tags. Piggyback on the whitespace fix
	      // and simply check if any non-visible tags appear in the source.
	      if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {
	        // Recover leading whitespace by temporarily prepending any character.
	        // \uFEFF has the potential advantage of being zero-width/invisible.
	        // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode
	        // in hopes that this is preserved even if "\uFEFF" is transformed to
	        // the actual Unicode character (by Babel, for example).
	        // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216
	        node.innerHTML = String.fromCharCode(0xfeff) + html;

	        // deleteData leaves an empty `TextNode` which offsets the index of all
	        // children. Definitely want to avoid this.
	        var textNode = node.firstChild;
	        if (textNode.data.length === 1) {
	          node.removeChild(textNode);
	        } else {
	          textNode.deleteData(0, 1);
	        }
	      } else {
	        node.innerHTML = html;
	      }
	    };
	  }
	  testElement = null;
	}

	module.exports = setInnerHTML;

/***/ },
/* 117 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	/* globals MSApp */

	'use strict';

	/**
	 * Create a function which has 'unsafe' privileges (required by windows8 apps)
	 */

	var createMicrosoftUnsafeLocalFunction = function (func) {
	  if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
	    return function (arg0, arg1, arg2, arg3) {
	      MSApp.execUnsafeLocalFunction(function () {
	        return func(arg0, arg1, arg2, arg3);
	      });
	    };
	  } else {
	    return func;
	  }
	};

	module.exports = createMicrosoftUnsafeLocalFunction;

/***/ },
/* 118 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ExecutionEnvironment = __webpack_require__(80);
	var escapeTextContentForBrowser = __webpack_require__(119);
	var setInnerHTML = __webpack_require__(116);

	/**
	 * Set the textContent property of a node, ensuring that whitespace is preserved
	 * even in IE8. innerText is a poor substitute for textContent and, among many
	 * issues, inserts <br> instead of the literal newline chars. innerHTML behaves
	 * as it should.
	 *
	 * @param {DOMElement} node
	 * @param {string} text
	 * @internal
	 */
	var setTextContent = function (node, text) {
	  if (text) {
	    var firstChild = node.firstChild;

	    if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {
	      firstChild.nodeValue = text;
	      return;
	    }
	  }
	  node.textContent = text;
	};

	if (ExecutionEnvironment.canUseDOM) {
	  if (!('textContent' in document.documentElement)) {
	    setTextContent = function (node, text) {
	      if (node.nodeType === 3) {
	        node.nodeValue = text;
	        return;
	      }
	      setInnerHTML(node, escapeTextContentForBrowser(text));
	    };
	  }
	}

	module.exports = setTextContent;

/***/ },
/* 119 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2016-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * Based on the escape-html library, which is used under the MIT License below:
	 *
	 * Copyright (c) 2012-2013 TJ Holowaychuk
	 * Copyright (c) 2015 Andreas Lubbe
	 * Copyright (c) 2015 Tiancheng "Timothy" Gu
	 *
	 * Permission is hereby granted, free of charge, to any person obtaining
	 * a copy of this software and associated documentation files (the
	 * 'Software'), to deal in the Software without restriction, including
	 * without limitation the rights to use, copy, modify, merge, publish,
	 * distribute, sublicense, and/or sell copies of the Software, and to
	 * permit persons to whom the Software is furnished to do so, subject to
	 * the following conditions:
	 *
	 * The above copyright notice and this permission notice shall be
	 * included in all copies or substantial portions of the Software.
	 *
	 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
	 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
	 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
	 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
	 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
	 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
	 *
	 */

	'use strict';

	// code copied and modified from escape-html
	/**
	 * Module variables.
	 * @private
	 */

	var matchHtmlRegExp = /["'&<>]/;

	/**
	 * Escape special characters in the given string of html.
	 *
	 * @param  {string} string The string to escape for inserting into HTML
	 * @return {string}
	 * @public
	 */

	function escapeHtml(string) {
	  var str = '' + string;
	  var match = matchHtmlRegExp.exec(str);

	  if (!match) {
	    return str;
	  }

	  var escape;
	  var html = '';
	  var index = 0;
	  var lastIndex = 0;

	  for (index = match.index; index < str.length; index++) {
	    switch (str.charCodeAt(index)) {
	      case 34:
	        // "
	        escape = '&quot;';
	        break;
	      case 38:
	        // &
	        escape = '&amp;';
	        break;
	      case 39:
	        // '
	        escape = '&#x27;'; // modified from escape-html; used to be '&#39'
	        break;
	      case 60:
	        // <
	        escape = '&lt;';
	        break;
	      case 62:
	        // >
	        escape = '&gt;';
	        break;
	      default:
	        continue;
	    }

	    if (lastIndex !== index) {
	      html += str.substring(lastIndex, index);
	    }

	    lastIndex = index + 1;
	    html += escape;
	  }

	  return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
	}
	// end code copied and modified from escape-html

	/**
	 * Escapes text to prevent scripting attacks.
	 *
	 * @param {*} text Text value to escape.
	 * @return {string} An escaped string.
	 */
	function escapeTextContentForBrowser(text) {
	  if (typeof text === 'boolean' || typeof text === 'number') {
	    // this shortcircuit helps perf for types that we know will never have
	    // special characters, especially given that this function is used often
	    // for numeric dom ids.
	    return '' + text;
	  }
	  return escapeHtml(text);
	}

	module.exports = escapeTextContentForBrowser;

/***/ },
/* 120 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var DOMLazyTree = __webpack_require__(114);
	var ExecutionEnvironment = __webpack_require__(80);

	var createNodesFromMarkup = __webpack_require__(121);
	var emptyFunction = __webpack_require__(36);
	var invariant = __webpack_require__(39);

	var Danger = {
	  /**
	   * Replaces a node with a string of markup at its current position within its
	   * parent. The markup must render into a single root node.
	   *
	   * @param {DOMElement} oldChild Child node to replace.
	   * @param {string} markup Markup to render in place of the child node.
	   * @internal
	   */
	  dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) {
	    !ExecutionEnvironment.canUseDOM ? process.env.NODE_ENV !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('56') : void 0;
	    !markup ? process.env.NODE_ENV !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : _prodInvariant('57') : void 0;
	    !(oldChild.nodeName !== 'HTML') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().') : _prodInvariant('58') : void 0;

	    if (typeof markup === 'string') {
	      var newChild = createNodesFromMarkup(markup, emptyFunction)[0];
	      oldChild.parentNode.replaceChild(newChild, oldChild);
	    } else {
	      DOMLazyTree.replaceChildWithTree(oldChild, markup);
	    }
	  }
	};

	module.exports = Danger;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 121 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	/*eslint-disable fb-www/unsafe-html*/

	var ExecutionEnvironment = __webpack_require__(80);

	var createArrayFromMixed = __webpack_require__(122);
	var getMarkupWrap = __webpack_require__(123);
	var invariant = __webpack_require__(39);

	/**
	 * Dummy container used to render all markup.
	 */
	var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;

	/**
	 * Pattern used by `getNodeName`.
	 */
	var nodeNamePattern = /^\s*<(\w+)/;

	/**
	 * Extracts the `nodeName` of the first element in a string of markup.
	 *
	 * @param {string} markup String of markup.
	 * @return {?string} Node name of the supplied markup.
	 */
	function getNodeName(markup) {
	  var nodeNameMatch = markup.match(nodeNamePattern);
	  return nodeNameMatch && nodeNameMatch[1].toLowerCase();
	}

	/**
	 * Creates an array containing the nodes rendered from the supplied markup. The
	 * optionally supplied `handleScript` function will be invoked once for each
	 * <script> element that is rendered. If no `handleScript` function is supplied,
	 * an exception is thrown if any <script> elements are rendered.
	 *
	 * @param {string} markup A string of valid HTML markup.
	 * @param {?function} handleScript Invoked once for each rendered <script>.
	 * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.
	 */
	function createNodesFromMarkup(markup, handleScript) {
	  var node = dummyNode;
	  !!!dummyNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;
	  var nodeName = getNodeName(markup);

	  var wrap = nodeName && getMarkupWrap(nodeName);
	  if (wrap) {
	    node.innerHTML = wrap[1] + markup + wrap[2];

	    var wrapDepth = wrap[0];
	    while (wrapDepth--) {
	      node = node.lastChild;
	    }
	  } else {
	    node.innerHTML = markup;
	  }

	  var scripts = node.getElementsByTagName('script');
	  if (scripts.length) {
	    !handleScript ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;
	    createArrayFromMixed(scripts).forEach(handleScript);
	  }

	  var nodes = Array.from(node.childNodes);
	  while (node.lastChild) {
	    node.removeChild(node.lastChild);
	  }
	  return nodes;
	}

	module.exports = createNodesFromMarkup;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 122 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	var invariant = __webpack_require__(39);

	/**
	 * Convert array-like objects to arrays.
	 *
	 * This API assumes the caller knows the contents of the data type. For less
	 * well defined inputs use createArrayFromMixed.
	 *
	 * @param {object|function|filelist} obj
	 * @return {array}
	 */
	function toArray(obj) {
	  var length = obj.length;

	  // Some browsers builtin objects can report typeof 'function' (e.g. NodeList
	  // in old versions of Safari).
	  !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0;

	  !(typeof length === 'number') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0;

	  !(length === 0 || length - 1 in obj) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0;

	  !(typeof obj.callee !== 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object can\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0;

	  // Old IE doesn't give collections access to hasOwnProperty. Assume inputs
	  // without method will throw during the slice call and skip straight to the
	  // fallback.
	  if (obj.hasOwnProperty) {
	    try {
	      return Array.prototype.slice.call(obj);
	    } catch (e) {
	      // IE < 9 does not support Array#slice on collections objects
	    }
	  }

	  // Fall back to copying key by key. This assumes all keys have a value,
	  // so will not preserve sparsely populated inputs.
	  var ret = Array(length);
	  for (var ii = 0; ii < length; ii++) {
	    ret[ii] = obj[ii];
	  }
	  return ret;
	}

	/**
	 * Perform a heuristic test to determine if an object is "array-like".
	 *
	 *   A monk asked Joshu, a Zen master, "Has a dog Buddha nature?"
	 *   Joshu replied: "Mu."
	 *
	 * This function determines if its argument has "array nature": it returns
	 * true if the argument is an actual array, an `arguments' object, or an
	 * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).
	 *
	 * It will return false for other array-like objects like Filelist.
	 *
	 * @param {*} obj
	 * @return {boolean}
	 */
	function hasArrayNature(obj) {
	  return (
	    // not null/false
	    !!obj && (
	    // arrays are objects, NodeLists are functions in Safari
	    typeof obj == 'object' || typeof obj == 'function') &&
	    // quacks like an array
	    'length' in obj &&
	    // not window
	    !('setInterval' in obj) &&
	    // no DOM node should be considered an array-like
	    // a 'select' element has 'length' and 'item' properties on IE8
	    typeof obj.nodeType != 'number' && (
	    // a real array
	    Array.isArray(obj) ||
	    // arguments
	    'callee' in obj ||
	    // HTMLCollection/NodeList
	    'item' in obj)
	  );
	}

	/**
	 * Ensure that the argument is an array by wrapping it in an array if it is not.
	 * Creates a copy of the argument if it is already an array.
	 *
	 * This is mostly useful idiomatically:
	 *
	 *   var createArrayFromMixed = require('createArrayFromMixed');
	 *
	 *   function takesOneOrMoreThings(things) {
	 *     things = createArrayFromMixed(things);
	 *     ...
	 *   }
	 *
	 * This allows you to treat `things' as an array, but accept scalars in the API.
	 *
	 * If you need to convert an array-like object, like `arguments`, into an array
	 * use toArray instead.
	 *
	 * @param {*} obj
	 * @return {array}
	 */
	function createArrayFromMixed(obj) {
	  if (!hasArrayNature(obj)) {
	    return [obj];
	  } else if (Array.isArray(obj)) {
	    return obj.slice();
	  } else {
	    return toArray(obj);
	  }
	}

	module.exports = createArrayFromMixed;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 123 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	/*eslint-disable fb-www/unsafe-html */

	var ExecutionEnvironment = __webpack_require__(80);

	var invariant = __webpack_require__(39);

	/**
	 * Dummy container used to detect which wraps are necessary.
	 */
	var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;

	/**
	 * Some browsers cannot use `innerHTML` to render certain elements standalone,
	 * so we wrap them, render the wrapped nodes, then extract the desired node.
	 *
	 * In IE8, certain elements cannot render alone, so wrap all elements ('*').
	 */

	var shouldWrap = {};

	var selectWrap = [1, '<select multiple="true">', '</select>'];
	var tableWrap = [1, '<table>', '</table>'];
	var trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];

	var svgWrap = [1, '<svg xmlns="http://www.w3.org/2000/svg">', '</svg>'];

	var markupWrap = {
	  '*': [1, '?<div>', '</div>'],

	  'area': [1, '<map>', '</map>'],
	  'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
	  'legend': [1, '<fieldset>', '</fieldset>'],
	  'param': [1, '<object>', '</object>'],
	  'tr': [2, '<table><tbody>', '</tbody></table>'],

	  'optgroup': selectWrap,
	  'option': selectWrap,

	  'caption': tableWrap,
	  'colgroup': tableWrap,
	  'tbody': tableWrap,
	  'tfoot': tableWrap,
	  'thead': tableWrap,

	  'td': trWrap,
	  'th': trWrap
	};

	// Initialize the SVG elements since we know they'll always need to be wrapped
	// consistently. If they are created inside a <div> they will be initialized in
	// the wrong namespace (and will not display).
	var svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];
	svgElements.forEach(function (nodeName) {
	  markupWrap[nodeName] = svgWrap;
	  shouldWrap[nodeName] = true;
	});

	/**
	 * Gets the markup wrap configuration for the supplied `nodeName`.
	 *
	 * NOTE: This lazily detects which wraps are necessary for the current browser.
	 *
	 * @param {string} nodeName Lowercase `nodeName`.
	 * @return {?array} Markup wrap configuration, if applicable.
	 */
	function getMarkupWrap(nodeName) {
	  !!!dummyNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;
	  if (!markupWrap.hasOwnProperty(nodeName)) {
	    nodeName = '*';
	  }
	  if (!shouldWrap.hasOwnProperty(nodeName)) {
	    if (nodeName === '*') {
	      dummyNode.innerHTML = '<link />';
	    } else {
	      dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';
	    }
	    shouldWrap[nodeName] = !dummyNode.firstChild;
	  }
	  return shouldWrap[nodeName] ? markupWrap[nodeName] : null;
	}

	module.exports = getMarkupWrap;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 124 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMChildrenOperations = __webpack_require__(113);
	var ReactDOMComponentTree = __webpack_require__(66);

	/**
	 * Operations used to process updates to DOM nodes.
	 */
	var ReactDOMIDOperations = {
	  /**
	   * Updates a component's children by processing a series of updates.
	   *
	   * @param {array<object>} updates List of update configurations.
	   * @internal
	   */
	  dangerouslyProcessChildrenUpdates: function (parentInst, updates) {
	    var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);
	    DOMChildrenOperations.processUpdates(node, updates);
	  }
	};

	module.exports = ReactDOMIDOperations;

/***/ },
/* 125 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	/* global hasOwnProperty:true */

	'use strict';

	var _prodInvariant = __webpack_require__(67),
	    _assign = __webpack_require__(31);

	var AutoFocusUtils = __webpack_require__(126);
	var CSSPropertyOperations = __webpack_require__(128);
	var DOMLazyTree = __webpack_require__(114);
	var DOMNamespaces = __webpack_require__(115);
	var DOMProperty = __webpack_require__(68);
	var DOMPropertyOperations = __webpack_require__(136);
	var EventPluginHub = __webpack_require__(74);
	var EventPluginRegistry = __webpack_require__(75);
	var ReactBrowserEventEmitter = __webpack_require__(138);
	var ReactDOMComponentFlags = __webpack_require__(69);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactDOMInput = __webpack_require__(141);
	var ReactDOMOption = __webpack_require__(144);
	var ReactDOMSelect = __webpack_require__(145);
	var ReactDOMTextarea = __webpack_require__(146);
	var ReactInstrumentation = __webpack_require__(94);
	var ReactMultiChild = __webpack_require__(147);
	var ReactServerRenderingTransaction = __webpack_require__(166);

	var emptyFunction = __webpack_require__(36);
	var escapeTextContentForBrowser = __webpack_require__(119);
	var invariant = __webpack_require__(39);
	var isEventSupported = __webpack_require__(103);
	var shallowEqual = __webpack_require__(156);
	var inputValueTracking = __webpack_require__(101);
	var validateDOMNesting = __webpack_require__(169);
	var warning = __webpack_require__(35);

	var Flags = ReactDOMComponentFlags;
	var deleteListener = EventPluginHub.deleteListener;
	var getNode = ReactDOMComponentTree.getNodeFromInstance;
	var listenTo = ReactBrowserEventEmitter.listenTo;
	var registrationNameModules = EventPluginRegistry.registrationNameModules;

	// For quickly matching children type, to test if can be treated as content.
	var CONTENT_TYPES = { string: true, number: true };

	var STYLE = 'style';
	var HTML = '__html';
	var RESERVED_PROPS = {
	  children: null,
	  dangerouslySetInnerHTML: null,
	  suppressContentEditableWarning: null
	};

	// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).
	var DOC_FRAGMENT_TYPE = 11;

	function getDeclarationErrorAddendum(internalInstance) {
	  if (internalInstance) {
	    var owner = internalInstance._currentElement._owner || null;
	    if (owner) {
	      var name = owner.getName();
	      if (name) {
	        return ' This DOM node was rendered by `' + name + '`.';
	      }
	    }
	  }
	  return '';
	}

	function friendlyStringify(obj) {
	  if (typeof obj === 'object') {
	    if (Array.isArray(obj)) {
	      return '[' + obj.map(friendlyStringify).join(', ') + ']';
	    } else {
	      var pairs = [];
	      for (var key in obj) {
	        if (Object.prototype.hasOwnProperty.call(obj, key)) {
	          var keyEscaped = /^[a-z$_][\w$_]*$/i.test(key) ? key : JSON.stringify(key);
	          pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));
	        }
	      }
	      return '{' + pairs.join(', ') + '}';
	    }
	  } else if (typeof obj === 'string') {
	    return JSON.stringify(obj);
	  } else if (typeof obj === 'function') {
	    return '[function object]';
	  }
	  // Differs from JSON.stringify in that undefined because undefined and that
	  // inf and nan don't become null
	  return String(obj);
	}

	var styleMutationWarning = {};

	function checkAndWarnForMutatedStyle(style1, style2, component) {
	  if (style1 == null || style2 == null) {
	    return;
	  }
	  if (shallowEqual(style1, style2)) {
	    return;
	  }

	  var componentName = component._tag;
	  var owner = component._currentElement._owner;
	  var ownerName;
	  if (owner) {
	    ownerName = owner.getName();
	  }

	  var hash = ownerName + '|' + componentName;

	  if (styleMutationWarning.hasOwnProperty(hash)) {
	    return;
	  }

	  styleMutationWarning[hash] = true;

	  process.env.NODE_ENV !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;
	}

	/**
	 * @param {object} component
	 * @param {?object} props
	 */
	function assertValidProps(component, props) {
	  if (!props) {
	    return;
	  }
	  // Note the use of `==` which checks for null or undefined.
	  if (voidElementTags[component._tag]) {
	    !(props.children == null && props.dangerouslySetInnerHTML == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : _prodInvariant('137', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : void 0;
	  }
	  if (props.dangerouslySetInnerHTML != null) {
	    !(props.children == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : _prodInvariant('60') : void 0;
	    !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? process.env.NODE_ENV !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : _prodInvariant('61') : void 0;
	  }
	  if (process.env.NODE_ENV !== 'production') {
	    process.env.NODE_ENV !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;
	    process.env.NODE_ENV !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0;
	    process.env.NODE_ENV !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;
	  }
	  !(props.style == null || typeof props.style === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \'em\'}} when using JSX.%s', getDeclarationErrorAddendum(component)) : _prodInvariant('62', getDeclarationErrorAddendum(component)) : void 0;
	}

	function enqueuePutListener(inst, registrationName, listener, transaction) {
	  if (transaction instanceof ReactServerRenderingTransaction) {
	    return;
	  }
	  if (process.env.NODE_ENV !== 'production') {
	    // IE8 has no API for event capturing and the `onScroll` event doesn't
	    // bubble.
	    process.env.NODE_ENV !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), "This browser doesn't support the `onScroll` event") : void 0;
	  }
	  var containerInfo = inst._hostContainerInfo;
	  var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;
	  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
	  listenTo(registrationName, doc);
	  transaction.getReactMountReady().enqueue(putListener, {
	    inst: inst,
	    registrationName: registrationName,
	    listener: listener
	  });
	}

	function putListener() {
	  var listenerToPut = this;
	  EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);
	}

	function inputPostMount() {
	  var inst = this;
	  ReactDOMInput.postMountWrapper(inst);
	}

	function textareaPostMount() {
	  var inst = this;
	  ReactDOMTextarea.postMountWrapper(inst);
	}

	function optionPostMount() {
	  var inst = this;
	  ReactDOMOption.postMountWrapper(inst);
	}

	var setAndValidateContentChildDev = emptyFunction;
	if (process.env.NODE_ENV !== 'production') {
	  setAndValidateContentChildDev = function (content) {
	    var hasExistingContent = this._contentDebugID != null;
	    var debugID = this._debugID;
	    // This ID represents the inlined child that has no backing instance:
	    var contentDebugID = -debugID;

	    if (content == null) {
	      if (hasExistingContent) {
	        ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);
	      }
	      this._contentDebugID = null;
	      return;
	    }

	    validateDOMNesting(null, String(content), this, this._ancestorInfo);
	    this._contentDebugID = contentDebugID;
	    if (hasExistingContent) {
	      ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);
	      ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);
	    } else {
	      ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content, debugID);
	      ReactInstrumentation.debugTool.onMountComponent(contentDebugID);
	      ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);
	    }
	  };
	}

	// There are so many media events, it makes sense to just
	// maintain a list rather than create a `trapBubbledEvent` for each
	var mediaEvents = {
	  topAbort: 'abort',
	  topCanPlay: 'canplay',
	  topCanPlayThrough: 'canplaythrough',
	  topDurationChange: 'durationchange',
	  topEmptied: 'emptied',
	  topEncrypted: 'encrypted',
	  topEnded: 'ended',
	  topError: 'error',
	  topLoadedData: 'loadeddata',
	  topLoadedMetadata: 'loadedmetadata',
	  topLoadStart: 'loadstart',
	  topPause: 'pause',
	  topPlay: 'play',
	  topPlaying: 'playing',
	  topProgress: 'progress',
	  topRateChange: 'ratechange',
	  topSeeked: 'seeked',
	  topSeeking: 'seeking',
	  topStalled: 'stalled',
	  topSuspend: 'suspend',
	  topTimeUpdate: 'timeupdate',
	  topVolumeChange: 'volumechange',
	  topWaiting: 'waiting'
	};

	function trackInputValue() {
	  inputValueTracking.track(this);
	}

	function trapBubbledEventsLocal() {
	  var inst = this;
	  // If a component renders to null or if another component fatals and causes
	  // the state of the tree to be corrupted, `node` here can be null.
	  !inst._rootNodeID ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Must be mounted to trap events') : _prodInvariant('63') : void 0;
	  var node = getNode(inst);
	  !node ? process.env.NODE_ENV !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : _prodInvariant('64') : void 0;

	  switch (inst._tag) {
	    case 'iframe':
	    case 'object':
	      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node)];
	      break;
	    case 'video':
	    case 'audio':
	      inst._wrapperState.listeners = [];
	      // Create listener for each media event
	      for (var event in mediaEvents) {
	        if (mediaEvents.hasOwnProperty(event)) {
	          inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(event, mediaEvents[event], node));
	        }
	      }
	      break;
	    case 'source':
	      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node)];
	      break;
	    case 'img':
	      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node), ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node)];
	      break;
	    case 'form':
	      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topReset', 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent('topSubmit', 'submit', node)];
	      break;
	    case 'input':
	    case 'select':
	    case 'textarea':
	      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topInvalid', 'invalid', node)];
	      break;
	  }
	}

	function postUpdateSelectWrapper() {
	  ReactDOMSelect.postUpdateWrapper(this);
	}

	// For HTML, certain tags should omit their close tag. We keep a whitelist for
	// those special-case tags.

	var omittedCloseTags = {
	  area: true,
	  base: true,
	  br: true,
	  col: true,
	  embed: true,
	  hr: true,
	  img: true,
	  input: true,
	  keygen: true,
	  link: true,
	  meta: true,
	  param: true,
	  source: true,
	  track: true,
	  wbr: true
	  // NOTE: menuitem's close tag should be omitted, but that causes problems.
	};

	var newlineEatingTags = {
	  listing: true,
	  pre: true,
	  textarea: true
	};

	// For HTML, certain tags cannot have children. This has the same purpose as
	// `omittedCloseTags` except that `menuitem` should still have its closing tag.

	var voidElementTags = _assign({
	  menuitem: true
	}, omittedCloseTags);

	// We accept any tag to be rendered but since this gets injected into arbitrary
	// HTML, we want to make sure that it's a safe tag.
	// http://www.w3.org/TR/REC-xml/#NT-Name

	var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
	var validatedTagCache = {};
	var hasOwnProperty = {}.hasOwnProperty;

	function validateDangerousTag(tag) {
	  if (!hasOwnProperty.call(validatedTagCache, tag)) {
	    !VALID_TAG_REGEX.test(tag) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : _prodInvariant('65', tag) : void 0;
	    validatedTagCache[tag] = true;
	  }
	}

	function isCustomComponent(tagName, props) {
	  return tagName.indexOf('-') >= 0 || props.is != null;
	}

	var globalIdCounter = 1;

	/**
	 * Creates a new React class that is idempotent and capable of containing other
	 * React components. It accepts event listeners and DOM properties that are
	 * valid according to `DOMProperty`.
	 *
	 *  - Event listeners: `onClick`, `onMouseDown`, etc.
	 *  - DOM properties: `className`, `name`, `title`, etc.
	 *
	 * The `style` property functions differently from the DOM API. It accepts an
	 * object mapping of style properties to values.
	 *
	 * @constructor ReactDOMComponent
	 * @extends ReactMultiChild
	 */
	function ReactDOMComponent(element) {
	  var tag = element.type;
	  validateDangerousTag(tag);
	  this._currentElement = element;
	  this._tag = tag.toLowerCase();
	  this._namespaceURI = null;
	  this._renderedChildren = null;
	  this._previousStyle = null;
	  this._previousStyleCopy = null;
	  this._hostNode = null;
	  this._hostParent = null;
	  this._rootNodeID = 0;
	  this._domID = 0;
	  this._hostContainerInfo = null;
	  this._wrapperState = null;
	  this._topLevelWrapper = null;
	  this._flags = 0;
	  if (process.env.NODE_ENV !== 'production') {
	    this._ancestorInfo = null;
	    setAndValidateContentChildDev.call(this, null);
	  }
	}

	ReactDOMComponent.displayName = 'ReactDOMComponent';

	ReactDOMComponent.Mixin = {
	  /**
	   * Generates root tag markup then recurses. This method has side effects and
	   * is not idempotent.
	   *
	   * @internal
	   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
	   * @param {?ReactDOMComponent} the parent component instance
	   * @param {?object} info about the host container
	   * @param {object} context
	   * @return {string} The computed markup.
	   */
	  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
	    this._rootNodeID = globalIdCounter++;
	    this._domID = hostContainerInfo._idCounter++;
	    this._hostParent = hostParent;
	    this._hostContainerInfo = hostContainerInfo;

	    var props = this._currentElement.props;

	    switch (this._tag) {
	      case 'audio':
	      case 'form':
	      case 'iframe':
	      case 'img':
	      case 'link':
	      case 'object':
	      case 'source':
	      case 'video':
	        this._wrapperState = {
	          listeners: null
	        };
	        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
	        break;
	      case 'input':
	        ReactDOMInput.mountWrapper(this, props, hostParent);
	        props = ReactDOMInput.getHostProps(this, props);
	        transaction.getReactMountReady().enqueue(trackInputValue, this);
	        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
	        break;
	      case 'option':
	        ReactDOMOption.mountWrapper(this, props, hostParent);
	        props = ReactDOMOption.getHostProps(this, props);
	        break;
	      case 'select':
	        ReactDOMSelect.mountWrapper(this, props, hostParent);
	        props = ReactDOMSelect.getHostProps(this, props);
	        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
	        break;
	      case 'textarea':
	        ReactDOMTextarea.mountWrapper(this, props, hostParent);
	        props = ReactDOMTextarea.getHostProps(this, props);
	        transaction.getReactMountReady().enqueue(trackInputValue, this);
	        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
	        break;
	    }

	    assertValidProps(this, props);

	    // We create tags in the namespace of their parent container, except HTML
	    // tags get no namespace.
	    var namespaceURI;
	    var parentTag;
	    if (hostParent != null) {
	      namespaceURI = hostParent._namespaceURI;
	      parentTag = hostParent._tag;
	    } else if (hostContainerInfo._tag) {
	      namespaceURI = hostContainerInfo._namespaceURI;
	      parentTag = hostContainerInfo._tag;
	    }
	    if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {
	      namespaceURI = DOMNamespaces.html;
	    }
	    if (namespaceURI === DOMNamespaces.html) {
	      if (this._tag === 'svg') {
	        namespaceURI = DOMNamespaces.svg;
	      } else if (this._tag === 'math') {
	        namespaceURI = DOMNamespaces.mathml;
	      }
	    }
	    this._namespaceURI = namespaceURI;

	    if (process.env.NODE_ENV !== 'production') {
	      var parentInfo;
	      if (hostParent != null) {
	        parentInfo = hostParent._ancestorInfo;
	      } else if (hostContainerInfo._tag) {
	        parentInfo = hostContainerInfo._ancestorInfo;
	      }
	      if (parentInfo) {
	        // parentInfo should always be present except for the top-level
	        // component when server rendering
	        validateDOMNesting(this._tag, null, this, parentInfo);
	      }
	      this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);
	    }

	    var mountImage;
	    if (transaction.useCreateElement) {
	      var ownerDocument = hostContainerInfo._ownerDocument;
	      var el;
	      if (namespaceURI === DOMNamespaces.html) {
	        if (this._tag === 'script') {
	          // Create the script via .innerHTML so its "parser-inserted" flag is
	          // set to true and it does not execute
	          var div = ownerDocument.createElement('div');
	          var type = this._currentElement.type;
	          div.innerHTML = '<' + type + '></' + type + '>';
	          el = div.removeChild(div.firstChild);
	        } else if (props.is) {
	          el = ownerDocument.createElement(this._currentElement.type, props.is);
	        } else {
	          // Separate else branch instead of using `props.is || undefined` above becuase of a Firefox bug.
	          // See discussion in https://github.com/facebook/react/pull/6896
	          // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
	          el = ownerDocument.createElement(this._currentElement.type);
	        }
	      } else {
	        el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);
	      }
	      ReactDOMComponentTree.precacheNode(this, el);
	      this._flags |= Flags.hasCachedChildNodes;
	      if (!this._hostParent) {
	        DOMPropertyOperations.setAttributeForRoot(el);
	      }
	      this._updateDOMProperties(null, props, transaction);
	      var lazyTree = DOMLazyTree(el);
	      this._createInitialChildren(transaction, props, context, lazyTree);
	      mountImage = lazyTree;
	    } else {
	      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
	      var tagContent = this._createContentMarkup(transaction, props, context);
	      if (!tagContent && omittedCloseTags[this._tag]) {
	        mountImage = tagOpen + '/>';
	      } else {
	        mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
	      }
	    }

	    switch (this._tag) {
	      case 'input':
	        transaction.getReactMountReady().enqueue(inputPostMount, this);
	        if (props.autoFocus) {
	          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
	        }
	        break;
	      case 'textarea':
	        transaction.getReactMountReady().enqueue(textareaPostMount, this);
	        if (props.autoFocus) {
	          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
	        }
	        break;
	      case 'select':
	        if (props.autoFocus) {
	          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
	        }
	        break;
	      case 'button':
	        if (props.autoFocus) {
	          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
	        }
	        break;
	      case 'option':
	        transaction.getReactMountReady().enqueue(optionPostMount, this);
	        break;
	    }

	    return mountImage;
	  },

	  /**
	   * Creates markup for the open tag and all attributes.
	   *
	   * This method has side effects because events get registered.
	   *
	   * Iterating over object properties is faster than iterating over arrays.
	   * @see http://jsperf.com/obj-vs-arr-iteration
	   *
	   * @private
	   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
	   * @param {object} props
	   * @return {string} Markup of opening tag.
	   */
	  _createOpenTagMarkupAndPutListeners: function (transaction, props) {
	    var ret = '<' + this._currentElement.type;

	    for (var propKey in props) {
	      if (!props.hasOwnProperty(propKey)) {
	        continue;
	      }
	      var propValue = props[propKey];
	      if (propValue == null) {
	        continue;
	      }
	      if (registrationNameModules.hasOwnProperty(propKey)) {
	        if (propValue) {
	          enqueuePutListener(this, propKey, propValue, transaction);
	        }
	      } else {
	        if (propKey === STYLE) {
	          if (propValue) {
	            if (process.env.NODE_ENV !== 'production') {
	              // See `_updateDOMProperties`. style block
	              this._previousStyle = propValue;
	            }
	            propValue = this._previousStyleCopy = _assign({}, props.style);
	          }
	          propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);
	        }
	        var markup = null;
	        if (this._tag != null && isCustomComponent(this._tag, props)) {
	          if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
	            markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
	          }
	        } else {
	          markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
	        }
	        if (markup) {
	          ret += ' ' + markup;
	        }
	      }
	    }

	    // For static pages, no need to put React ID and checksum. Saves lots of
	    // bytes.
	    if (transaction.renderToStaticMarkup) {
	      return ret;
	    }

	    if (!this._hostParent) {
	      ret += ' ' + DOMPropertyOperations.createMarkupForRoot();
	    }
	    ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);
	    return ret;
	  },

	  /**
	   * Creates markup for the content between the tags.
	   *
	   * @private
	   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
	   * @param {object} props
	   * @param {object} context
	   * @return {string} Content markup.
	   */
	  _createContentMarkup: function (transaction, props, context) {
	    var ret = '';

	    // Intentional use of != to avoid catching zero/false.
	    var innerHTML = props.dangerouslySetInnerHTML;
	    if (innerHTML != null) {
	      if (innerHTML.__html != null) {
	        ret = innerHTML.__html;
	      }
	    } else {
	      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
	      var childrenToUse = contentToUse != null ? null : props.children;
	      if (contentToUse != null) {
	        // TODO: Validate that text is allowed as a child of this node
	        ret = escapeTextContentForBrowser(contentToUse);
	        if (process.env.NODE_ENV !== 'production') {
	          setAndValidateContentChildDev.call(this, contentToUse);
	        }
	      } else if (childrenToUse != null) {
	        var mountImages = this.mountChildren(childrenToUse, transaction, context);
	        ret = mountImages.join('');
	      }
	    }
	    if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
	      // text/html ignores the first character in these tags if it's a newline
	      // Prefer to break application/xml over text/html (for now) by adding
	      // a newline specifically to get eaten by the parser. (Alternately for
	      // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
	      // \r is normalized out by HTMLTextAreaElement#value.)
	      // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
	      // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
	      // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
	      // See: Parsing of "textarea" "listing" and "pre" elements
	      //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
	      return '\n' + ret;
	    } else {
	      return ret;
	    }
	  },

	  _createInitialChildren: function (transaction, props, context, lazyTree) {
	    // Intentional use of != to avoid catching zero/false.
	    var innerHTML = props.dangerouslySetInnerHTML;
	    if (innerHTML != null) {
	      if (innerHTML.__html != null) {
	        DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);
	      }
	    } else {
	      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
	      var childrenToUse = contentToUse != null ? null : props.children;
	      // TODO: Validate that text is allowed as a child of this node
	      if (contentToUse != null) {
	        // Avoid setting textContent when the text is empty. In IE11 setting
	        // textContent on a text area will cause the placeholder to not
	        // show within the textarea until it has been focused and blurred again.
	        // https://github.com/facebook/react/issues/6731#issuecomment-254874553
	        if (contentToUse !== '') {
	          if (process.env.NODE_ENV !== 'production') {
	            setAndValidateContentChildDev.call(this, contentToUse);
	          }
	          DOMLazyTree.queueText(lazyTree, contentToUse);
	        }
	      } else if (childrenToUse != null) {
	        var mountImages = this.mountChildren(childrenToUse, transaction, context);
	        for (var i = 0; i < mountImages.length; i++) {
	          DOMLazyTree.queueChild(lazyTree, mountImages[i]);
	        }
	      }
	    }
	  },

	  /**
	   * Receives a next element and updates the component.
	   *
	   * @internal
	   * @param {ReactElement} nextElement
	   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
	   * @param {object} context
	   */
	  receiveComponent: function (nextElement, transaction, context) {
	    var prevElement = this._currentElement;
	    this._currentElement = nextElement;
	    this.updateComponent(transaction, prevElement, nextElement, context);
	  },

	  /**
	   * Updates a DOM component after it has already been allocated and
	   * attached to the DOM. Reconciles the root DOM node, then recurses.
	   *
	   * @param {ReactReconcileTransaction} transaction
	   * @param {ReactElement} prevElement
	   * @param {ReactElement} nextElement
	   * @internal
	   * @overridable
	   */
	  updateComponent: function (transaction, prevElement, nextElement, context) {
	    var lastProps = prevElement.props;
	    var nextProps = this._currentElement.props;

	    switch (this._tag) {
	      case 'input':
	        lastProps = ReactDOMInput.getHostProps(this, lastProps);
	        nextProps = ReactDOMInput.getHostProps(this, nextProps);
	        break;
	      case 'option':
	        lastProps = ReactDOMOption.getHostProps(this, lastProps);
	        nextProps = ReactDOMOption.getHostProps(this, nextProps);
	        break;
	      case 'select':
	        lastProps = ReactDOMSelect.getHostProps(this, lastProps);
	        nextProps = ReactDOMSelect.getHostProps(this, nextProps);
	        break;
	      case 'textarea':
	        lastProps = ReactDOMTextarea.getHostProps(this, lastProps);
	        nextProps = ReactDOMTextarea.getHostProps(this, nextProps);
	        break;
	    }

	    assertValidProps(this, nextProps);
	    this._updateDOMProperties(lastProps, nextProps, transaction);
	    this._updateDOMChildren(lastProps, nextProps, transaction, context);

	    switch (this._tag) {
	      case 'input':
	        // Update the wrapper around inputs *after* updating props. This has to
	        // happen after `_updateDOMProperties`. Otherwise HTML5 input validations
	        // raise warnings and prevent the new value from being assigned.
	        ReactDOMInput.updateWrapper(this);

	        // We also check that we haven't missed a value update, such as a
	        // Radio group shifting the checked value to another named radio input.
	        inputValueTracking.updateValueIfChanged(this);
	        break;
	      case 'textarea':
	        ReactDOMTextarea.updateWrapper(this);
	        break;
	      case 'select':
	        // <select> value update needs to occur after <option> children
	        // reconciliation
	        transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
	        break;
	    }
	  },

	  /**
	   * Reconciles the properties by detecting differences in property values and
	   * updating the DOM as necessary. This function is probably the single most
	   * critical path for performance optimization.
	   *
	   * TODO: Benchmark whether checking for changed values in memory actually
	   *       improves performance (especially statically positioned elements).
	   * TODO: Benchmark the effects of putting this at the top since 99% of props
	   *       do not change for a given reconciliation.
	   * TODO: Benchmark areas that can be improved with caching.
	   *
	   * @private
	   * @param {object} lastProps
	   * @param {object} nextProps
	   * @param {?DOMElement} node
	   */
	  _updateDOMProperties: function (lastProps, nextProps, transaction) {
	    var propKey;
	    var styleName;
	    var styleUpdates;
	    for (propKey in lastProps) {
	      if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
	        continue;
	      }
	      if (propKey === STYLE) {
	        var lastStyle = this._previousStyleCopy;
	        for (styleName in lastStyle) {
	          if (lastStyle.hasOwnProperty(styleName)) {
	            styleUpdates = styleUpdates || {};
	            styleUpdates[styleName] = '';
	          }
	        }
	        this._previousStyleCopy = null;
	      } else if (registrationNameModules.hasOwnProperty(propKey)) {
	        if (lastProps[propKey]) {
	          // Only call deleteListener if there was a listener previously or
	          // else willDeleteListener gets called when there wasn't actually a
	          // listener (e.g., onClick={null})
	          deleteListener(this, propKey);
	        }
	      } else if (isCustomComponent(this._tag, lastProps)) {
	        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
	          DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);
	        }
	      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
	        DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);
	      }
	    }
	    for (propKey in nextProps) {
	      var nextProp = nextProps[propKey];
	      var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;
	      if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
	        continue;
	      }
	      if (propKey === STYLE) {
	        if (nextProp) {
	          if (process.env.NODE_ENV !== 'production') {
	            checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
	            this._previousStyle = nextProp;
	          }
	          nextProp = this._previousStyleCopy = _assign({}, nextProp);
	        } else {
	          this._previousStyleCopy = null;
	        }
	        if (lastProp) {
	          // Unset styles on `lastProp` but not on `nextProp`.
	          for (styleName in lastProp) {
	            if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
	              styleUpdates = styleUpdates || {};
	              styleUpdates[styleName] = '';
	            }
	          }
	          // Update styles that changed since `lastProp`.
	          for (styleName in nextProp) {
	            if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
	              styleUpdates = styleUpdates || {};
	              styleUpdates[styleName] = nextProp[styleName];
	            }
	          }
	        } else {
	          // Relies on `updateStylesByID` not mutating `styleUpdates`.
	          styleUpdates = nextProp;
	        }
	      } else if (registrationNameModules.hasOwnProperty(propKey)) {
	        if (nextProp) {
	          enqueuePutListener(this, propKey, nextProp, transaction);
	        } else if (lastProp) {
	          deleteListener(this, propKey);
	        }
	      } else if (isCustomComponent(this._tag, nextProps)) {
	        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
	          DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);
	        }
	      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
	        var node = getNode(this);
	        // If we're updating to null or undefined, we should remove the property
	        // from the DOM node instead of inadvertently setting to a string. This
	        // brings us in line with the same behavior we have on initial render.
	        if (nextProp != null) {
	          DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
	        } else {
	          DOMPropertyOperations.deleteValueForProperty(node, propKey);
	        }
	      }
	    }
	    if (styleUpdates) {
	      CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);
	    }
	  },

	  /**
	   * Reconciles the children with the various properties that affect the
	   * children content.
	   *
	   * @param {object} lastProps
	   * @param {object} nextProps
	   * @param {ReactReconcileTransaction} transaction
	   * @param {object} context
	   */
	  _updateDOMChildren: function (lastProps, nextProps, transaction, context) {
	    var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
	    var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;

	    var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;
	    var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;

	    // Note the use of `!=` which checks for null or undefined.
	    var lastChildren = lastContent != null ? null : lastProps.children;
	    var nextChildren = nextContent != null ? null : nextProps.children;

	    // If we're switching from children to content/html or vice versa, remove
	    // the old content
	    var lastHasContentOrHtml = lastContent != null || lastHtml != null;
	    var nextHasContentOrHtml = nextContent != null || nextHtml != null;
	    if (lastChildren != null && nextChildren == null) {
	      this.updateChildren(null, transaction, context);
	    } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
	      this.updateTextContent('');
	      if (process.env.NODE_ENV !== 'production') {
	        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
	      }
	    }

	    if (nextContent != null) {
	      if (lastContent !== nextContent) {
	        this.updateTextContent('' + nextContent);
	        if (process.env.NODE_ENV !== 'production') {
	          setAndValidateContentChildDev.call(this, nextContent);
	        }
	      }
	    } else if (nextHtml != null) {
	      if (lastHtml !== nextHtml) {
	        this.updateMarkup('' + nextHtml);
	      }
	      if (process.env.NODE_ENV !== 'production') {
	        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
	      }
	    } else if (nextChildren != null) {
	      if (process.env.NODE_ENV !== 'production') {
	        setAndValidateContentChildDev.call(this, null);
	      }

	      this.updateChildren(nextChildren, transaction, context);
	    }
	  },

	  getHostNode: function () {
	    return getNode(this);
	  },

	  /**
	   * Destroys all event registrations for this instance. Does not remove from
	   * the DOM. That must be done by the parent.
	   *
	   * @internal
	   */
	  unmountComponent: function (safely) {
	    switch (this._tag) {
	      case 'audio':
	      case 'form':
	      case 'iframe':
	      case 'img':
	      case 'link':
	      case 'object':
	      case 'source':
	      case 'video':
	        var listeners = this._wrapperState.listeners;
	        if (listeners) {
	          for (var i = 0; i < listeners.length; i++) {
	            listeners[i].remove();
	          }
	        }
	        break;
	      case 'input':
	      case 'textarea':
	        inputValueTracking.stopTracking(this);
	        break;
	      case 'html':
	      case 'head':
	      case 'body':
	        /**
	         * Components like <html> <head> and <body> can't be removed or added
	         * easily in a cross-browser way, however it's valuable to be able to
	         * take advantage of React's reconciliation for styling and <title>
	         * management. So we just document it and throw in dangerous cases.
	         */
	         true ? process.env.NODE_ENV !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.', this._tag) : _prodInvariant('66', this._tag) : void 0;
	        break;
	    }

	    this.unmountChildren(safely);
	    ReactDOMComponentTree.uncacheNode(this);
	    EventPluginHub.deleteAllListeners(this);
	    this._rootNodeID = 0;
	    this._domID = 0;
	    this._wrapperState = null;

	    if (process.env.NODE_ENV !== 'production') {
	      setAndValidateContentChildDev.call(this, null);
	    }
	  },

	  getPublicInstance: function () {
	    return getNode(this);
	  }
	};

	_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);

	module.exports = ReactDOMComponent;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 126 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactDOMComponentTree = __webpack_require__(66);

	var focusNode = __webpack_require__(127);

	var AutoFocusUtils = {
	  focusDOMComponent: function () {
	    focusNode(ReactDOMComponentTree.getNodeFromInstance(this));
	  }
	};

	module.exports = AutoFocusUtils;

/***/ },
/* 127 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * @param {DOMElement} node input/textarea to focus
	 */

	function focusNode(node) {
	  // IE8 can throw "Can't move focus to the control because it is invisible,
	  // not enabled, or of a type that does not accept the focus." for all kinds of
	  // reasons that are too expensive and fragile to test.
	  try {
	    node.focus();
	  } catch (e) {}
	}

	module.exports = focusNode;

/***/ },
/* 128 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var CSSProperty = __webpack_require__(129);
	var ExecutionEnvironment = __webpack_require__(80);
	var ReactInstrumentation = __webpack_require__(94);

	var camelizeStyleName = __webpack_require__(130);
	var dangerousStyleValue = __webpack_require__(132);
	var hyphenateStyleName = __webpack_require__(133);
	var memoizeStringOnly = __webpack_require__(135);
	var warning = __webpack_require__(35);

	var processStyleName = memoizeStringOnly(function (styleName) {
	  return hyphenateStyleName(styleName);
	});

	var hasShorthandPropertyBug = false;
	var styleFloatAccessor = 'cssFloat';
	if (ExecutionEnvironment.canUseDOM) {
	  var tempStyle = document.createElement('div').style;
	  try {
	    // IE8 throws "Invalid argument." if resetting shorthand style properties.
	    tempStyle.font = '';
	  } catch (e) {
	    hasShorthandPropertyBug = true;
	  }
	  // IE8 only supports accessing cssFloat (standard) as styleFloat
	  if (document.documentElement.style.cssFloat === undefined) {
	    styleFloatAccessor = 'styleFloat';
	  }
	}

	if (process.env.NODE_ENV !== 'production') {
	  // 'msTransform' is correct, but the other prefixes should be capitalized
	  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;

	  // style values shouldn't contain a semicolon
	  var badStyleValueWithSemicolonPattern = /;\s*$/;

	  var warnedStyleNames = {};
	  var warnedStyleValues = {};
	  var warnedForNaNValue = false;

	  var warnHyphenatedStyleName = function (name, owner) {
	    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
	      return;
	    }

	    warnedStyleNames[name] = true;
	    process.env.NODE_ENV !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0;
	  };

	  var warnBadVendoredStyleName = function (name, owner) {
	    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
	      return;
	    }

	    warnedStyleNames[name] = true;
	    process.env.NODE_ENV !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0;
	  };

	  var warnStyleValueWithSemicolon = function (name, value, owner) {
	    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
	      return;
	    }

	    warnedStyleValues[value] = true;
	    process.env.NODE_ENV !== 'production' ? warning(false, "Style property values shouldn't contain a semicolon.%s " + 'Try "%s: %s" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;
	  };

	  var warnStyleValueIsNaN = function (name, value, owner) {
	    if (warnedForNaNValue) {
	      return;
	    }

	    warnedForNaNValue = true;
	    process.env.NODE_ENV !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0;
	  };

	  var checkRenderMessage = function (owner) {
	    if (owner) {
	      var name = owner.getName();
	      if (name) {
	        return ' Check the render method of `' + name + '`.';
	      }
	    }
	    return '';
	  };

	  /**
	   * @param {string} name
	   * @param {*} value
	   * @param {ReactDOMComponent} component
	   */
	  var warnValidStyle = function (name, value, component) {
	    var owner;
	    if (component) {
	      owner = component._currentElement._owner;
	    }
	    if (name.indexOf('-') > -1) {
	      warnHyphenatedStyleName(name, owner);
	    } else if (badVendoredStyleNamePattern.test(name)) {
	      warnBadVendoredStyleName(name, owner);
	    } else if (badStyleValueWithSemicolonPattern.test(value)) {
	      warnStyleValueWithSemicolon(name, value, owner);
	    }

	    if (typeof value === 'number' && isNaN(value)) {
	      warnStyleValueIsNaN(name, value, owner);
	    }
	  };
	}

	/**
	 * Operations for dealing with CSS properties.
	 */
	var CSSPropertyOperations = {
	  /**
	   * Serializes a mapping of style properties for use as inline styles:
	   *
	   *   > createMarkupForStyles({width: '200px', height: 0})
	   *   "width:200px;height:0;"
	   *
	   * Undefined values are ignored so that declarative programming is easier.
	   * The result should be HTML-escaped before insertion into the DOM.
	   *
	   * @param {object} styles
	   * @param {ReactDOMComponent} component
	   * @return {?string}
	   */
	  createMarkupForStyles: function (styles, component) {
	    var serialized = '';
	    for (var styleName in styles) {
	      if (!styles.hasOwnProperty(styleName)) {
	        continue;
	      }
	      var isCustomProperty = styleName.indexOf('--') === 0;
	      var styleValue = styles[styleName];
	      if (process.env.NODE_ENV !== 'production') {
	        if (!isCustomProperty) {
	          warnValidStyle(styleName, styleValue, component);
	        }
	      }
	      if (styleValue != null) {
	        serialized += processStyleName(styleName) + ':';
	        serialized += dangerousStyleValue(styleName, styleValue, component, isCustomProperty) + ';';
	      }
	    }
	    return serialized || null;
	  },

	  /**
	   * Sets the value for multiple styles on a node.  If a value is specified as
	   * '' (empty string), the corresponding style property will be unset.
	   *
	   * @param {DOMElement} node
	   * @param {object} styles
	   * @param {ReactDOMComponent} component
	   */
	  setValueForStyles: function (node, styles, component) {
	    if (process.env.NODE_ENV !== 'production') {
	      ReactInstrumentation.debugTool.onHostOperation({
	        instanceID: component._debugID,
	        type: 'update styles',
	        payload: styles
	      });
	    }

	    var style = node.style;
	    for (var styleName in styles) {
	      if (!styles.hasOwnProperty(styleName)) {
	        continue;
	      }
	      var isCustomProperty = styleName.indexOf('--') === 0;
	      if (process.env.NODE_ENV !== 'production') {
	        if (!isCustomProperty) {
	          warnValidStyle(styleName, styles[styleName], component);
	        }
	      }
	      var styleValue = dangerousStyleValue(styleName, styles[styleName], component, isCustomProperty);
	      if (styleName === 'float' || styleName === 'cssFloat') {
	        styleName = styleFloatAccessor;
	      }
	      if (isCustomProperty) {
	        style.setProperty(styleName, styleValue);
	      } else if (styleValue) {
	        style[styleName] = styleValue;
	      } else {
	        var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];
	        if (expansion) {
	          // Shorthand property that IE8 won't like unsetting, so unset each
	          // component to placate it
	          for (var individualStyleName in expansion) {
	            style[individualStyleName] = '';
	          }
	        } else {
	          style[styleName] = '';
	        }
	      }
	    }
	  }
	};

	module.exports = CSSPropertyOperations;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 129 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * CSS properties which accept numbers but are not in units of "px".
	 */

	var isUnitlessNumber = {
	  animationIterationCount: true,
	  borderImageOutset: true,
	  borderImageSlice: true,
	  borderImageWidth: true,
	  boxFlex: true,
	  boxFlexGroup: true,
	  boxOrdinalGroup: true,
	  columnCount: true,
	  columns: true,
	  flex: true,
	  flexGrow: true,
	  flexPositive: true,
	  flexShrink: true,
	  flexNegative: true,
	  flexOrder: true,
	  gridRow: true,
	  gridRowEnd: true,
	  gridRowSpan: true,
	  gridRowStart: true,
	  gridColumn: true,
	  gridColumnEnd: true,
	  gridColumnSpan: true,
	  gridColumnStart: true,
	  fontWeight: true,
	  lineClamp: true,
	  lineHeight: true,
	  opacity: true,
	  order: true,
	  orphans: true,
	  tabSize: true,
	  widows: true,
	  zIndex: true,
	  zoom: true,

	  // SVG-related properties
	  fillOpacity: true,
	  floodOpacity: true,
	  stopOpacity: true,
	  strokeDasharray: true,
	  strokeDashoffset: true,
	  strokeMiterlimit: true,
	  strokeOpacity: true,
	  strokeWidth: true
	};

	/**
	 * @param {string} prefix vendor-specific prefix, eg: Webkit
	 * @param {string} key style name, eg: transitionDuration
	 * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
	 * WebkitTransitionDuration
	 */
	function prefixKey(prefix, key) {
	  return prefix + key.charAt(0).toUpperCase() + key.substring(1);
	}

	/**
	 * Support style names that may come passed in prefixed by adding permutations
	 * of vendor prefixes.
	 */
	var prefixes = ['Webkit', 'ms', 'Moz', 'O'];

	// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
	// infinite loop, because it iterates over the newly added props too.
	Object.keys(isUnitlessNumber).forEach(function (prop) {
	  prefixes.forEach(function (prefix) {
	    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
	  });
	});

	/**
	 * Most style properties can be unset by doing .style[prop] = '' but IE8
	 * doesn't like doing that with shorthand properties so for the properties that
	 * IE8 breaks on, which are listed here, we instead unset each of the
	 * individual properties. See http://bugs.jquery.com/ticket/12385.
	 * The 4-value 'clock' properties like margin, padding, border-width seem to
	 * behave without any problems. Curiously, list-style works too without any
	 * special prodding.
	 */
	var shorthandPropertyExpansions = {
	  background: {
	    backgroundAttachment: true,
	    backgroundColor: true,
	    backgroundImage: true,
	    backgroundPositionX: true,
	    backgroundPositionY: true,
	    backgroundRepeat: true
	  },
	  backgroundPosition: {
	    backgroundPositionX: true,
	    backgroundPositionY: true
	  },
	  border: {
	    borderWidth: true,
	    borderStyle: true,
	    borderColor: true
	  },
	  borderBottom: {
	    borderBottomWidth: true,
	    borderBottomStyle: true,
	    borderBottomColor: true
	  },
	  borderLeft: {
	    borderLeftWidth: true,
	    borderLeftStyle: true,
	    borderLeftColor: true
	  },
	  borderRight: {
	    borderRightWidth: true,
	    borderRightStyle: true,
	    borderRightColor: true
	  },
	  borderTop: {
	    borderTopWidth: true,
	    borderTopStyle: true,
	    borderTopColor: true
	  },
	  font: {
	    fontStyle: true,
	    fontVariant: true,
	    fontWeight: true,
	    fontSize: true,
	    lineHeight: true,
	    fontFamily: true
	  },
	  outline: {
	    outlineWidth: true,
	    outlineStyle: true,
	    outlineColor: true
	  }
	};

	var CSSProperty = {
	  isUnitlessNumber: isUnitlessNumber,
	  shorthandPropertyExpansions: shorthandPropertyExpansions
	};

	module.exports = CSSProperty;

/***/ },
/* 130 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	'use strict';

	var camelize = __webpack_require__(131);

	var msPattern = /^-ms-/;

	/**
	 * Camelcases a hyphenated CSS property name, for example:
	 *
	 *   > camelizeStyleName('background-color')
	 *   < "backgroundColor"
	 *   > camelizeStyleName('-moz-transition')
	 *   < "MozTransition"
	 *   > camelizeStyleName('-ms-transition')
	 *   < "msTransition"
	 *
	 * As Andi Smith suggests
	 * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
	 * is converted to lowercase `ms`.
	 *
	 * @param {string} string
	 * @return {string}
	 */
	function camelizeStyleName(string) {
	  return camelize(string.replace(msPattern, 'ms-'));
	}

	module.exports = camelizeStyleName;

/***/ },
/* 131 */
/***/ function(module, exports) {

	"use strict";

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	var _hyphenPattern = /-(.)/g;

	/**
	 * Camelcases a hyphenated string, for example:
	 *
	 *   > camelize('background-color')
	 *   < "backgroundColor"
	 *
	 * @param {string} string
	 * @return {string}
	 */
	function camelize(string) {
	  return string.replace(_hyphenPattern, function (_, character) {
	    return character.toUpperCase();
	  });
	}

	module.exports = camelize;

/***/ },
/* 132 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var CSSProperty = __webpack_require__(129);
	var warning = __webpack_require__(35);

	var isUnitlessNumber = CSSProperty.isUnitlessNumber;
	var styleWarnings = {};

	/**
	 * Convert a value into the proper css writable value. The style name `name`
	 * should be logical (no hyphens), as specified
	 * in `CSSProperty.isUnitlessNumber`.
	 *
	 * @param {string} name CSS property name such as `topMargin`.
	 * @param {*} value CSS property value such as `10px`.
	 * @param {ReactDOMComponent} component
	 * @return {string} Normalized style value with dimensions applied.
	 */
	function dangerousStyleValue(name, value, component, isCustomProperty) {
	  // Note that we've removed escapeTextForBrowser() calls here since the
	  // whole string will be escaped when the attribute is injected into
	  // the markup. If you provide unsafe user data here they can inject
	  // arbitrary CSS which may be problematic (I couldn't repro this):
	  // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
	  // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
	  // This is not an XSS hole but instead a potential CSS injection issue
	  // which has lead to a greater discussion about how we're going to
	  // trust URLs moving forward. See #2115901

	  var isEmpty = value == null || typeof value === 'boolean' || value === '';
	  if (isEmpty) {
	    return '';
	  }

	  var isNonNumeric = isNaN(value);
	  if (isCustomProperty || isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {
	    return '' + value; // cast to string
	  }

	  if (typeof value === 'string') {
	    if (process.env.NODE_ENV !== 'production') {
	      // Allow '0' to pass through without warning. 0 is already special and
	      // doesn't require units, so we don't need to warn about it.
	      if (component && value !== '0') {
	        var owner = component._currentElement._owner;
	        var ownerName = owner ? owner.getName() : null;
	        if (ownerName && !styleWarnings[ownerName]) {
	          styleWarnings[ownerName] = {};
	        }
	        var warned = false;
	        if (ownerName) {
	          var warnings = styleWarnings[ownerName];
	          warned = warnings[name];
	          if (!warned) {
	            warnings[name] = true;
	          }
	        }
	        if (!warned) {
	          process.env.NODE_ENV !== 'production' ? warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' + 'for CSS property `%s` (value: `%s`) which will be treated ' + 'as a unitless number in a future version of React.', component._currentElement.type, ownerName || 'unknown', name, value) : void 0;
	        }
	      }
	    }
	    value = value.trim();
	  }
	  return value + 'px';
	}

	module.exports = dangerousStyleValue;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 133 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	'use strict';

	var hyphenate = __webpack_require__(134);

	var msPattern = /^ms-/;

	/**
	 * Hyphenates a camelcased CSS property name, for example:
	 *
	 *   > hyphenateStyleName('backgroundColor')
	 *   < "background-color"
	 *   > hyphenateStyleName('MozTransition')
	 *   < "-moz-transition"
	 *   > hyphenateStyleName('msTransition')
	 *   < "-ms-transition"
	 *
	 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
	 * is converted to `-ms-`.
	 *
	 * @param {string} string
	 * @return {string}
	 */
	function hyphenateStyleName(string) {
	  return hyphenate(string).replace(msPattern, '-ms-');
	}

	module.exports = hyphenateStyleName;

/***/ },
/* 134 */
/***/ function(module, exports) {

	'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	var _uppercasePattern = /([A-Z])/g;

	/**
	 * Hyphenates a camelcased string, for example:
	 *
	 *   > hyphenate('backgroundColor')
	 *   < "background-color"
	 *
	 * For CSS style names, use `hyphenateStyleName` instead which works properly
	 * with all vendor prefixes, including `ms`.
	 *
	 * @param {string} string
	 * @return {string}
	 */
	function hyphenate(string) {
	  return string.replace(_uppercasePattern, '-$1').toLowerCase();
	}

	module.exports = hyphenate;

/***/ },
/* 135 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 * @typechecks static-only
	 */

	'use strict';

	/**
	 * Memoizes the return value of a function that accepts one string argument.
	 */

	function memoizeStringOnly(callback) {
	  var cache = {};
	  return function (string) {
	    if (!cache.hasOwnProperty(string)) {
	      cache[string] = callback.call(this, string);
	    }
	    return cache[string];
	  };
	}

	module.exports = memoizeStringOnly;

/***/ },
/* 136 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMProperty = __webpack_require__(68);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactInstrumentation = __webpack_require__(94);

	var quoteAttributeValueForBrowser = __webpack_require__(137);
	var warning = __webpack_require__(35);

	var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');
	var illegalAttributeNameCache = {};
	var validatedAttributeNameCache = {};

	function isAttributeNameSafe(attributeName) {
	  if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
	    return true;
	  }
	  if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
	    return false;
	  }
	  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
	    validatedAttributeNameCache[attributeName] = true;
	    return true;
	  }
	  illegalAttributeNameCache[attributeName] = true;
	  process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;
	  return false;
	}

	function shouldIgnoreValue(propertyInfo, value) {
	  return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;
	}

	/**
	 * Operations for dealing with DOM properties.
	 */
	var DOMPropertyOperations = {
	  /**
	   * Creates markup for the ID property.
	   *
	   * @param {string} id Unescaped ID.
	   * @return {string} Markup string.
	   */
	  createMarkupForID: function (id) {
	    return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);
	  },

	  setAttributeForID: function (node, id) {
	    node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);
	  },

	  createMarkupForRoot: function () {
	    return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""';
	  },

	  setAttributeForRoot: function (node) {
	    node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');
	  },

	  /**
	   * Creates markup for a property.
	   *
	   * @param {string} name
	   * @param {*} value
	   * @return {?string} Markup string, or null if the property was invalid.
	   */
	  createMarkupForProperty: function (name, value) {
	    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
	    if (propertyInfo) {
	      if (shouldIgnoreValue(propertyInfo, value)) {
	        return '';
	      }
	      var attributeName = propertyInfo.attributeName;
	      if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
	        return attributeName + '=""';
	      }
	      return attributeName + '=' + quoteAttributeValueForBrowser(value);
	    } else if (DOMProperty.isCustomAttribute(name)) {
	      if (value == null) {
	        return '';
	      }
	      return name + '=' + quoteAttributeValueForBrowser(value);
	    }
	    return null;
	  },

	  /**
	   * Creates markup for a custom property.
	   *
	   * @param {string} name
	   * @param {*} value
	   * @return {string} Markup string, or empty string if the property was invalid.
	   */
	  createMarkupForCustomAttribute: function (name, value) {
	    if (!isAttributeNameSafe(name) || value == null) {
	      return '';
	    }
	    return name + '=' + quoteAttributeValueForBrowser(value);
	  },

	  /**
	   * Sets the value for a property on a node.
	   *
	   * @param {DOMElement} node
	   * @param {string} name
	   * @param {*} value
	   */
	  setValueForProperty: function (node, name, value) {
	    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
	    if (propertyInfo) {
	      var mutationMethod = propertyInfo.mutationMethod;
	      if (mutationMethod) {
	        mutationMethod(node, value);
	      } else if (shouldIgnoreValue(propertyInfo, value)) {
	        this.deleteValueForProperty(node, name);
	        return;
	      } else if (propertyInfo.mustUseProperty) {
	        // Contrary to `setAttribute`, object properties are properly
	        // `toString`ed by IE8/9.
	        node[propertyInfo.propertyName] = value;
	      } else {
	        var attributeName = propertyInfo.attributeName;
	        var namespace = propertyInfo.attributeNamespace;
	        // `setAttribute` with objects becomes only `[object]` in IE8/9,
	        // ('' + value) makes it output the correct toString()-value.
	        if (namespace) {
	          node.setAttributeNS(namespace, attributeName, '' + value);
	        } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
	          node.setAttribute(attributeName, '');
	        } else {
	          node.setAttribute(attributeName, '' + value);
	        }
	      }
	    } else if (DOMProperty.isCustomAttribute(name)) {
	      DOMPropertyOperations.setValueForAttribute(node, name, value);
	      return;
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      var payload = {};
	      payload[name] = value;
	      ReactInstrumentation.debugTool.onHostOperation({
	        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
	        type: 'update attribute',
	        payload: payload
	      });
	    }
	  },

	  setValueForAttribute: function (node, name, value) {
	    if (!isAttributeNameSafe(name)) {
	      return;
	    }
	    if (value == null) {
	      node.removeAttribute(name);
	    } else {
	      node.setAttribute(name, '' + value);
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      var payload = {};
	      payload[name] = value;
	      ReactInstrumentation.debugTool.onHostOperation({
	        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
	        type: 'update attribute',
	        payload: payload
	      });
	    }
	  },

	  /**
	   * Deletes an attributes from a node.
	   *
	   * @param {DOMElement} node
	   * @param {string} name
	   */
	  deleteValueForAttribute: function (node, name) {
	    node.removeAttribute(name);
	    if (process.env.NODE_ENV !== 'production') {
	      ReactInstrumentation.debugTool.onHostOperation({
	        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
	        type: 'remove attribute',
	        payload: name
	      });
	    }
	  },

	  /**
	   * Deletes the value for a property on a node.
	   *
	   * @param {DOMElement} node
	   * @param {string} name
	   */
	  deleteValueForProperty: function (node, name) {
	    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
	    if (propertyInfo) {
	      var mutationMethod = propertyInfo.mutationMethod;
	      if (mutationMethod) {
	        mutationMethod(node, undefined);
	      } else if (propertyInfo.mustUseProperty) {
	        var propName = propertyInfo.propertyName;
	        if (propertyInfo.hasBooleanValue) {
	          node[propName] = false;
	        } else {
	          node[propName] = '';
	        }
	      } else {
	        node.removeAttribute(propertyInfo.attributeName);
	      }
	    } else if (DOMProperty.isCustomAttribute(name)) {
	      node.removeAttribute(name);
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      ReactInstrumentation.debugTool.onHostOperation({
	        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
	        type: 'remove attribute',
	        payload: name
	      });
	    }
	  }
	};

	module.exports = DOMPropertyOperations;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 137 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var escapeTextContentForBrowser = __webpack_require__(119);

	/**
	 * Escapes attribute value to prevent scripting attacks.
	 *
	 * @param {*} value Value to escape.
	 * @return {string} An escaped string.
	 */
	function quoteAttributeValueForBrowser(value) {
	  return '"' + escapeTextContentForBrowser(value) + '"';
	}

	module.exports = quoteAttributeValueForBrowser;

/***/ },
/* 138 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var EventPluginRegistry = __webpack_require__(75);
	var ReactEventEmitterMixin = __webpack_require__(139);
	var ViewportMetrics = __webpack_require__(109);

	var getVendorPrefixedEventName = __webpack_require__(140);
	var isEventSupported = __webpack_require__(103);

	/**
	 * Summary of `ReactBrowserEventEmitter` event handling:
	 *
	 *  - Top-level delegation is used to trap most native browser events. This
	 *    may only occur in the main thread and is the responsibility of
	 *    ReactEventListener, which is injected and can therefore support pluggable
	 *    event sources. This is the only work that occurs in the main thread.
	 *
	 *  - We normalize and de-duplicate events to account for browser quirks. This
	 *    may be done in the worker thread.
	 *
	 *  - Forward these native events (with the associated top-level type used to
	 *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want
	 *    to extract any synthetic events.
	 *
	 *  - The `EventPluginHub` will then process each event by annotating them with
	 *    "dispatches", a sequence of listeners and IDs that care about that event.
	 *
	 *  - The `EventPluginHub` then dispatches the events.
	 *
	 * Overview of React and the event system:
	 *
	 * +------------+    .
	 * |    DOM     |    .
	 * +------------+    .
	 *       |           .
	 *       v           .
	 * +------------+    .
	 * | ReactEvent |    .
	 * |  Listener  |    .
	 * +------------+    .                         +-----------+
	 *       |           .               +--------+|SimpleEvent|
	 *       |           .               |         |Plugin     |
	 * +-----|------+    .               v         +-----------+
	 * |     |      |    .    +--------------+                    +------------+
	 * |     +-----------.--->|EventPluginHub|                    |    Event   |
	 * |            |    .    |              |     +-----------+  | Propagators|
	 * | ReactEvent |    .    |              |     |TapEvent   |  |------------|
	 * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|
	 * |            |    .    |              |     +-----------+  |  utilities |
	 * |     +-----------.--->|              |                    +------------+
	 * |     |      |    .    +--------------+
	 * +-----|------+    .                ^        +-----------+
	 *       |           .                |        |Enter/Leave|
	 *       +           .                +-------+|Plugin     |
	 * +-------------+   .                         +-----------+
	 * | application |   .
	 * |-------------|   .
	 * |             |   .
	 * |             |   .
	 * +-------------+   .
	 *                   .
	 *    React Core     .  General Purpose Event Plugin System
	 */

	var hasEventPageXY;
	var alreadyListeningTo = {};
	var isMonitoringScrollValue = false;
	var reactTopListenersCounter = 0;

	// For events like 'submit' which don't consistently bubble (which we trap at a
	// lower node than `document`), binding at `document` would cause duplicate
	// events so we don't include them here
	var topEventMapping = {
	  topAbort: 'abort',
	  topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',
	  topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',
	  topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',
	  topBlur: 'blur',
	  topCanPlay: 'canplay',
	  topCanPlayThrough: 'canplaythrough',
	  topChange: 'change',
	  topClick: 'click',
	  topCompositionEnd: 'compositionend',
	  topCompositionStart: 'compositionstart',
	  topCompositionUpdate: 'compositionupdate',
	  topContextMenu: 'contextmenu',
	  topCopy: 'copy',
	  topCut: 'cut',
	  topDoubleClick: 'dblclick',
	  topDrag: 'drag',
	  topDragEnd: 'dragend',
	  topDragEnter: 'dragenter',
	  topDragExit: 'dragexit',
	  topDragLeave: 'dragleave',
	  topDragOver: 'dragover',
	  topDragStart: 'dragstart',
	  topDrop: 'drop',
	  topDurationChange: 'durationchange',
	  topEmptied: 'emptied',
	  topEncrypted: 'encrypted',
	  topEnded: 'ended',
	  topError: 'error',
	  topFocus: 'focus',
	  topInput: 'input',
	  topKeyDown: 'keydown',
	  topKeyPress: 'keypress',
	  topKeyUp: 'keyup',
	  topLoadedData: 'loadeddata',
	  topLoadedMetadata: 'loadedmetadata',
	  topLoadStart: 'loadstart',
	  topMouseDown: 'mousedown',
	  topMouseMove: 'mousemove',
	  topMouseOut: 'mouseout',
	  topMouseOver: 'mouseover',
	  topMouseUp: 'mouseup',
	  topPaste: 'paste',
	  topPause: 'pause',
	  topPlay: 'play',
	  topPlaying: 'playing',
	  topProgress: 'progress',
	  topRateChange: 'ratechange',
	  topScroll: 'scroll',
	  topSeeked: 'seeked',
	  topSeeking: 'seeking',
	  topSelectionChange: 'selectionchange',
	  topStalled: 'stalled',
	  topSuspend: 'suspend',
	  topTextInput: 'textInput',
	  topTimeUpdate: 'timeupdate',
	  topTouchCancel: 'touchcancel',
	  topTouchEnd: 'touchend',
	  topTouchMove: 'touchmove',
	  topTouchStart: 'touchstart',
	  topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',
	  topVolumeChange: 'volumechange',
	  topWaiting: 'waiting',
	  topWheel: 'wheel'
	};

	/**
	 * To ensure no conflicts with other potential React instances on the page
	 */
	var topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2);

	function getListeningForDocument(mountAt) {
	  // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
	  // directly.
	  if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
	    mountAt[topListenersIDKey] = reactTopListenersCounter++;
	    alreadyListeningTo[mountAt[topListenersIDKey]] = {};
	  }
	  return alreadyListeningTo[mountAt[topListenersIDKey]];
	}

	/**
	 * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For
	 * example:
	 *
	 *   EventPluginHub.putListener('myID', 'onClick', myFunction);
	 *
	 * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
	 *
	 * @internal
	 */
	var ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {
	  /**
	   * Injectable event backend
	   */
	  ReactEventListener: null,

	  injection: {
	    /**
	     * @param {object} ReactEventListener
	     */
	    injectReactEventListener: function (ReactEventListener) {
	      ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel);
	      ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;
	    }
	  },

	  /**
	   * Sets whether or not any created callbacks should be enabled.
	   *
	   * @param {boolean} enabled True if callbacks should be enabled.
	   */
	  setEnabled: function (enabled) {
	    if (ReactBrowserEventEmitter.ReactEventListener) {
	      ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled);
	    }
	  },

	  /**
	   * @return {boolean} True if callbacks are enabled.
	   */
	  isEnabled: function () {
	    return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled());
	  },

	  /**
	   * We listen for bubbled touch events on the document object.
	   *
	   * Firefox v8.01 (and possibly others) exhibited strange behavior when
	   * mounting `onmousemove` events at some node that was not the document
	   * element. The symptoms were that if your mouse is not moving over something
	   * contained within that mount point (for example on the background) the
	   * top-level listeners for `onmousemove` won't be called. However, if you
	   * register the `mousemove` on the document object, then it will of course
	   * catch all `mousemove`s. This along with iOS quirks, justifies restricting
	   * top-level listeners to the document object only, at least for these
	   * movement types of events and possibly all events.
	   *
	   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
	   *
	   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
	   * they bubble to document.
	   *
	   * @param {string} registrationName Name of listener (e.g. `onClick`).
	   * @param {object} contentDocumentHandle Document which owns the container
	   */
	  listenTo: function (registrationName, contentDocumentHandle) {
	    var mountAt = contentDocumentHandle;
	    var isListening = getListeningForDocument(mountAt);
	    var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName];

	    for (var i = 0; i < dependencies.length; i++) {
	      var dependency = dependencies[i];
	      if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
	        if (dependency === 'topWheel') {
	          if (isEventSupported('wheel')) {
	            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent('topWheel', 'wheel', mountAt);
	          } else if (isEventSupported('mousewheel')) {
	            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent('topWheel', 'mousewheel', mountAt);
	          } else {
	            // Firefox needs to capture a different mouse scroll event.
	            // @see http://www.quirksmode.org/dom/events/tests/scroll.html
	            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent('topWheel', 'DOMMouseScroll', mountAt);
	          }
	        } else if (dependency === 'topScroll') {
	          if (isEventSupported('scroll', true)) {
	            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent('topScroll', 'scroll', mountAt);
	          } else {
	            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent('topScroll', 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE);
	          }
	        } else if (dependency === 'topFocus' || dependency === 'topBlur') {
	          if (isEventSupported('focus', true)) {
	            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent('topFocus', 'focus', mountAt);
	            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent('topBlur', 'blur', mountAt);
	          } else if (isEventSupported('focusin')) {
	            // IE has `focusin` and `focusout` events which bubble.
	            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
	            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent('topFocus', 'focusin', mountAt);
	            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent('topBlur', 'focusout', mountAt);
	          }

	          // to make sure blur and focus event listeners are only attached once
	          isListening.topBlur = true;
	          isListening.topFocus = true;
	        } else if (topEventMapping.hasOwnProperty(dependency)) {
	          ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt);
	        }

	        isListening[dependency] = true;
	      }
	    }
	  },

	  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {
	    return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle);
	  },

	  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {
	    return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);
	  },

	  /**
	   * Protect against document.createEvent() returning null
	   * Some popup blocker extensions appear to do this:
	   * https://github.com/facebook/react/issues/6887
	   */
	  supportsEventPageXY: function () {
	    if (!document.createEvent) {
	      return false;
	    }
	    var ev = document.createEvent('MouseEvent');
	    return ev != null && 'pageX' in ev;
	  },

	  /**
	   * Listens to window scroll and resize events. We cache scroll values so that
	   * application code can access them without triggering reflows.
	   *
	   * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when
	   * pageX/pageY isn't supported (legacy browsers).
	   *
	   * NOTE: Scroll events do not bubble.
	   *
	   * @see http://www.quirksmode.org/dom/events/scroll.html
	   */
	  ensureScrollValueMonitoring: function () {
	    if (hasEventPageXY === undefined) {
	      hasEventPageXY = ReactBrowserEventEmitter.supportsEventPageXY();
	    }
	    if (!hasEventPageXY && !isMonitoringScrollValue) {
	      var refresh = ViewportMetrics.refreshScrollValues;
	      ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);
	      isMonitoringScrollValue = true;
	    }
	  }
	});

	module.exports = ReactBrowserEventEmitter;

/***/ },
/* 139 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var EventPluginHub = __webpack_require__(74);

	function runEventQueueInBatch(events) {
	  EventPluginHub.enqueueEvents(events);
	  EventPluginHub.processEventQueue(false);
	}

	var ReactEventEmitterMixin = {
	  /**
	   * Streams a fired top-level event to `EventPluginHub` where plugins have the
	   * opportunity to create `ReactEvent`s to be dispatched.
	   */
	  handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	    var events = EventPluginHub.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
	    runEventQueueInBatch(events);
	  }
	};

	module.exports = ReactEventEmitterMixin;

/***/ },
/* 140 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ExecutionEnvironment = __webpack_require__(80);

	/**
	 * Generate a mapping of standard vendor prefixes using the defined style property and event name.
	 *
	 * @param {string} styleProp
	 * @param {string} eventName
	 * @returns {object}
	 */
	function makePrefixMap(styleProp, eventName) {
	  var prefixes = {};

	  prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
	  prefixes['Webkit' + styleProp] = 'webkit' + eventName;
	  prefixes['Moz' + styleProp] = 'moz' + eventName;
	  prefixes['ms' + styleProp] = 'MS' + eventName;
	  prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();

	  return prefixes;
	}

	/**
	 * A list of event names to a configurable list of vendor prefixes.
	 */
	var vendorPrefixes = {
	  animationend: makePrefixMap('Animation', 'AnimationEnd'),
	  animationiteration: makePrefixMap('Animation', 'AnimationIteration'),
	  animationstart: makePrefixMap('Animation', 'AnimationStart'),
	  transitionend: makePrefixMap('Transition', 'TransitionEnd')
	};

	/**
	 * Event names that have already been detected and prefixed (if applicable).
	 */
	var prefixedEventNames = {};

	/**
	 * Element to check for prefixes on.
	 */
	var style = {};

	/**
	 * Bootstrap if a DOM exists.
	 */
	if (ExecutionEnvironment.canUseDOM) {
	  style = document.createElement('div').style;

	  // On some platforms, in particular some releases of Android 4.x,
	  // the un-prefixed "animation" and "transition" properties are defined on the
	  // style object but the events that fire will still be prefixed, so we need
	  // to check if the un-prefixed events are usable, and if not remove them from the map.
	  if (!('AnimationEvent' in window)) {
	    delete vendorPrefixes.animationend.animation;
	    delete vendorPrefixes.animationiteration.animation;
	    delete vendorPrefixes.animationstart.animation;
	  }

	  // Same as above
	  if (!('TransitionEvent' in window)) {
	    delete vendorPrefixes.transitionend.transition;
	  }
	}

	/**
	 * Attempts to determine the correct vendor prefixed event name.
	 *
	 * @param {string} eventName
	 * @returns {string}
	 */
	function getVendorPrefixedEventName(eventName) {
	  if (prefixedEventNames[eventName]) {
	    return prefixedEventNames[eventName];
	  } else if (!vendorPrefixes[eventName]) {
	    return eventName;
	  }

	  var prefixMap = vendorPrefixes[eventName];

	  for (var styleProp in prefixMap) {
	    if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {
	      return prefixedEventNames[eventName] = prefixMap[styleProp];
	    }
	  }

	  return '';
	}

	module.exports = getVendorPrefixedEventName;

/***/ },
/* 141 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67),
	    _assign = __webpack_require__(31);

	var DOMPropertyOperations = __webpack_require__(136);
	var LinkedValueUtils = __webpack_require__(142);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactUpdates = __webpack_require__(88);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	var didWarnValueLink = false;
	var didWarnCheckedLink = false;
	var didWarnValueDefaultValue = false;
	var didWarnCheckedDefaultChecked = false;
	var didWarnControlledToUncontrolled = false;
	var didWarnUncontrolledToControlled = false;

	function forceUpdateIfMounted() {
	  if (this._rootNodeID) {
	    // DOM component is still mounted; update
	    ReactDOMInput.updateWrapper(this);
	  }
	}

	function isControlled(props) {
	  var usesChecked = props.type === 'checkbox' || props.type === 'radio';
	  return usesChecked ? props.checked != null : props.value != null;
	}

	/**
	 * Implements an <input> host component that allows setting these optional
	 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
	 *
	 * If `checked` or `value` are not supplied (or null/undefined), user actions
	 * that affect the checked state or value will trigger updates to the element.
	 *
	 * If they are supplied (and not null/undefined), the rendered element will not
	 * trigger updates to the element. Instead, the props must change in order for
	 * the rendered element to be updated.
	 *
	 * The rendered element will be initialized as unchecked (or `defaultChecked`)
	 * with an empty value (or `defaultValue`).
	 *
	 * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
	 */
	var ReactDOMInput = {
	  getHostProps: function (inst, props) {
	    var value = LinkedValueUtils.getValue(props);
	    var checked = LinkedValueUtils.getChecked(props);

	    var hostProps = _assign({
	      // Make sure we set .type before any other properties (setting .value
	      // before .type means .value is lost in IE11 and below)
	      type: undefined,
	      // Make sure we set .step before .value (setting .value before .step
	      // means .value is rounded on mount, based upon step precision)
	      step: undefined,
	      // Make sure we set .min & .max before .value (to ensure proper order
	      // in corner cases such as min or max deriving from value, e.g. Issue #7170)
	      min: undefined,
	      max: undefined
	    }, props, {
	      defaultChecked: undefined,
	      defaultValue: undefined,
	      value: value != null ? value : inst._wrapperState.initialValue,
	      checked: checked != null ? checked : inst._wrapperState.initialChecked,
	      onChange: inst._wrapperState.onChange
	    });

	    return hostProps;
	  },

	  mountWrapper: function (inst, props) {
	    if (process.env.NODE_ENV !== 'production') {
	      LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);

	      var owner = inst._currentElement._owner;

	      if (props.valueLink !== undefined && !didWarnValueLink) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
	        didWarnValueLink = true;
	      }
	      if (props.checkedLink !== undefined && !didWarnCheckedLink) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
	        didWarnCheckedLink = true;
	      }
	      if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
	        didWarnCheckedDefaultChecked = true;
	      }
	      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
	        didWarnValueDefaultValue = true;
	      }
	    }

	    var defaultValue = props.defaultValue;
	    inst._wrapperState = {
	      initialChecked: props.checked != null ? props.checked : props.defaultChecked,
	      initialValue: props.value != null ? props.value : defaultValue,
	      listeners: null,
	      onChange: _handleChange.bind(inst),
	      controlled: isControlled(props)
	    };
	  },

	  updateWrapper: function (inst) {
	    var props = inst._currentElement.props;

	    if (process.env.NODE_ENV !== 'production') {
	      var controlled = isControlled(props);
	      var owner = inst._currentElement._owner;

	      if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
	        didWarnUncontrolledToControlled = true;
	      }
	      if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
	        didWarnControlledToUncontrolled = true;
	      }
	    }

	    // TODO: Shouldn't this be getChecked(props)?
	    var checked = props.checked;
	    if (checked != null) {
	      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);
	    }

	    var node = ReactDOMComponentTree.getNodeFromInstance(inst);
	    var value = LinkedValueUtils.getValue(props);
	    if (value != null) {
	      if (value === 0 && node.value === '') {
	        node.value = '0';
	        // Note: IE9 reports a number inputs as 'text', so check props instead.
	      } else if (props.type === 'number') {
	        // Simulate `input.valueAsNumber`. IE9 does not support it
	        var valueAsNumber = parseFloat(node.value, 10) || 0;

	        if (
	        // eslint-disable-next-line
	        value != valueAsNumber ||
	        // eslint-disable-next-line
	        value == valueAsNumber && node.value != value) {
	          // Cast `value` to a string to ensure the value is set correctly. While
	          // browsers typically do this as necessary, jsdom doesn't.
	          node.value = '' + value;
	        }
	      } else if (node.value !== '' + value) {
	        // Cast `value` to a string to ensure the value is set correctly. While
	        // browsers typically do this as necessary, jsdom doesn't.
	        node.value = '' + value;
	      }
	    } else {
	      if (props.value == null && props.defaultValue != null) {
	        // In Chrome, assigning defaultValue to certain input types triggers input validation.
	        // For number inputs, the display value loses trailing decimal points. For email inputs,
	        // Chrome raises "The specified value <x> is not a valid email address".
	        //
	        // Here we check to see if the defaultValue has actually changed, avoiding these problems
	        // when the user is inputting text
	        //
	        // https://github.com/facebook/react/issues/7253
	        if (node.defaultValue !== '' + props.defaultValue) {
	          node.defaultValue = '' + props.defaultValue;
	        }
	      }
	      if (props.checked == null && props.defaultChecked != null) {
	        node.defaultChecked = !!props.defaultChecked;
	      }
	    }
	  },

	  postMountWrapper: function (inst) {
	    var props = inst._currentElement.props;

	    // This is in postMount because we need access to the DOM node, which is not
	    // available until after the component has mounted.
	    var node = ReactDOMComponentTree.getNodeFromInstance(inst);

	    // Detach value from defaultValue. We won't do anything if we're working on
	    // submit or reset inputs as those values & defaultValues are linked. They
	    // are not resetable nodes so this operation doesn't matter and actually
	    // removes browser-default values (eg "Submit Query") when no value is
	    // provided.

	    switch (props.type) {
	      case 'submit':
	      case 'reset':
	        break;
	      case 'color':
	      case 'date':
	      case 'datetime':
	      case 'datetime-local':
	      case 'month':
	      case 'time':
	      case 'week':
	        // This fixes the no-show issue on iOS Safari and Android Chrome:
	        // https://github.com/facebook/react/issues/7233
	        node.value = '';
	        node.value = node.defaultValue;
	        break;
	      default:
	        node.value = node.value;
	        break;
	    }

	    // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
	    // this is needed to work around a chrome bug where setting defaultChecked
	    // will sometimes influence the value of checked (even after detachment).
	    // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
	    // We need to temporarily unset name to avoid disrupting radio button groups.
	    var name = node.name;
	    if (name !== '') {
	      node.name = '';
	    }
	    node.defaultChecked = !node.defaultChecked;
	    node.defaultChecked = !node.defaultChecked;
	    if (name !== '') {
	      node.name = name;
	    }
	  }
	};

	function _handleChange(event) {
	  var props = this._currentElement.props;

	  var returnValue = LinkedValueUtils.executeOnChange(props, event);

	  // Here we use asap to wait until all updates have propagated, which
	  // is important when using controlled components within layers:
	  // https://github.com/facebook/react/issues/1698
	  ReactUpdates.asap(forceUpdateIfMounted, this);

	  var name = props.name;
	  if (props.type === 'radio' && name != null) {
	    var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);
	    var queryRoot = rootNode;

	    while (queryRoot.parentNode) {
	      queryRoot = queryRoot.parentNode;
	    }

	    // If `rootNode.form` was non-null, then we could try `form.elements`,
	    // but that sometimes behaves strangely in IE8. We could also try using
	    // `form.getElementsByName`, but that will only return direct children
	    // and won't include inputs that use the HTML5 `form=` attribute. Since
	    // the input might not even be in a form, let's just use the global
	    // `querySelectorAll` to ensure we don't miss anything.
	    var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');

	    for (var i = 0; i < group.length; i++) {
	      var otherNode = group[i];
	      if (otherNode === rootNode || otherNode.form !== rootNode.form) {
	        continue;
	      }
	      // This will throw if radio buttons rendered by different copies of React
	      // and the same name are rendered into the same form (same as #1939).
	      // That's probably okay; we don't support it just as we don't support
	      // mixing React radio buttons with non-React ones.
	      var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
	      !otherInstance ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;
	      // If this is a controlled radio button group, forcing the input that
	      // was previously checked to update will cause it to be come re-checked
	      // as appropriate.
	      ReactUpdates.asap(forceUpdateIfMounted, otherInstance);
	    }
	  }

	  return returnValue;
	}

	module.exports = ReactDOMInput;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 142 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var ReactPropTypesSecret = __webpack_require__(143);
	var propTypesFactory = __webpack_require__(56);

	var React = __webpack_require__(29);
	var PropTypes = propTypesFactory(React.isValidElement);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	var hasReadOnlyValue = {
	  button: true,
	  checkbox: true,
	  image: true,
	  hidden: true,
	  radio: true,
	  reset: true,
	  submit: true
	};

	function _assertSingleLink(inputProps) {
	  !(inputProps.checkedLink == null || inputProps.valueLink == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don\'t want to use valueLink and vice versa.') : _prodInvariant('87') : void 0;
	}
	function _assertValueLink(inputProps) {
	  _assertSingleLink(inputProps);
	  !(inputProps.value == null && inputProps.onChange == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don\'t want to use valueLink.') : _prodInvariant('88') : void 0;
	}

	function _assertCheckedLink(inputProps) {
	  _assertSingleLink(inputProps);
	  !(inputProps.checked == null && inputProps.onChange == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don\'t want to use checkedLink') : _prodInvariant('89') : void 0;
	}

	var propTypes = {
	  value: function (props, propName, componentName) {
	    if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {
	      return null;
	    }
	    return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
	  },
	  checked: function (props, propName, componentName) {
	    if (!props[propName] || props.onChange || props.readOnly || props.disabled) {
	      return null;
	    }
	    return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
	  },
	  onChange: PropTypes.func
	};

	var loggedTypeFailures = {};
	function getDeclarationErrorAddendum(owner) {
	  if (owner) {
	    var name = owner.getName();
	    if (name) {
	      return ' Check the render method of `' + name + '`.';
	    }
	  }
	  return '';
	}

	/**
	 * Provide a linked `value` attribute for controlled forms. You should not use
	 * this outside of the ReactDOM controlled form components.
	 */
	var LinkedValueUtils = {
	  checkPropTypes: function (tagName, props, owner) {
	    for (var propName in propTypes) {
	      if (propTypes.hasOwnProperty(propName)) {
	        var error = propTypes[propName](props, propName, tagName, 'prop', null, ReactPropTypesSecret);
	      }
	      if (error instanceof Error && !(error.message in loggedTypeFailures)) {
	        // Only monitor this failure once because there tends to be a lot of the
	        // same error.
	        loggedTypeFailures[error.message] = true;

	        var addendum = getDeclarationErrorAddendum(owner);
	        process.env.NODE_ENV !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0;
	      }
	    }
	  },

	  /**
	   * @param {object} inputProps Props for form component
	   * @return {*} current value of the input either from value prop or link.
	   */
	  getValue: function (inputProps) {
	    if (inputProps.valueLink) {
	      _assertValueLink(inputProps);
	      return inputProps.valueLink.value;
	    }
	    return inputProps.value;
	  },

	  /**
	   * @param {object} inputProps Props for form component
	   * @return {*} current checked status of the input either from checked prop
	   *             or link.
	   */
	  getChecked: function (inputProps) {
	    if (inputProps.checkedLink) {
	      _assertCheckedLink(inputProps);
	      return inputProps.checkedLink.value;
	    }
	    return inputProps.checked;
	  },

	  /**
	   * @param {object} inputProps Props for form component
	   * @param {SyntheticEvent} event change event to handle
	   */
	  executeOnChange: function (inputProps, event) {
	    if (inputProps.valueLink) {
	      _assertValueLink(inputProps);
	      return inputProps.valueLink.requestChange(event.target.value);
	    } else if (inputProps.checkedLink) {
	      _assertCheckedLink(inputProps);
	      return inputProps.checkedLink.requestChange(event.target.checked);
	    } else if (inputProps.onChange) {
	      return inputProps.onChange.call(undefined, event);
	    }
	  }
	};

	module.exports = LinkedValueUtils;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 143 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';

	module.exports = ReactPropTypesSecret;

/***/ },
/* 144 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var React = __webpack_require__(29);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactDOMSelect = __webpack_require__(145);

	var warning = __webpack_require__(35);
	var didWarnInvalidOptionChildren = false;

	function flattenChildren(children) {
	  var content = '';

	  // Flatten children and warn if they aren't strings or numbers;
	  // invalid types are ignored.
	  React.Children.forEach(children, function (child) {
	    if (child == null) {
	      return;
	    }
	    if (typeof child === 'string' || typeof child === 'number') {
	      content += child;
	    } else if (!didWarnInvalidOptionChildren) {
	      didWarnInvalidOptionChildren = true;
	      process.env.NODE_ENV !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;
	    }
	  });

	  return content;
	}

	/**
	 * Implements an <option> host component that warns when `selected` is set.
	 */
	var ReactDOMOption = {
	  mountWrapper: function (inst, props, hostParent) {
	    // TODO (yungsters): Remove support for `selected` in <option>.
	    if (process.env.NODE_ENV !== 'production') {
	      process.env.NODE_ENV !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;
	    }

	    // Look up whether this option is 'selected'
	    var selectValue = null;
	    if (hostParent != null) {
	      var selectParent = hostParent;

	      if (selectParent._tag === 'optgroup') {
	        selectParent = selectParent._hostParent;
	      }

	      if (selectParent != null && selectParent._tag === 'select') {
	        selectValue = ReactDOMSelect.getSelectValueContext(selectParent);
	      }
	    }

	    // If the value is null (e.g., no specified value or after initial mount)
	    // or missing (e.g., for <datalist>), we don't change props.selected
	    var selected = null;
	    if (selectValue != null) {
	      var value;
	      if (props.value != null) {
	        value = props.value + '';
	      } else {
	        value = flattenChildren(props.children);
	      }
	      selected = false;
	      if (Array.isArray(selectValue)) {
	        // multiple
	        for (var i = 0; i < selectValue.length; i++) {
	          if ('' + selectValue[i] === value) {
	            selected = true;
	            break;
	          }
	        }
	      } else {
	        selected = '' + selectValue === value;
	      }
	    }

	    inst._wrapperState = { selected: selected };
	  },

	  postMountWrapper: function (inst) {
	    // value="" should make a value attribute (#6219)
	    var props = inst._currentElement.props;
	    if (props.value != null) {
	      var node = ReactDOMComponentTree.getNodeFromInstance(inst);
	      node.setAttribute('value', props.value);
	    }
	  },

	  getHostProps: function (inst, props) {
	    var hostProps = _assign({ selected: undefined, children: undefined }, props);

	    // Read state only from initial mount because <select> updates value
	    // manually; we need the initial state only for server rendering
	    if (inst._wrapperState.selected != null) {
	      hostProps.selected = inst._wrapperState.selected;
	    }

	    var content = flattenChildren(props.children);

	    if (content) {
	      hostProps.children = content;
	    }

	    return hostProps;
	  }
	};

	module.exports = ReactDOMOption;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 145 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var LinkedValueUtils = __webpack_require__(142);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactUpdates = __webpack_require__(88);

	var warning = __webpack_require__(35);

	var didWarnValueLink = false;
	var didWarnValueDefaultValue = false;

	function updateOptionsIfPendingUpdateAndMounted() {
	  if (this._rootNodeID && this._wrapperState.pendingUpdate) {
	    this._wrapperState.pendingUpdate = false;

	    var props = this._currentElement.props;
	    var value = LinkedValueUtils.getValue(props);

	    if (value != null) {
	      updateOptions(this, Boolean(props.multiple), value);
	    }
	  }
	}

	function getDeclarationErrorAddendum(owner) {
	  if (owner) {
	    var name = owner.getName();
	    if (name) {
	      return ' Check the render method of `' + name + '`.';
	    }
	  }
	  return '';
	}

	var valuePropNames = ['value', 'defaultValue'];

	/**
	 * Validation function for `value` and `defaultValue`.
	 * @private
	 */
	function checkSelectPropTypes(inst, props) {
	  var owner = inst._currentElement._owner;
	  LinkedValueUtils.checkPropTypes('select', props, owner);

	  if (props.valueLink !== undefined && !didWarnValueLink) {
	    process.env.NODE_ENV !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;
	    didWarnValueLink = true;
	  }

	  for (var i = 0; i < valuePropNames.length; i++) {
	    var propName = valuePropNames[i];
	    if (props[propName] == null) {
	      continue;
	    }
	    var isArray = Array.isArray(props[propName]);
	    if (props.multiple && !isArray) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
	    } else if (!props.multiple && isArray) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
	    }
	  }
	}

	/**
	 * @param {ReactDOMComponent} inst
	 * @param {boolean} multiple
	 * @param {*} propValue A stringable (with `multiple`, a list of stringables).
	 * @private
	 */
	function updateOptions(inst, multiple, propValue) {
	  var selectedValue, i;
	  var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;

	  if (multiple) {
	    selectedValue = {};
	    for (i = 0; i < propValue.length; i++) {
	      selectedValue['' + propValue[i]] = true;
	    }
	    for (i = 0; i < options.length; i++) {
	      var selected = selectedValue.hasOwnProperty(options[i].value);
	      if (options[i].selected !== selected) {
	        options[i].selected = selected;
	      }
	    }
	  } else {
	    // Do not set `select.value` as exact behavior isn't consistent across all
	    // browsers for all cases.
	    selectedValue = '' + propValue;
	    for (i = 0; i < options.length; i++) {
	      if (options[i].value === selectedValue) {
	        options[i].selected = true;
	        return;
	      }
	    }
	    if (options.length) {
	      options[0].selected = true;
	    }
	  }
	}

	/**
	 * Implements a <select> host component that allows optionally setting the
	 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
	 * stringable. If `multiple` is true, the prop must be an array of stringables.
	 *
	 * If `value` is not supplied (or null/undefined), user actions that change the
	 * selected option will trigger updates to the rendered options.
	 *
	 * If it is supplied (and not null/undefined), the rendered options will not
	 * update in response to user actions. Instead, the `value` prop must change in
	 * order for the rendered options to update.
	 *
	 * If `defaultValue` is provided, any options with the supplied values will be
	 * selected.
	 */
	var ReactDOMSelect = {
	  getHostProps: function (inst, props) {
	    return _assign({}, props, {
	      onChange: inst._wrapperState.onChange,
	      value: undefined
	    });
	  },

	  mountWrapper: function (inst, props) {
	    if (process.env.NODE_ENV !== 'production') {
	      checkSelectPropTypes(inst, props);
	    }

	    var value = LinkedValueUtils.getValue(props);
	    inst._wrapperState = {
	      pendingUpdate: false,
	      initialValue: value != null ? value : props.defaultValue,
	      listeners: null,
	      onChange: _handleChange.bind(inst),
	      wasMultiple: Boolean(props.multiple)
	    };

	    if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
	      didWarnValueDefaultValue = true;
	    }
	  },

	  getSelectValueContext: function (inst) {
	    // ReactDOMOption looks at this initial value so the initial generated
	    // markup has correct `selected` attributes
	    return inst._wrapperState.initialValue;
	  },

	  postUpdateWrapper: function (inst) {
	    var props = inst._currentElement.props;

	    // After the initial mount, we control selected-ness manually so don't pass
	    // this value down
	    inst._wrapperState.initialValue = undefined;

	    var wasMultiple = inst._wrapperState.wasMultiple;
	    inst._wrapperState.wasMultiple = Boolean(props.multiple);

	    var value = LinkedValueUtils.getValue(props);
	    if (value != null) {
	      inst._wrapperState.pendingUpdate = false;
	      updateOptions(inst, Boolean(props.multiple), value);
	    } else if (wasMultiple !== Boolean(props.multiple)) {
	      // For simplicity, reapply `defaultValue` if `multiple` is toggled.
	      if (props.defaultValue != null) {
	        updateOptions(inst, Boolean(props.multiple), props.defaultValue);
	      } else {
	        // Revert the select back to its default unselected state.
	        updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : '');
	      }
	    }
	  }
	};

	function _handleChange(event) {
	  var props = this._currentElement.props;
	  var returnValue = LinkedValueUtils.executeOnChange(props, event);

	  if (this._rootNodeID) {
	    this._wrapperState.pendingUpdate = true;
	  }
	  ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this);
	  return returnValue;
	}

	module.exports = ReactDOMSelect;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 146 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67),
	    _assign = __webpack_require__(31);

	var LinkedValueUtils = __webpack_require__(142);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactUpdates = __webpack_require__(88);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	var didWarnValueLink = false;
	var didWarnValDefaultVal = false;

	function forceUpdateIfMounted() {
	  if (this._rootNodeID) {
	    // DOM component is still mounted; update
	    ReactDOMTextarea.updateWrapper(this);
	  }
	}

	/**
	 * Implements a <textarea> host component that allows setting `value`, and
	 * `defaultValue`. This differs from the traditional DOM API because value is
	 * usually set as PCDATA children.
	 *
	 * If `value` is not supplied (or null/undefined), user actions that affect the
	 * value will trigger updates to the element.
	 *
	 * If `value` is supplied (and not null/undefined), the rendered element will
	 * not trigger updates to the element. Instead, the `value` prop must change in
	 * order for the rendered element to be updated.
	 *
	 * The rendered element will be initialized with an empty value, the prop
	 * `defaultValue` if specified, or the children content (deprecated).
	 */
	var ReactDOMTextarea = {
	  getHostProps: function (inst, props) {
	    !(props.dangerouslySetInnerHTML == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : _prodInvariant('91') : void 0;

	    // Always set children to the same thing. In IE9, the selection range will
	    // get reset if `textContent` is mutated.  We could add a check in setTextContent
	    // to only set the value if/when the value differs from the node value (which would
	    // completely solve this IE9 bug), but Sebastian+Ben seemed to like this solution.
	    // The value can be a boolean or object so that's why it's forced to be a string.
	    var hostProps = _assign({}, props, {
	      value: undefined,
	      defaultValue: undefined,
	      children: '' + inst._wrapperState.initialValue,
	      onChange: inst._wrapperState.onChange
	    });

	    return hostProps;
	  },

	  mountWrapper: function (inst, props) {
	    if (process.env.NODE_ENV !== 'production') {
	      LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);
	      if (props.valueLink !== undefined && !didWarnValueLink) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '`valueLink` prop on `textarea` is deprecated; set `value` and `onChange` instead.') : void 0;
	        didWarnValueLink = true;
	      }
	      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
	        process.env.NODE_ENV !== 'production' ? warning(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
	        didWarnValDefaultVal = true;
	      }
	    }

	    var value = LinkedValueUtils.getValue(props);
	    var initialValue = value;

	    // Only bother fetching default value if we're going to use it
	    if (value == null) {
	      var defaultValue = props.defaultValue;
	      // TODO (yungsters): Remove support for children content in <textarea>.
	      var children = props.children;
	      if (children != null) {
	        if (process.env.NODE_ENV !== 'production') {
	          process.env.NODE_ENV !== 'production' ? warning(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.') : void 0;
	        }
	        !(defaultValue == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : _prodInvariant('92') : void 0;
	        if (Array.isArray(children)) {
	          !(children.length <= 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, '<textarea> can only have at most one child.') : _prodInvariant('93') : void 0;
	          children = children[0];
	        }

	        defaultValue = '' + children;
	      }
	      if (defaultValue == null) {
	        defaultValue = '';
	      }
	      initialValue = defaultValue;
	    }

	    inst._wrapperState = {
	      initialValue: '' + initialValue,
	      listeners: null,
	      onChange: _handleChange.bind(inst)
	    };
	  },

	  updateWrapper: function (inst) {
	    var props = inst._currentElement.props;

	    var node = ReactDOMComponentTree.getNodeFromInstance(inst);
	    var value = LinkedValueUtils.getValue(props);
	    if (value != null) {
	      // Cast `value` to a string to ensure the value is set correctly. While
	      // browsers typically do this as necessary, jsdom doesn't.
	      var newValue = '' + value;

	      // To avoid side effects (such as losing text selection), only set value if changed
	      if (newValue !== node.value) {
	        node.value = newValue;
	      }
	      if (props.defaultValue == null) {
	        node.defaultValue = newValue;
	      }
	    }
	    if (props.defaultValue != null) {
	      node.defaultValue = props.defaultValue;
	    }
	  },

	  postMountWrapper: function (inst) {
	    // This is in postMount because we need access to the DOM node, which is not
	    // available until after the component has mounted.
	    var node = ReactDOMComponentTree.getNodeFromInstance(inst);
	    var textContent = node.textContent;

	    // Only set node.value if textContent is equal to the expected
	    // initial value. In IE10/IE11 there is a bug where the placeholder attribute
	    // will populate textContent as well.
	    // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
	    if (textContent === inst._wrapperState.initialValue) {
	      node.value = textContent;
	    }
	  }
	};

	function _handleChange(event) {
	  var props = this._currentElement.props;
	  var returnValue = LinkedValueUtils.executeOnChange(props, event);
	  ReactUpdates.asap(forceUpdateIfMounted, this);
	  return returnValue;
	}

	module.exports = ReactDOMTextarea;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 147 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var ReactComponentEnvironment = __webpack_require__(148);
	var ReactInstanceMap = __webpack_require__(149);
	var ReactInstrumentation = __webpack_require__(94);

	var ReactCurrentOwner = __webpack_require__(44);
	var ReactReconciler = __webpack_require__(91);
	var ReactChildReconciler = __webpack_require__(150);

	var emptyFunction = __webpack_require__(36);
	var flattenChildren = __webpack_require__(165);
	var invariant = __webpack_require__(39);

	/**
	 * Make an update for markup to be rendered and inserted at a supplied index.
	 *
	 * @param {string} markup Markup that renders into an element.
	 * @param {number} toIndex Destination index.
	 * @private
	 */
	function makeInsertMarkup(markup, afterNode, toIndex) {
	  // NOTE: Null values reduce hidden classes.
	  return {
	    type: 'INSERT_MARKUP',
	    content: markup,
	    fromIndex: null,
	    fromNode: null,
	    toIndex: toIndex,
	    afterNode: afterNode
	  };
	}

	/**
	 * Make an update for moving an existing element to another index.
	 *
	 * @param {number} fromIndex Source index of the existing element.
	 * @param {number} toIndex Destination index of the element.
	 * @private
	 */
	function makeMove(child, afterNode, toIndex) {
	  // NOTE: Null values reduce hidden classes.
	  return {
	    type: 'MOVE_EXISTING',
	    content: null,
	    fromIndex: child._mountIndex,
	    fromNode: ReactReconciler.getHostNode(child),
	    toIndex: toIndex,
	    afterNode: afterNode
	  };
	}

	/**
	 * Make an update for removing an element at an index.
	 *
	 * @param {number} fromIndex Index of the element to remove.
	 * @private
	 */
	function makeRemove(child, node) {
	  // NOTE: Null values reduce hidden classes.
	  return {
	    type: 'REMOVE_NODE',
	    content: null,
	    fromIndex: child._mountIndex,
	    fromNode: node,
	    toIndex: null,
	    afterNode: null
	  };
	}

	/**
	 * Make an update for setting the markup of a node.
	 *
	 * @param {string} markup Markup that renders into an element.
	 * @private
	 */
	function makeSetMarkup(markup) {
	  // NOTE: Null values reduce hidden classes.
	  return {
	    type: 'SET_MARKUP',
	    content: markup,
	    fromIndex: null,
	    fromNode: null,
	    toIndex: null,
	    afterNode: null
	  };
	}

	/**
	 * Make an update for setting the text content.
	 *
	 * @param {string} textContent Text content to set.
	 * @private
	 */
	function makeTextContent(textContent) {
	  // NOTE: Null values reduce hidden classes.
	  return {
	    type: 'TEXT_CONTENT',
	    content: textContent,
	    fromIndex: null,
	    fromNode: null,
	    toIndex: null,
	    afterNode: null
	  };
	}

	/**
	 * Push an update, if any, onto the queue. Creates a new queue if none is
	 * passed and always returns the queue. Mutative.
	 */
	function enqueue(queue, update) {
	  if (update) {
	    queue = queue || [];
	    queue.push(update);
	  }
	  return queue;
	}

	/**
	 * Processes any enqueued updates.
	 *
	 * @private
	 */
	function processQueue(inst, updateQueue) {
	  ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue);
	}

	var setChildrenForInstrumentation = emptyFunction;
	if (process.env.NODE_ENV !== 'production') {
	  var getDebugID = function (inst) {
	    if (!inst._debugID) {
	      // Check for ART-like instances. TODO: This is silly/gross.
	      var internal;
	      if (internal = ReactInstanceMap.get(inst)) {
	        inst = internal;
	      }
	    }
	    return inst._debugID;
	  };
	  setChildrenForInstrumentation = function (children) {
	    var debugID = getDebugID(this);
	    // TODO: React Native empty components are also multichild.
	    // This means they still get into this method but don't have _debugID.
	    if (debugID !== 0) {
	      ReactInstrumentation.debugTool.onSetChildren(debugID, children ? Object.keys(children).map(function (key) {
	        return children[key]._debugID;
	      }) : []);
	    }
	  };
	}

	/**
	 * ReactMultiChild are capable of reconciling multiple children.
	 *
	 * @class ReactMultiChild
	 * @internal
	 */
	var ReactMultiChild = {
	  /**
	   * Provides common functionality for components that must reconcile multiple
	   * children. This is used by `ReactDOMComponent` to mount, update, and
	   * unmount child components.
	   *
	   * @lends {ReactMultiChild.prototype}
	   */
	  Mixin: {
	    _reconcilerInstantiateChildren: function (nestedChildren, transaction, context) {
	      if (process.env.NODE_ENV !== 'production') {
	        var selfDebugID = getDebugID(this);
	        if (this._currentElement) {
	          try {
	            ReactCurrentOwner.current = this._currentElement._owner;
	            return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context, selfDebugID);
	          } finally {
	            ReactCurrentOwner.current = null;
	          }
	        }
	      }
	      return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context);
	    },

	    _reconcilerUpdateChildren: function (prevChildren, nextNestedChildrenElements, mountImages, removedNodes, transaction, context) {
	      var nextChildren;
	      var selfDebugID = 0;
	      if (process.env.NODE_ENV !== 'production') {
	        selfDebugID = getDebugID(this);
	        if (this._currentElement) {
	          try {
	            ReactCurrentOwner.current = this._currentElement._owner;
	            nextChildren = flattenChildren(nextNestedChildrenElements, selfDebugID);
	          } finally {
	            ReactCurrentOwner.current = null;
	          }
	          ReactChildReconciler.updateChildren(prevChildren, nextChildren, mountImages, removedNodes, transaction, this, this._hostContainerInfo, context, selfDebugID);
	          return nextChildren;
	        }
	      }
	      nextChildren = flattenChildren(nextNestedChildrenElements, selfDebugID);
	      ReactChildReconciler.updateChildren(prevChildren, nextChildren, mountImages, removedNodes, transaction, this, this._hostContainerInfo, context, selfDebugID);
	      return nextChildren;
	    },

	    /**
	     * Generates a "mount image" for each of the supplied children. In the case
	     * of `ReactDOMComponent`, a mount image is a string of markup.
	     *
	     * @param {?object} nestedChildren Nested child maps.
	     * @return {array} An array of mounted representations.
	     * @internal
	     */
	    mountChildren: function (nestedChildren, transaction, context) {
	      var children = this._reconcilerInstantiateChildren(nestedChildren, transaction, context);
	      this._renderedChildren = children;

	      var mountImages = [];
	      var index = 0;
	      for (var name in children) {
	        if (children.hasOwnProperty(name)) {
	          var child = children[name];
	          var selfDebugID = 0;
	          if (process.env.NODE_ENV !== 'production') {
	            selfDebugID = getDebugID(this);
	          }
	          var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context, selfDebugID);
	          child._mountIndex = index++;
	          mountImages.push(mountImage);
	        }
	      }

	      if (process.env.NODE_ENV !== 'production') {
	        setChildrenForInstrumentation.call(this, children);
	      }

	      return mountImages;
	    },

	    /**
	     * Replaces any rendered children with a text content string.
	     *
	     * @param {string} nextContent String of content.
	     * @internal
	     */
	    updateTextContent: function (nextContent) {
	      var prevChildren = this._renderedChildren;
	      // Remove any rendered children.
	      ReactChildReconciler.unmountChildren(prevChildren, false);
	      for (var name in prevChildren) {
	        if (prevChildren.hasOwnProperty(name)) {
	           true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;
	        }
	      }
	      // Set new text content.
	      var updates = [makeTextContent(nextContent)];
	      processQueue(this, updates);
	    },

	    /**
	     * Replaces any rendered children with a markup string.
	     *
	     * @param {string} nextMarkup String of markup.
	     * @internal
	     */
	    updateMarkup: function (nextMarkup) {
	      var prevChildren = this._renderedChildren;
	      // Remove any rendered children.
	      ReactChildReconciler.unmountChildren(prevChildren, false);
	      for (var name in prevChildren) {
	        if (prevChildren.hasOwnProperty(name)) {
	           true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;
	        }
	      }
	      var updates = [makeSetMarkup(nextMarkup)];
	      processQueue(this, updates);
	    },

	    /**
	     * Updates the rendered children with new children.
	     *
	     * @param {?object} nextNestedChildrenElements Nested child element maps.
	     * @param {ReactReconcileTransaction} transaction
	     * @internal
	     */
	    updateChildren: function (nextNestedChildrenElements, transaction, context) {
	      // Hook used by React ART
	      this._updateChildren(nextNestedChildrenElements, transaction, context);
	    },

	    /**
	     * @param {?object} nextNestedChildrenElements Nested child element maps.
	     * @param {ReactReconcileTransaction} transaction
	     * @final
	     * @protected
	     */
	    _updateChildren: function (nextNestedChildrenElements, transaction, context) {
	      var prevChildren = this._renderedChildren;
	      var removedNodes = {};
	      var mountImages = [];
	      var nextChildren = this._reconcilerUpdateChildren(prevChildren, nextNestedChildrenElements, mountImages, removedNodes, transaction, context);
	      if (!nextChildren && !prevChildren) {
	        return;
	      }
	      var updates = null;
	      var name;
	      // `nextIndex` will increment for each child in `nextChildren`, but
	      // `lastIndex` will be the last index visited in `prevChildren`.
	      var nextIndex = 0;
	      var lastIndex = 0;
	      // `nextMountIndex` will increment for each newly mounted child.
	      var nextMountIndex = 0;
	      var lastPlacedNode = null;
	      for (name in nextChildren) {
	        if (!nextChildren.hasOwnProperty(name)) {
	          continue;
	        }
	        var prevChild = prevChildren && prevChildren[name];
	        var nextChild = nextChildren[name];
	        if (prevChild === nextChild) {
	          updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));
	          lastIndex = Math.max(prevChild._mountIndex, lastIndex);
	          prevChild._mountIndex = nextIndex;
	        } else {
	          if (prevChild) {
	            // Update `lastIndex` before `_mountIndex` gets unset by unmounting.
	            lastIndex = Math.max(prevChild._mountIndex, lastIndex);
	            // The `removedNodes` loop below will actually remove the child.
	          }
	          // The child must be instantiated before it's mounted.
	          updates = enqueue(updates, this._mountChildAtIndex(nextChild, mountImages[nextMountIndex], lastPlacedNode, nextIndex, transaction, context));
	          nextMountIndex++;
	        }
	        nextIndex++;
	        lastPlacedNode = ReactReconciler.getHostNode(nextChild);
	      }
	      // Remove children that are no longer present.
	      for (name in removedNodes) {
	        if (removedNodes.hasOwnProperty(name)) {
	          updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name]));
	        }
	      }
	      if (updates) {
	        processQueue(this, updates);
	      }
	      this._renderedChildren = nextChildren;

	      if (process.env.NODE_ENV !== 'production') {
	        setChildrenForInstrumentation.call(this, nextChildren);
	      }
	    },

	    /**
	     * Unmounts all rendered children. This should be used to clean up children
	     * when this component is unmounted. It does not actually perform any
	     * backend operations.
	     *
	     * @internal
	     */
	    unmountChildren: function (safely) {
	      var renderedChildren = this._renderedChildren;
	      ReactChildReconciler.unmountChildren(renderedChildren, safely);
	      this._renderedChildren = null;
	    },

	    /**
	     * Moves a child component to the supplied index.
	     *
	     * @param {ReactComponent} child Component to move.
	     * @param {number} toIndex Destination index of the element.
	     * @param {number} lastIndex Last index visited of the siblings of `child`.
	     * @protected
	     */
	    moveChild: function (child, afterNode, toIndex, lastIndex) {
	      // If the index of `child` is less than `lastIndex`, then it needs to
	      // be moved. Otherwise, we do not need to move it because a child will be
	      // inserted or moved before `child`.
	      if (child._mountIndex < lastIndex) {
	        return makeMove(child, afterNode, toIndex);
	      }
	    },

	    /**
	     * Creates a child component.
	     *
	     * @param {ReactComponent} child Component to create.
	     * @param {string} mountImage Markup to insert.
	     * @protected
	     */
	    createChild: function (child, afterNode, mountImage) {
	      return makeInsertMarkup(mountImage, afterNode, child._mountIndex);
	    },

	    /**
	     * Removes a child component.
	     *
	     * @param {ReactComponent} child Child to remove.
	     * @protected
	     */
	    removeChild: function (child, node) {
	      return makeRemove(child, node);
	    },

	    /**
	     * Mounts a child with the supplied name.
	     *
	     * NOTE: This is part of `updateChildren` and is here for readability.
	     *
	     * @param {ReactComponent} child Component to mount.
	     * @param {string} name Name of the child.
	     * @param {number} index Index at which to insert the child.
	     * @param {ReactReconcileTransaction} transaction
	     * @private
	     */
	    _mountChildAtIndex: function (child, mountImage, afterNode, index, transaction, context) {
	      child._mountIndex = index;
	      return this.createChild(child, afterNode, mountImage);
	    },

	    /**
	     * Unmounts a rendered child.
	     *
	     * NOTE: This is part of `updateChildren` and is here for readability.
	     *
	     * @param {ReactComponent} child Component to unmount.
	     * @private
	     */
	    _unmountChild: function (child, node) {
	      var update = this.removeChild(child, node);
	      child._mountIndex = null;
	      return update;
	    }
	  }
	};

	module.exports = ReactMultiChild;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 148 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	var injected = false;

	var ReactComponentEnvironment = {
	  /**
	   * Optionally injectable hook for swapping out mount images in the middle of
	   * the tree.
	   */
	  replaceNodeWithMarkup: null,

	  /**
	   * Optionally injectable hook for processing a queue of child updates. Will
	   * later move into MultiChildComponents.
	   */
	  processChildrenUpdates: null,

	  injection: {
	    injectEnvironment: function (environment) {
	      !!injected ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0;
	      ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;
	      ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;
	      injected = true;
	    }
	  }
	};

	module.exports = ReactComponentEnvironment;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 149 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * `ReactInstanceMap` maintains a mapping from a public facing stateful
	 * instance (key) and the internal representation (value). This allows public
	 * methods to accept the user facing instance as an argument and map them back
	 * to internal methods.
	 */

	// TODO: Replace this with ES6: var ReactInstanceMap = new Map();

	var ReactInstanceMap = {
	  /**
	   * This API should be called `delete` but we'd have to make sure to always
	   * transform these to strings for IE support. When this transform is fully
	   * supported we can rename it.
	   */
	  remove: function (key) {
	    key._reactInternalInstance = undefined;
	  },

	  get: function (key) {
	    return key._reactInternalInstance;
	  },

	  has: function (key) {
	    return key._reactInternalInstance !== undefined;
	  },

	  set: function (key, value) {
	    key._reactInternalInstance = value;
	  }
	};

	module.exports = ReactInstanceMap;

/***/ },
/* 150 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactReconciler = __webpack_require__(91);

	var instantiateReactComponent = __webpack_require__(151);
	var KeyEscapeUtils = __webpack_require__(161);
	var shouldUpdateReactComponent = __webpack_require__(157);
	var traverseAllChildren = __webpack_require__(162);
	var warning = __webpack_require__(35);

	var ReactComponentTreeHook;

	if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'test') {
	  // Temporary hack.
	  // Inline requires don't work well with Jest:
	  // https://github.com/facebook/react/issues/7240
	  // Remove the inline requires when we don't need them anymore:
	  // https://github.com/facebook/react/pull/7178
	  ReactComponentTreeHook = __webpack_require__(51);
	}

	function instantiateChild(childInstances, child, name, selfDebugID) {
	  // We found a component instance.
	  var keyUnique = childInstances[name] === undefined;
	  if (process.env.NODE_ENV !== 'production') {
	    if (!ReactComponentTreeHook) {
	      ReactComponentTreeHook = __webpack_require__(51);
	    }
	    if (!keyUnique) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeHook.getStackAddendumByID(selfDebugID)) : void 0;
	    }
	  }
	  if (child != null && keyUnique) {
	    childInstances[name] = instantiateReactComponent(child, true);
	  }
	}

	/**
	 * ReactChildReconciler provides helpers for initializing or updating a set of
	 * children. Its output is suitable for passing it onto ReactMultiChild which
	 * does diffed reordering and insertion.
	 */
	var ReactChildReconciler = {
	  /**
	   * Generates a "mount image" for each of the supplied children. In the case
	   * of `ReactDOMComponent`, a mount image is a string of markup.
	   *
	   * @param {?object} nestedChildNodes Nested child maps.
	   * @return {?object} A set of child instances.
	   * @internal
	   */
	  instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID) // 0 in production and for roots
	  {
	    if (nestedChildNodes == null) {
	      return null;
	    }
	    var childInstances = {};

	    if (process.env.NODE_ENV !== 'production') {
	      traverseAllChildren(nestedChildNodes, function (childInsts, child, name) {
	        return instantiateChild(childInsts, child, name, selfDebugID);
	      }, childInstances);
	    } else {
	      traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);
	    }
	    return childInstances;
	  },

	  /**
	   * Updates the rendered children and returns a new set of children.
	   *
	   * @param {?object} prevChildren Previously initialized set of children.
	   * @param {?object} nextChildren Flat child element maps.
	   * @param {ReactReconcileTransaction} transaction
	   * @param {object} context
	   * @return {?object} A new set of child instances.
	   * @internal
	   */
	  updateChildren: function (prevChildren, nextChildren, mountImages, removedNodes, transaction, hostParent, hostContainerInfo, context, selfDebugID) // 0 in production and for roots
	  {
	    // We currently don't have a way to track moves here but if we use iterators
	    // instead of for..in we can zip the iterators and check if an item has
	    // moved.
	    // TODO: If nothing has changed, return the prevChildren object so that we
	    // can quickly bailout if nothing has changed.
	    if (!nextChildren && !prevChildren) {
	      return;
	    }
	    var name;
	    var prevChild;
	    for (name in nextChildren) {
	      if (!nextChildren.hasOwnProperty(name)) {
	        continue;
	      }
	      prevChild = prevChildren && prevChildren[name];
	      var prevElement = prevChild && prevChild._currentElement;
	      var nextElement = nextChildren[name];
	      if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {
	        ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);
	        nextChildren[name] = prevChild;
	      } else {
	        if (prevChild) {
	          removedNodes[name] = ReactReconciler.getHostNode(prevChild);
	          ReactReconciler.unmountComponent(prevChild, false);
	        }
	        // The child must be instantiated before it's mounted.
	        var nextChildInstance = instantiateReactComponent(nextElement, true);
	        nextChildren[name] = nextChildInstance;
	        // Creating mount image now ensures refs are resolved in right order
	        // (see https://github.com/facebook/react/pull/7101 for explanation).
	        var nextChildMountImage = ReactReconciler.mountComponent(nextChildInstance, transaction, hostParent, hostContainerInfo, context, selfDebugID);
	        mountImages.push(nextChildMountImage);
	      }
	    }
	    // Unmount children that are no longer present.
	    for (name in prevChildren) {
	      if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {
	        prevChild = prevChildren[name];
	        removedNodes[name] = ReactReconciler.getHostNode(prevChild);
	        ReactReconciler.unmountComponent(prevChild, false);
	      }
	    }
	  },

	  /**
	   * Unmounts all rendered children. This should be used to clean up children
	   * when this component is unmounted.
	   *
	   * @param {?object} renderedChildren Previously initialized set of children.
	   * @internal
	   */
	  unmountChildren: function (renderedChildren, safely) {
	    for (var name in renderedChildren) {
	      if (renderedChildren.hasOwnProperty(name)) {
	        var renderedChild = renderedChildren[name];
	        ReactReconciler.unmountComponent(renderedChild, safely);
	      }
	    }
	  }
	};

	module.exports = ReactChildReconciler;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 151 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67),
	    _assign = __webpack_require__(31);

	var ReactCompositeComponent = __webpack_require__(152);
	var ReactEmptyComponent = __webpack_require__(158);
	var ReactHostComponent = __webpack_require__(159);

	var getNextDebugID = __webpack_require__(160);
	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	// To avoid a cyclic dependency, we create the final class in this module
	var ReactCompositeComponentWrapper = function (element) {
	  this.construct(element);
	};

	function getDeclarationErrorAddendum(owner) {
	  if (owner) {
	    var name = owner.getName();
	    if (name) {
	      return ' Check the render method of `' + name + '`.';
	    }
	  }
	  return '';
	}

	/**
	 * Check if the type reference is a known internal type. I.e. not a user
	 * provided composite type.
	 *
	 * @param {function} type
	 * @return {boolean} Returns true if this is a valid internal type.
	 */
	function isInternalComponentType(type) {
	  return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';
	}

	/**
	 * Given a ReactNode, create an instance that will actually be mounted.
	 *
	 * @param {ReactNode} node
	 * @param {boolean} shouldHaveDebugID
	 * @return {object} A new instance of the element's constructor.
	 * @protected
	 */
	function instantiateReactComponent(node, shouldHaveDebugID) {
	  var instance;

	  if (node === null || node === false) {
	    instance = ReactEmptyComponent.create(instantiateReactComponent);
	  } else if (typeof node === 'object') {
	    var element = node;
	    var type = element.type;
	    if (typeof type !== 'function' && typeof type !== 'string') {
	      var info = '';
	      if (process.env.NODE_ENV !== 'production') {
	        if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
	          info += ' You likely forgot to export your component from the file ' + "it's defined in.";
	        }
	      }
	      info += getDeclarationErrorAddendum(element._owner);
	       true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', type == null ? type : typeof type, info) : _prodInvariant('130', type == null ? type : typeof type, info) : void 0;
	    }

	    // Special case string values
	    if (typeof element.type === 'string') {
	      instance = ReactHostComponent.createInternalComponent(element);
	    } else if (isInternalComponentType(element.type)) {
	      // This is temporarily available for custom components that are not string
	      // representations. I.e. ART. Once those are updated to use the string
	      // representation, we can drop this code path.
	      instance = new element.type(element);

	      // We renamed this. Allow the old name for compat. :(
	      if (!instance.getHostNode) {
	        instance.getHostNode = instance.getNativeNode;
	      }
	    } else {
	      instance = new ReactCompositeComponentWrapper(element);
	    }
	  } else if (typeof node === 'string' || typeof node === 'number') {
	    instance = ReactHostComponent.createInstanceForText(node);
	  } else {
	     true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : _prodInvariant('131', typeof node) : void 0;
	  }

	  if (process.env.NODE_ENV !== 'production') {
	    process.env.NODE_ENV !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getHostNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;
	  }

	  // These two fields are used by the DOM and ART diffing algorithms
	  // respectively. Instead of using expandos on components, we should be
	  // storing the state needed by the diffing algorithms elsewhere.
	  instance._mountIndex = 0;
	  instance._mountImage = null;

	  if (process.env.NODE_ENV !== 'production') {
	    instance._debugID = shouldHaveDebugID ? getNextDebugID() : 0;
	  }

	  // Internal instances should fully constructed at this point, so they should
	  // not get any new fields added to them at this point.
	  if (process.env.NODE_ENV !== 'production') {
	    if (Object.preventExtensions) {
	      Object.preventExtensions(instance);
	    }
	  }

	  return instance;
	}

	_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent, {
	  _instantiateReactComponent: instantiateReactComponent
	});

	module.exports = instantiateReactComponent;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 152 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67),
	    _assign = __webpack_require__(31);

	var React = __webpack_require__(29);
	var ReactComponentEnvironment = __webpack_require__(148);
	var ReactCurrentOwner = __webpack_require__(44);
	var ReactErrorUtils = __webpack_require__(77);
	var ReactInstanceMap = __webpack_require__(149);
	var ReactInstrumentation = __webpack_require__(94);
	var ReactNodeTypes = __webpack_require__(153);
	var ReactReconciler = __webpack_require__(91);

	if (process.env.NODE_ENV !== 'production') {
	  var checkReactTypeSpec = __webpack_require__(154);
	}

	var emptyObject = __webpack_require__(38);
	var invariant = __webpack_require__(39);
	var shallowEqual = __webpack_require__(156);
	var shouldUpdateReactComponent = __webpack_require__(157);
	var warning = __webpack_require__(35);

	var CompositeTypes = {
	  ImpureClass: 0,
	  PureClass: 1,
	  StatelessFunctional: 2
	};

	function StatelessComponent(Component) {}
	StatelessComponent.prototype.render = function () {
	  var Component = ReactInstanceMap.get(this)._currentElement.type;
	  var element = Component(this.props, this.context, this.updater);
	  warnIfInvalidElement(Component, element);
	  return element;
	};

	function warnIfInvalidElement(Component, element) {
	  if (process.env.NODE_ENV !== 'production') {
	    process.env.NODE_ENV !== 'production' ? warning(element === null || element === false || React.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;
	    process.env.NODE_ENV !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0;
	  }
	}

	function shouldConstruct(Component) {
	  return !!(Component.prototype && Component.prototype.isReactComponent);
	}

	function isPureComponent(Component) {
	  return !!(Component.prototype && Component.prototype.isPureReactComponent);
	}

	// Separated into a function to contain deoptimizations caused by try/finally.
	function measureLifeCyclePerf(fn, debugID, timerType) {
	  if (debugID === 0) {
	    // Top-level wrappers (see ReactMount) and empty components (see
	    // ReactDOMEmptyComponent) are invisible to hooks and devtools.
	    // Both are implementation details that should go away in the future.
	    return fn();
	  }

	  ReactInstrumentation.debugTool.onBeginLifeCycleTimer(debugID, timerType);
	  try {
	    return fn();
	  } finally {
	    ReactInstrumentation.debugTool.onEndLifeCycleTimer(debugID, timerType);
	  }
	}

	/**
	 * ------------------ The Life-Cycle of a Composite Component ------------------
	 *
	 * - constructor: Initialization of state. The instance is now retained.
	 *   - componentWillMount
	 *   - render
	 *   - [children's constructors]
	 *     - [children's componentWillMount and render]
	 *     - [children's componentDidMount]
	 *     - componentDidMount
	 *
	 *       Update Phases:
	 *       - componentWillReceiveProps (only called if parent updated)
	 *       - shouldComponentUpdate
	 *         - componentWillUpdate
	 *           - render
	 *           - [children's constructors or receive props phases]
	 *         - componentDidUpdate
	 *
	 *     - componentWillUnmount
	 *     - [children's componentWillUnmount]
	 *   - [children destroyed]
	 * - (destroyed): The instance is now blank, released by React and ready for GC.
	 *
	 * -----------------------------------------------------------------------------
	 */

	/**
	 * An incrementing ID assigned to each component when it is mounted. This is
	 * used to enforce the order in which `ReactUpdates` updates dirty components.
	 *
	 * @private
	 */
	var nextMountID = 1;

	/**
	 * @lends {ReactCompositeComponent.prototype}
	 */
	var ReactCompositeComponent = {
	  /**
	   * Base constructor for all composite component.
	   *
	   * @param {ReactElement} element
	   * @final
	   * @internal
	   */
	  construct: function (element) {
	    this._currentElement = element;
	    this._rootNodeID = 0;
	    this._compositeType = null;
	    this._instance = null;
	    this._hostParent = null;
	    this._hostContainerInfo = null;

	    // See ReactUpdateQueue
	    this._updateBatchNumber = null;
	    this._pendingElement = null;
	    this._pendingStateQueue = null;
	    this._pendingReplaceState = false;
	    this._pendingForceUpdate = false;

	    this._renderedNodeType = null;
	    this._renderedComponent = null;
	    this._context = null;
	    this._mountOrder = 0;
	    this._topLevelWrapper = null;

	    // See ReactUpdates and ReactUpdateQueue.
	    this._pendingCallbacks = null;

	    // ComponentWillUnmount shall only be called once
	    this._calledComponentWillUnmount = false;

	    if (process.env.NODE_ENV !== 'production') {
	      this._warnedAboutRefsInRender = false;
	    }
	  },

	  /**
	   * Initializes the component, renders markup, and registers event listeners.
	   *
	   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
	   * @param {?object} hostParent
	   * @param {?object} hostContainerInfo
	   * @param {?object} context
	   * @return {?string} Rendered markup to be inserted into the DOM.
	   * @final
	   * @internal
	   */
	  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
	    var _this = this;

	    this._context = context;
	    this._mountOrder = nextMountID++;
	    this._hostParent = hostParent;
	    this._hostContainerInfo = hostContainerInfo;

	    var publicProps = this._currentElement.props;
	    var publicContext = this._processContext(context);

	    var Component = this._currentElement.type;

	    var updateQueue = transaction.getUpdateQueue();

	    // Initialize the public class
	    var doConstruct = shouldConstruct(Component);
	    var inst = this._constructComponent(doConstruct, publicProps, publicContext, updateQueue);
	    var renderedElement;

	    // Support functional components
	    if (!doConstruct && (inst == null || inst.render == null)) {
	      renderedElement = inst;
	      warnIfInvalidElement(Component, renderedElement);
	      !(inst === null || inst === false || React.isValidElement(inst)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0;
	      inst = new StatelessComponent(Component);
	      this._compositeType = CompositeTypes.StatelessFunctional;
	    } else {
	      if (isPureComponent(Component)) {
	        this._compositeType = CompositeTypes.PureClass;
	      } else {
	        this._compositeType = CompositeTypes.ImpureClass;
	      }
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      // This will throw later in _renderValidatedComponent, but add an early
	      // warning now to help debugging
	      if (inst.render == null) {
	        process.env.NODE_ENV !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0;
	      }

	      var propsMutated = inst.props !== publicProps;
	      var componentName = Component.displayName || Component.name || 'Component';

	      process.env.NODE_ENV !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + "up the same props that your component's constructor was passed.", componentName, componentName) : void 0;
	    }

	    // These should be set up in the constructor, but as a convenience for
	    // simpler class abstractions, we set them up after the fact.
	    inst.props = publicProps;
	    inst.context = publicContext;
	    inst.refs = emptyObject;
	    inst.updater = updateQueue;

	    this._instance = inst;

	    // Store a reference from the instance back to the internal representation
	    ReactInstanceMap.set(inst, this);

	    if (process.env.NODE_ENV !== 'production') {
	      // Since plain JS classes are defined without any special initialization
	      // logic, we can not catch common errors early. Therefore, we have to
	      // catch them here, at initialization time, instead.
	      process.env.NODE_ENV !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved || inst.state, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0;
	      process.env.NODE_ENV !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0;
	      process.env.NODE_ENV !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0;
	      process.env.NODE_ENV !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0;
	      process.env.NODE_ENV !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : void 0;
	      process.env.NODE_ENV !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0;
	      process.env.NODE_ENV !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0;
	    }

	    var initialState = inst.state;
	    if (initialState === undefined) {
	      inst.state = initialState = null;
	    }
	    !(typeof initialState === 'object' && !Array.isArray(initialState)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;

	    this._pendingStateQueue = null;
	    this._pendingReplaceState = false;
	    this._pendingForceUpdate = false;

	    var markup;
	    if (inst.unstable_handleError) {
	      markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);
	    } else {
	      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
	    }

	    if (inst.componentDidMount) {
	      if (process.env.NODE_ENV !== 'production') {
	        transaction.getReactMountReady().enqueue(function () {
	          measureLifeCyclePerf(function () {
	            return inst.componentDidMount();
	          }, _this._debugID, 'componentDidMount');
	        });
	      } else {
	        transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
	      }
	    }

	    return markup;
	  },

	  _constructComponent: function (doConstruct, publicProps, publicContext, updateQueue) {
	    if (process.env.NODE_ENV !== 'production' && !doConstruct) {
	      ReactCurrentOwner.current = this;
	      try {
	        return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);
	      } finally {
	        ReactCurrentOwner.current = null;
	      }
	    } else {
	      return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);
	    }
	  },

	  _constructComponentWithoutOwner: function (doConstruct, publicProps, publicContext, updateQueue) {
	    var Component = this._currentElement.type;

	    if (doConstruct) {
	      if (process.env.NODE_ENV !== 'production') {
	        return measureLifeCyclePerf(function () {
	          return new Component(publicProps, publicContext, updateQueue);
	        }, this._debugID, 'ctor');
	      } else {
	        return new Component(publicProps, publicContext, updateQueue);
	      }
	    }

	    // This can still be an instance in case of factory components
	    // but we'll count this as time spent rendering as the more common case.
	    if (process.env.NODE_ENV !== 'production') {
	      return measureLifeCyclePerf(function () {
	        return Component(publicProps, publicContext, updateQueue);
	      }, this._debugID, 'render');
	    } else {
	      return Component(publicProps, publicContext, updateQueue);
	    }
	  },

	  performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
	    var markup;
	    var checkpoint = transaction.checkpoint();
	    try {
	      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
	    } catch (e) {
	      // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint
	      transaction.rollback(checkpoint);
	      this._instance.unstable_handleError(e);
	      if (this._pendingStateQueue) {
	        this._instance.state = this._processPendingState(this._instance.props, this._instance.context);
	      }
	      checkpoint = transaction.checkpoint();

	      this._renderedComponent.unmountComponent(true);
	      transaction.rollback(checkpoint);

	      // Try again - we've informed the component about the error, so they can render an error message this time.
	      // If this throws again, the error will bubble up (and can be caught by a higher error boundary).
	      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
	    }
	    return markup;
	  },

	  performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
	    var inst = this._instance;

	    var debugID = 0;
	    if (process.env.NODE_ENV !== 'production') {
	      debugID = this._debugID;
	    }

	    if (inst.componentWillMount) {
	      if (process.env.NODE_ENV !== 'production') {
	        measureLifeCyclePerf(function () {
	          return inst.componentWillMount();
	        }, debugID, 'componentWillMount');
	      } else {
	        inst.componentWillMount();
	      }
	      // When mounting, calls to `setState` by `componentWillMount` will set
	      // `this._pendingStateQueue` without triggering a re-render.
	      if (this._pendingStateQueue) {
	        inst.state = this._processPendingState(inst.props, inst.context);
	      }
	    }

	    // If not a stateless component, we now render
	    if (renderedElement === undefined) {
	      renderedElement = this._renderValidatedComponent();
	    }

	    var nodeType = ReactNodeTypes.getType(renderedElement);
	    this._renderedNodeType = nodeType;
	    var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */
	    );
	    this._renderedComponent = child;

	    var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context), debugID);

	    if (process.env.NODE_ENV !== 'production') {
	      if (debugID !== 0) {
	        var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
	        ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
	      }
	    }

	    return markup;
	  },

	  getHostNode: function () {
	    return ReactReconciler.getHostNode(this._renderedComponent);
	  },

	  /**
	   * Releases any resources allocated by `mountComponent`.
	   *
	   * @final
	   * @internal
	   */
	  unmountComponent: function (safely) {
	    if (!this._renderedComponent) {
	      return;
	    }

	    var inst = this._instance;

	    if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
	      inst._calledComponentWillUnmount = true;

	      if (safely) {
	        var name = this.getName() + '.componentWillUnmount()';
	        ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));
	      } else {
	        if (process.env.NODE_ENV !== 'production') {
	          measureLifeCyclePerf(function () {
	            return inst.componentWillUnmount();
	          }, this._debugID, 'componentWillUnmount');
	        } else {
	          inst.componentWillUnmount();
	        }
	      }
	    }

	    if (this._renderedComponent) {
	      ReactReconciler.unmountComponent(this._renderedComponent, safely);
	      this._renderedNodeType = null;
	      this._renderedComponent = null;
	      this._instance = null;
	    }

	    // Reset pending fields
	    // Even if this component is scheduled for another update in ReactUpdates,
	    // it would still be ignored because these fields are reset.
	    this._pendingStateQueue = null;
	    this._pendingReplaceState = false;
	    this._pendingForceUpdate = false;
	    this._pendingCallbacks = null;
	    this._pendingElement = null;

	    // These fields do not really need to be reset since this object is no
	    // longer accessible.
	    this._context = null;
	    this._rootNodeID = 0;
	    this._topLevelWrapper = null;

	    // Delete the reference from the instance to this internal representation
	    // which allow the internals to be properly cleaned up even if the user
	    // leaks a reference to the public instance.
	    ReactInstanceMap.remove(inst);

	    // Some existing components rely on inst.props even after they've been
	    // destroyed (in event handlers).
	    // TODO: inst.props = null;
	    // TODO: inst.state = null;
	    // TODO: inst.context = null;
	  },

	  /**
	   * Filters the context object to only contain keys specified in
	   * `contextTypes`
	   *
	   * @param {object} context
	   * @return {?object}
	   * @private
	   */
	  _maskContext: function (context) {
	    var Component = this._currentElement.type;
	    var contextTypes = Component.contextTypes;
	    if (!contextTypes) {
	      return emptyObject;
	    }
	    var maskedContext = {};
	    for (var contextName in contextTypes) {
	      maskedContext[contextName] = context[contextName];
	    }
	    return maskedContext;
	  },

	  /**
	   * Filters the context object to only contain keys specified in
	   * `contextTypes`, and asserts that they are valid.
	   *
	   * @param {object} context
	   * @return {?object}
	   * @private
	   */
	  _processContext: function (context) {
	    var maskedContext = this._maskContext(context);
	    if (process.env.NODE_ENV !== 'production') {
	      var Component = this._currentElement.type;
	      if (Component.contextTypes) {
	        this._checkContextTypes(Component.contextTypes, maskedContext, 'context');
	      }
	    }
	    return maskedContext;
	  },

	  /**
	   * @param {object} currentContext
	   * @return {object}
	   * @private
	   */
	  _processChildContext: function (currentContext) {
	    var Component = this._currentElement.type;
	    var inst = this._instance;
	    var childContext;

	    if (inst.getChildContext) {
	      if (process.env.NODE_ENV !== 'production') {
	        ReactInstrumentation.debugTool.onBeginProcessingChildContext();
	        try {
	          childContext = inst.getChildContext();
	        } finally {
	          ReactInstrumentation.debugTool.onEndProcessingChildContext();
	        }
	      } else {
	        childContext = inst.getChildContext();
	      }
	    }

	    if (childContext) {
	      !(typeof Component.childContextTypes === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;
	      if (process.env.NODE_ENV !== 'production') {
	        this._checkContextTypes(Component.childContextTypes, childContext, 'child context');
	      }
	      for (var name in childContext) {
	        !(name in Component.childContextTypes) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0;
	      }
	      return _assign({}, currentContext, childContext);
	    }
	    return currentContext;
	  },

	  /**
	   * Assert that the context types are valid
	   *
	   * @param {object} typeSpecs Map of context field to a ReactPropType
	   * @param {object} values Runtime values that need to be type-checked
	   * @param {string} location e.g. "prop", "context", "child context"
	   * @private
	   */
	  _checkContextTypes: function (typeSpecs, values, location) {
	    if (process.env.NODE_ENV !== 'production') {
	      checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);
	    }
	  },

	  receiveComponent: function (nextElement, transaction, nextContext) {
	    var prevElement = this._currentElement;
	    var prevContext = this._context;

	    this._pendingElement = null;

	    this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);
	  },

	  /**
	   * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`
	   * is set, update the component.
	   *
	   * @param {ReactReconcileTransaction} transaction
	   * @internal
	   */
	  performUpdateIfNecessary: function (transaction) {
	    if (this._pendingElement != null) {
	      ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);
	    } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
	      this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);
	    } else {
	      this._updateBatchNumber = null;
	    }
	  },

	  /**
	   * Perform an update to a mounted component. The componentWillReceiveProps and
	   * shouldComponentUpdate methods are called, then (assuming the update isn't
	   * skipped) the remaining update lifecycle methods are called and the DOM
	   * representation is updated.
	   *
	   * By default, this implements React's rendering and reconciliation algorithm.
	   * Sophisticated clients may wish to override this.
	   *
	   * @param {ReactReconcileTransaction} transaction
	   * @param {ReactElement} prevParentElement
	   * @param {ReactElement} nextParentElement
	   * @internal
	   * @overridable
	   */
	  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {
	    var inst = this._instance;
	    !(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0;

	    var willReceive = false;
	    var nextContext;

	    // Determine if the context has changed or not
	    if (this._context === nextUnmaskedContext) {
	      nextContext = inst.context;
	    } else {
	      nextContext = this._processContext(nextUnmaskedContext);
	      willReceive = true;
	    }

	    var prevProps = prevParentElement.props;
	    var nextProps = nextParentElement.props;

	    // Not a simple state update but a props update
	    if (prevParentElement !== nextParentElement) {
	      willReceive = true;
	    }

	    // An update here will schedule an update but immediately set
	    // _pendingStateQueue which will ensure that any state updates gets
	    // immediately reconciled instead of waiting for the next batch.
	    if (willReceive && inst.componentWillReceiveProps) {
	      if (process.env.NODE_ENV !== 'production') {
	        measureLifeCyclePerf(function () {
	          return inst.componentWillReceiveProps(nextProps, nextContext);
	        }, this._debugID, 'componentWillReceiveProps');
	      } else {
	        inst.componentWillReceiveProps(nextProps, nextContext);
	      }
	    }

	    var nextState = this._processPendingState(nextProps, nextContext);
	    var shouldUpdate = true;

	    if (!this._pendingForceUpdate) {
	      if (inst.shouldComponentUpdate) {
	        if (process.env.NODE_ENV !== 'production') {
	          shouldUpdate = measureLifeCyclePerf(function () {
	            return inst.shouldComponentUpdate(nextProps, nextState, nextContext);
	          }, this._debugID, 'shouldComponentUpdate');
	        } else {
	          shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
	        }
	      } else {
	        if (this._compositeType === CompositeTypes.PureClass) {
	          shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);
	        }
	      }
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      process.env.NODE_ENV !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;
	    }

	    this._updateBatchNumber = null;
	    if (shouldUpdate) {
	      this._pendingForceUpdate = false;
	      // Will set `this.props`, `this.state` and `this.context`.
	      this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);
	    } else {
	      // If it's determined that a component should not update, we still want
	      // to set props and state but we shortcut the rest of the update.
	      this._currentElement = nextParentElement;
	      this._context = nextUnmaskedContext;
	      inst.props = nextProps;
	      inst.state = nextState;
	      inst.context = nextContext;
	    }
	  },

	  _processPendingState: function (props, context) {
	    var inst = this._instance;
	    var queue = this._pendingStateQueue;
	    var replace = this._pendingReplaceState;
	    this._pendingReplaceState = false;
	    this._pendingStateQueue = null;

	    if (!queue) {
	      return inst.state;
	    }

	    if (replace && queue.length === 1) {
	      return queue[0];
	    }

	    var nextState = _assign({}, replace ? queue[0] : inst.state);
	    for (var i = replace ? 1 : 0; i < queue.length; i++) {
	      var partial = queue[i];
	      _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);
	    }

	    return nextState;
	  },

	  /**
	   * Merges new props and state, notifies delegate methods of update and
	   * performs update.
	   *
	   * @param {ReactElement} nextElement Next element
	   * @param {object} nextProps Next public object to set as properties.
	   * @param {?object} nextState Next object to set as state.
	   * @param {?object} nextContext Next public object to set as context.
	   * @param {ReactReconcileTransaction} transaction
	   * @param {?object} unmaskedContext
	   * @private
	   */
	  _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {
	    var _this2 = this;

	    var inst = this._instance;

	    var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);
	    var prevProps;
	    var prevState;
	    var prevContext;
	    if (hasComponentDidUpdate) {
	      prevProps = inst.props;
	      prevState = inst.state;
	      prevContext = inst.context;
	    }

	    if (inst.componentWillUpdate) {
	      if (process.env.NODE_ENV !== 'production') {
	        measureLifeCyclePerf(function () {
	          return inst.componentWillUpdate(nextProps, nextState, nextContext);
	        }, this._debugID, 'componentWillUpdate');
	      } else {
	        inst.componentWillUpdate(nextProps, nextState, nextContext);
	      }
	    }

	    this._currentElement = nextElement;
	    this._context = unmaskedContext;
	    inst.props = nextProps;
	    inst.state = nextState;
	    inst.context = nextContext;

	    this._updateRenderedComponent(transaction, unmaskedContext);

	    if (hasComponentDidUpdate) {
	      if (process.env.NODE_ENV !== 'production') {
	        transaction.getReactMountReady().enqueue(function () {
	          measureLifeCyclePerf(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), _this2._debugID, 'componentDidUpdate');
	        });
	      } else {
	        transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
	      }
	    }
	  },

	  /**
	   * Call the component's `render` method and update the DOM accordingly.
	   *
	   * @param {ReactReconcileTransaction} transaction
	   * @internal
	   */
	  _updateRenderedComponent: function (transaction, context) {
	    var prevComponentInstance = this._renderedComponent;
	    var prevRenderedElement = prevComponentInstance._currentElement;
	    var nextRenderedElement = this._renderValidatedComponent();

	    var debugID = 0;
	    if (process.env.NODE_ENV !== 'production') {
	      debugID = this._debugID;
	    }

	    if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
	      ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));
	    } else {
	      var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);
	      ReactReconciler.unmountComponent(prevComponentInstance, false);

	      var nodeType = ReactNodeTypes.getType(nextRenderedElement);
	      this._renderedNodeType = nodeType;
	      var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */
	      );
	      this._renderedComponent = child;

	      var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context), debugID);

	      if (process.env.NODE_ENV !== 'production') {
	        if (debugID !== 0) {
	          var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
	          ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
	        }
	      }

	      this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);
	    }
	  },

	  /**
	   * Overridden in shallow rendering.
	   *
	   * @protected
	   */
	  _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {
	    ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);
	  },

	  /**
	   * @protected
	   */
	  _renderValidatedComponentWithoutOwnerOrContext: function () {
	    var inst = this._instance;
	    var renderedElement;

	    if (process.env.NODE_ENV !== 'production') {
	      renderedElement = measureLifeCyclePerf(function () {
	        return inst.render();
	      }, this._debugID, 'render');
	    } else {
	      renderedElement = inst.render();
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      // We allow auto-mocks to proceed as if they're returning null.
	      if (renderedElement === undefined && inst.render._isMockFunction) {
	        // This is probably bad practice. Consider warning here and
	        // deprecating this convenience.
	        renderedElement = null;
	      }
	    }

	    return renderedElement;
	  },

	  /**
	   * @private
	   */
	  _renderValidatedComponent: function () {
	    var renderedElement;
	    if (process.env.NODE_ENV !== 'production' || this._compositeType !== CompositeTypes.StatelessFunctional) {
	      ReactCurrentOwner.current = this;
	      try {
	        renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();
	      } finally {
	        ReactCurrentOwner.current = null;
	      }
	    } else {
	      renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();
	    }
	    !(
	    // TODO: An `isValidNode` function would probably be more appropriate
	    renderedElement === null || renderedElement === false || React.isValidElement(renderedElement)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0;

	    return renderedElement;
	  },

	  /**
	   * Lazily allocates the refs object and stores `component` as `ref`.
	   *
	   * @param {string} ref Reference name.
	   * @param {component} component Component to store as `ref`.
	   * @final
	   * @private
	   */
	  attachRef: function (ref, component) {
	    var inst = this.getPublicInstance();
	    !(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0;
	    var publicComponentInstance = component.getPublicInstance();
	    if (process.env.NODE_ENV !== 'production') {
	      var componentName = component && component.getName ? component.getName() : 'a component';
	      process.env.NODE_ENV !== 'production' ? warning(publicComponentInstance != null || component._compositeType !== CompositeTypes.StatelessFunctional, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;
	    }
	    var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;
	    refs[ref] = publicComponentInstance;
	  },

	  /**
	   * Detaches a reference name.
	   *
	   * @param {string} ref Name to dereference.
	   * @final
	   * @private
	   */
	  detachRef: function (ref) {
	    var refs = this.getPublicInstance().refs;
	    delete refs[ref];
	  },

	  /**
	   * Get a text description of the component that can be used to identify it
	   * in error messages.
	   * @return {string} The name or null.
	   * @internal
	   */
	  getName: function () {
	    var type = this._currentElement.type;
	    var constructor = this._instance && this._instance.constructor;
	    return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;
	  },

	  /**
	   * Get the publicly accessible representation of this component - i.e. what
	   * is exposed by refs and returned by render. Can be null for stateless
	   * components.
	   *
	   * @return {ReactComponent} the public component instance.
	   * @internal
	   */
	  getPublicInstance: function () {
	    var inst = this._instance;
	    if (this._compositeType === CompositeTypes.StatelessFunctional) {
	      return null;
	    }
	    return inst;
	  },

	  // Stub
	  _instantiateReactComponent: null
	};

	module.exports = ReactCompositeComponent;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 153 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var React = __webpack_require__(29);

	var invariant = __webpack_require__(39);

	var ReactNodeTypes = {
	  HOST: 0,
	  COMPOSITE: 1,
	  EMPTY: 2,

	  getType: function (node) {
	    if (node === null || node === false) {
	      return ReactNodeTypes.EMPTY;
	    } else if (React.isValidElement(node)) {
	      if (typeof node.type === 'function') {
	        return ReactNodeTypes.COMPOSITE;
	      } else {
	        return ReactNodeTypes.HOST;
	      }
	    }
	     true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unexpected node: %s', node) : _prodInvariant('26', node) : void 0;
	  }
	};

	module.exports = ReactNodeTypes;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 154 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var ReactPropTypeLocationNames = __webpack_require__(155);
	var ReactPropTypesSecret = __webpack_require__(143);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	var ReactComponentTreeHook;

	if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'test') {
	  // Temporary hack.
	  // Inline requires don't work well with Jest:
	  // https://github.com/facebook/react/issues/7240
	  // Remove the inline requires when we don't need them anymore:
	  // https://github.com/facebook/react/pull/7178
	  ReactComponentTreeHook = __webpack_require__(51);
	}

	var loggedTypeFailures = {};

	/**
	 * Assert that the values match with the type specs.
	 * Error messages are memorized and will only be shown once.
	 *
	 * @param {object} typeSpecs Map of name to a ReactPropType
	 * @param {object} values Runtime values that need to be type-checked
	 * @param {string} location e.g. "prop", "context", "child context"
	 * @param {string} componentName Name of the component for error messages.
	 * @param {?object} element The React element that is being type-checked
	 * @param {?number} debugID The React component instance that is being type-checked
	 * @private
	 */
	function checkReactTypeSpec(typeSpecs, values, location, componentName, element, debugID) {
	  for (var typeSpecName in typeSpecs) {
	    if (typeSpecs.hasOwnProperty(typeSpecName)) {
	      var error;
	      // Prop type validation may throw. In case they do, we don't want to
	      // fail the render phase where it didn't fail before. So we log it.
	      // After these have been cleaned up, we'll let them throw.
	      try {
	        // This is intentionally an invariant that gets caught. It's the same
	        // behavior as without this statement except with a better message.
	        !(typeof typeSpecs[typeSpecName] === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : _prodInvariant('84', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : void 0;
	        error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
	      } catch (ex) {
	        error = ex;
	      }
	      process.env.NODE_ENV !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName, typeof error) : void 0;
	      if (error instanceof Error && !(error.message in loggedTypeFailures)) {
	        // Only monitor this failure once because there tends to be a lot of the
	        // same error.
	        loggedTypeFailures[error.message] = true;

	        var componentStackInfo = '';

	        if (process.env.NODE_ENV !== 'production') {
	          if (!ReactComponentTreeHook) {
	            ReactComponentTreeHook = __webpack_require__(51);
	          }
	          if (debugID !== null) {
	            componentStackInfo = ReactComponentTreeHook.getStackAddendumByID(debugID);
	          } else if (element !== null) {
	            componentStackInfo = ReactComponentTreeHook.getCurrentStackAddendum(element);
	          }
	        }

	        process.env.NODE_ENV !== 'production' ? warning(false, 'Failed %s type: %s%s', location, error.message, componentStackInfo) : void 0;
	      }
	    }
	  }
	}

	module.exports = checkReactTypeSpec;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 155 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var ReactPropTypeLocationNames = {};

	if (process.env.NODE_ENV !== 'production') {
	  ReactPropTypeLocationNames = {
	    prop: 'prop',
	    context: 'context',
	    childContext: 'child context'
	  };
	}

	module.exports = ReactPropTypeLocationNames;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 156 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 * 
	 */

	/*eslint-disable no-self-compare */

	'use strict';

	var hasOwnProperty = Object.prototype.hasOwnProperty;

	/**
	 * inlined Object.is polyfill to avoid requiring consumers ship their own
	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
	 */
	function is(x, y) {
	  // SameValue algorithm
	  if (x === y) {
	    // Steps 1-5, 7-10
	    // Steps 6.b-6.e: +0 != -0
	    // Added the nonzero y check to make Flow happy, but it is redundant
	    return x !== 0 || y !== 0 || 1 / x === 1 / y;
	  } else {
	    // Step 6.a: NaN == NaN
	    return x !== x && y !== y;
	  }
	}

	/**
	 * Performs equality by iterating through keys on an object and returning false
	 * when any key has values which are not strictly equal between the arguments.
	 * Returns true when the values of all keys are strictly equal.
	 */
	function shallowEqual(objA, objB) {
	  if (is(objA, objB)) {
	    return true;
	  }

	  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
	    return false;
	  }

	  var keysA = Object.keys(objA);
	  var keysB = Object.keys(objB);

	  if (keysA.length !== keysB.length) {
	    return false;
	  }

	  // Test for A's keys different from B.
	  for (var i = 0; i < keysA.length; i++) {
	    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
	      return false;
	    }
	  }

	  return true;
	}

	module.exports = shallowEqual;

/***/ },
/* 157 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * Given a `prevElement` and `nextElement`, determines if the existing
	 * instance should be updated as opposed to being destroyed or replaced by a new
	 * instance. Both arguments are elements. This ensures that this logic can
	 * operate on stateless trees without any backing instance.
	 *
	 * @param {?object} prevElement
	 * @param {?object} nextElement
	 * @return {boolean} True if the existing instance should be updated.
	 * @protected
	 */

	function shouldUpdateReactComponent(prevElement, nextElement) {
	  var prevEmpty = prevElement === null || prevElement === false;
	  var nextEmpty = nextElement === null || nextElement === false;
	  if (prevEmpty || nextEmpty) {
	    return prevEmpty === nextEmpty;
	  }

	  var prevType = typeof prevElement;
	  var nextType = typeof nextElement;
	  if (prevType === 'string' || prevType === 'number') {
	    return nextType === 'string' || nextType === 'number';
	  } else {
	    return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key;
	  }
	}

	module.exports = shouldUpdateReactComponent;

/***/ },
/* 158 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var emptyComponentFactory;

	var ReactEmptyComponentInjection = {
	  injectEmptyComponentFactory: function (factory) {
	    emptyComponentFactory = factory;
	  }
	};

	var ReactEmptyComponent = {
	  create: function (instantiate) {
	    return emptyComponentFactory(instantiate);
	  }
	};

	ReactEmptyComponent.injection = ReactEmptyComponentInjection;

	module.exports = ReactEmptyComponent;

/***/ },
/* 159 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	var genericComponentClass = null;
	var textComponentClass = null;

	var ReactHostComponentInjection = {
	  // This accepts a class that receives the tag string. This is a catch all
	  // that can render any kind of tag.
	  injectGenericComponentClass: function (componentClass) {
	    genericComponentClass = componentClass;
	  },
	  // This accepts a text component class that takes the text string to be
	  // rendered as props.
	  injectTextComponentClass: function (componentClass) {
	    textComponentClass = componentClass;
	  }
	};

	/**
	 * Get a host internal component class for a specific tag.
	 *
	 * @param {ReactElement} element The element to create.
	 * @return {function} The internal class constructor function.
	 */
	function createInternalComponent(element) {
	  !genericComponentClass ? process.env.NODE_ENV !== 'production' ? invariant(false, 'There is no registered component for the tag %s', element.type) : _prodInvariant('111', element.type) : void 0;
	  return new genericComponentClass(element);
	}

	/**
	 * @param {ReactText} text
	 * @return {ReactComponent}
	 */
	function createInstanceForText(text) {
	  return new textComponentClass(text);
	}

	/**
	 * @param {ReactComponent} component
	 * @return {boolean}
	 */
	function isTextComponent(component) {
	  return component instanceof textComponentClass;
	}

	var ReactHostComponent = {
	  createInternalComponent: createInternalComponent,
	  createInstanceForText: createInstanceForText,
	  isTextComponent: isTextComponent,
	  injection: ReactHostComponentInjection
	};

	module.exports = ReactHostComponent;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 160 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var nextDebugID = 1;

	function getNextDebugID() {
	  return nextDebugID++;
	}

	module.exports = getNextDebugID;

/***/ },
/* 161 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	/**
	 * Escape and wrap key so it is safe to use as a reactid
	 *
	 * @param {string} key to be escaped.
	 * @return {string} the escaped key.
	 */

	function escape(key) {
	  var escapeRegex = /[=:]/g;
	  var escaperLookup = {
	    '=': '=0',
	    ':': '=2'
	  };
	  var escapedString = ('' + key).replace(escapeRegex, function (match) {
	    return escaperLookup[match];
	  });

	  return '$' + escapedString;
	}

	/**
	 * Unescape and unwrap key for human-readable display
	 *
	 * @param {string} key to unescape.
	 * @return {string} the unescaped key.
	 */
	function unescape(key) {
	  var unescapeRegex = /(=0|=2)/g;
	  var unescaperLookup = {
	    '=0': '=',
	    '=2': ':'
	  };
	  var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);

	  return ('' + keySubstring).replace(unescapeRegex, function (match) {
	    return unescaperLookup[match];
	  });
	}

	var KeyEscapeUtils = {
	  escape: escape,
	  unescape: unescape
	};

	module.exports = KeyEscapeUtils;

/***/ },
/* 162 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var ReactCurrentOwner = __webpack_require__(44);
	var REACT_ELEMENT_TYPE = __webpack_require__(163);

	var getIteratorFn = __webpack_require__(164);
	var invariant = __webpack_require__(39);
	var KeyEscapeUtils = __webpack_require__(161);
	var warning = __webpack_require__(35);

	var SEPARATOR = '.';
	var SUBSEPARATOR = ':';

	/**
	 * This is inlined from ReactElement since this file is shared between
	 * isomorphic and renderers. We could extract this to a
	 *
	 */

	/**
	 * TODO: Test that a single child and an array with one item have the same key
	 * pattern.
	 */

	var didWarnAboutMaps = false;

	/**
	 * Generate a key string that identifies a component within a set.
	 *
	 * @param {*} component A component that could contain a manual key.
	 * @param {number} index Index that is used if a manual key is not provided.
	 * @return {string}
	 */
	function getComponentKey(component, index) {
	  // Do some typechecking here since we call this blindly. We want to ensure
	  // that we don't block potential future ES APIs.
	  if (component && typeof component === 'object' && component.key != null) {
	    // Explicit key
	    return KeyEscapeUtils.escape(component.key);
	  }
	  // Implicit key determined by the index in the set
	  return index.toString(36);
	}

	/**
	 * @param {?*} children Children tree container.
	 * @param {!string} nameSoFar Name of the key path so far.
	 * @param {!function} callback Callback to invoke with each child found.
	 * @param {?*} traverseContext Used to pass information throughout the traversal
	 * process.
	 * @return {!number} The number of children in this subtree.
	 */
	function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {
	  var type = typeof children;

	  if (type === 'undefined' || type === 'boolean') {
	    // All of the above are perceived as null.
	    children = null;
	  }

	  if (children === null || type === 'string' || type === 'number' ||
	  // The following is inlined from ReactElement. This means we can optimize
	  // some checks. React Fiber also inlines this logic for similar purposes.
	  type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE) {
	    callback(traverseContext, children,
	    // If it's the only child, treat the name as if it was wrapped in an array
	    // so that it's consistent if the number of children grows.
	    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);
	    return 1;
	  }

	  var child;
	  var nextName;
	  var subtreeCount = 0; // Count of children found in the current subtree.
	  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;

	  if (Array.isArray(children)) {
	    for (var i = 0; i < children.length; i++) {
	      child = children[i];
	      nextName = nextNamePrefix + getComponentKey(child, i);
	      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
	    }
	  } else {
	    var iteratorFn = getIteratorFn(children);
	    if (iteratorFn) {
	      var iterator = iteratorFn.call(children);
	      var step;
	      if (iteratorFn !== children.entries) {
	        var ii = 0;
	        while (!(step = iterator.next()).done) {
	          child = step.value;
	          nextName = nextNamePrefix + getComponentKey(child, ii++);
	          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
	        }
	      } else {
	        if (process.env.NODE_ENV !== 'production') {
	          var mapsAsChildrenAddendum = '';
	          if (ReactCurrentOwner.current) {
	            var mapsAsChildrenOwnerName = ReactCurrentOwner.current.getName();
	            if (mapsAsChildrenOwnerName) {
	              mapsAsChildrenAddendum = ' Check the render method of `' + mapsAsChildrenOwnerName + '`.';
	            }
	          }
	          process.env.NODE_ENV !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.%s', mapsAsChildrenAddendum) : void 0;
	          didWarnAboutMaps = true;
	        }
	        // Iterator will provide entry [k,v] tuples rather than values.
	        while (!(step = iterator.next()).done) {
	          var entry = step.value;
	          if (entry) {
	            child = entry[1];
	            nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);
	            subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
	          }
	        }
	      }
	    } else if (type === 'object') {
	      var addendum = '';
	      if (process.env.NODE_ENV !== 'production') {
	        addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';
	        if (children._isReactElement) {
	          addendum = " It looks like you're using an element created by a different " + 'version of React. Make sure to use only one copy of React.';
	        }
	        if (ReactCurrentOwner.current) {
	          var name = ReactCurrentOwner.current.getName();
	          if (name) {
	            addendum += ' Check the render method of `' + name + '`.';
	          }
	        }
	      }
	      var childrenString = String(children);
	       true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0;
	    }
	  }

	  return subtreeCount;
	}

	/**
	 * Traverses children that are typically specified as `props.children`, but
	 * might also be specified through attributes:
	 *
	 * - `traverseAllChildren(this.props.children, ...)`
	 * - `traverseAllChildren(this.props.leftPanelChildren, ...)`
	 *
	 * The `traverseContext` is an optional argument that is passed through the
	 * entire traversal. It can be used to store accumulations or anything else that
	 * the callback might find relevant.
	 *
	 * @param {?*} children Children tree object.
	 * @param {!function} callback To invoke upon traversing each child.
	 * @param {?*} traverseContext Context for traversal.
	 * @return {!number} The number of children in this subtree.
	 */
	function traverseAllChildren(children, callback, traverseContext) {
	  if (children == null) {
	    return 0;
	  }

	  return traverseAllChildrenImpl(children, '', callback, traverseContext);
	}

	module.exports = traverseAllChildren;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 163 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	// The Symbol used to tag the ReactElement type. If there is no native Symbol
	// nor polyfill, then a plain number is used for performance.

	var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;

	module.exports = REACT_ELEMENT_TYPE;

/***/ },
/* 164 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	/* global Symbol */

	var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
	var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.

	/**
	 * Returns the iterator method function contained on the iterable object.
	 *
	 * Be sure to invoke the function with the iterable as context:
	 *
	 *     var iteratorFn = getIteratorFn(myIterable);
	 *     if (iteratorFn) {
	 *       var iterator = iteratorFn.call(myIterable);
	 *       ...
	 *     }
	 *
	 * @param {?object} maybeIterable
	 * @return {?function}
	 */
	function getIteratorFn(maybeIterable) {
	  var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
	  if (typeof iteratorFn === 'function') {
	    return iteratorFn;
	  }
	}

	module.exports = getIteratorFn;

/***/ },
/* 165 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var KeyEscapeUtils = __webpack_require__(161);
	var traverseAllChildren = __webpack_require__(162);
	var warning = __webpack_require__(35);

	var ReactComponentTreeHook;

	if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'test') {
	  // Temporary hack.
	  // Inline requires don't work well with Jest:
	  // https://github.com/facebook/react/issues/7240
	  // Remove the inline requires when we don't need them anymore:
	  // https://github.com/facebook/react/pull/7178
	  ReactComponentTreeHook = __webpack_require__(51);
	}

	/**
	 * @param {function} traverseContext Context passed through traversal.
	 * @param {?ReactComponent} child React child component.
	 * @param {!string} name String name of key path to child.
	 * @param {number=} selfDebugID Optional debugID of the current internal instance.
	 */
	function flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID) {
	  // We found a component instance.
	  if (traverseContext && typeof traverseContext === 'object') {
	    var result = traverseContext;
	    var keyUnique = result[name] === undefined;
	    if (process.env.NODE_ENV !== 'production') {
	      if (!ReactComponentTreeHook) {
	        ReactComponentTreeHook = __webpack_require__(51);
	      }
	      if (!keyUnique) {
	        process.env.NODE_ENV !== 'production' ? warning(false, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeHook.getStackAddendumByID(selfDebugID)) : void 0;
	      }
	    }
	    if (keyUnique && child != null) {
	      result[name] = child;
	    }
	  }
	}

	/**
	 * Flattens children that are typically specified as `props.children`. Any null
	 * children will not be included in the resulting object.
	 * @return {!object} flattened children keyed by name.
	 */
	function flattenChildren(children, selfDebugID) {
	  if (children == null) {
	    return children;
	  }
	  var result = {};

	  if (process.env.NODE_ENV !== 'production') {
	    traverseAllChildren(children, function (traverseContext, child, name) {
	      return flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID);
	    }, result);
	  } else {
	    traverseAllChildren(children, flattenSingleChildIntoContext, result);
	  }
	  return result;
	}

	module.exports = flattenChildren;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 166 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var PooledClass = __webpack_require__(82);
	var Transaction = __webpack_require__(100);
	var ReactInstrumentation = __webpack_require__(94);
	var ReactServerUpdateQueue = __webpack_require__(167);

	/**
	 * Executed within the scope of the `Transaction` instance. Consider these as
	 * being member methods, but with an implied ordering while being isolated from
	 * each other.
	 */
	var TRANSACTION_WRAPPERS = [];

	if (process.env.NODE_ENV !== 'production') {
	  TRANSACTION_WRAPPERS.push({
	    initialize: ReactInstrumentation.debugTool.onBeginFlush,
	    close: ReactInstrumentation.debugTool.onEndFlush
	  });
	}

	var noopCallbackQueue = {
	  enqueue: function () {}
	};

	/**
	 * @class ReactServerRenderingTransaction
	 * @param {boolean} renderToStaticMarkup
	 */
	function ReactServerRenderingTransaction(renderToStaticMarkup) {
	  this.reinitializeTransaction();
	  this.renderToStaticMarkup = renderToStaticMarkup;
	  this.useCreateElement = false;
	  this.updateQueue = new ReactServerUpdateQueue(this);
	}

	var Mixin = {
	  /**
	   * @see Transaction
	   * @abstract
	   * @final
	   * @return {array} Empty list of operation wrap procedures.
	   */
	  getTransactionWrappers: function () {
	    return TRANSACTION_WRAPPERS;
	  },

	  /**
	   * @return {object} The queue to collect `onDOMReady` callbacks with.
	   */
	  getReactMountReady: function () {
	    return noopCallbackQueue;
	  },

	  /**
	   * @return {object} The queue to collect React async events.
	   */
	  getUpdateQueue: function () {
	    return this.updateQueue;
	  },

	  /**
	   * `PooledClass` looks for this, and will invoke this before allowing this
	   * instance to be reused.
	   */
	  destructor: function () {},

	  checkpoint: function () {},

	  rollback: function () {}
	};

	_assign(ReactServerRenderingTransaction.prototype, Transaction, Mixin);

	PooledClass.addPoolingTo(ReactServerRenderingTransaction);

	module.exports = ReactServerRenderingTransaction;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 167 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2015-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var ReactUpdateQueue = __webpack_require__(168);

	var warning = __webpack_require__(35);

	function warnNoop(publicInstance, callerName) {
	  if (process.env.NODE_ENV !== 'production') {
	    var constructor = publicInstance.constructor;
	    process.env.NODE_ENV !== 'production' ? warning(false, '%s(...): Can only update a mounting component. ' + 'This usually means you called %s() outside componentWillMount() on the server. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;
	  }
	}

	/**
	 * This is the update queue used for server rendering.
	 * It delegates to ReactUpdateQueue while server rendering is in progress and
	 * switches to ReactNoopUpdateQueue after the transaction has completed.
	 * @class ReactServerUpdateQueue
	 * @param {Transaction} transaction
	 */

	var ReactServerUpdateQueue = function () {
	  function ReactServerUpdateQueue(transaction) {
	    _classCallCheck(this, ReactServerUpdateQueue);

	    this.transaction = transaction;
	  }

	  /**
	   * Checks whether or not this composite component is mounted.
	   * @param {ReactClass} publicInstance The instance we want to test.
	   * @return {boolean} True if mounted, false otherwise.
	   * @protected
	   * @final
	   */


	  ReactServerUpdateQueue.prototype.isMounted = function isMounted(publicInstance) {
	    return false;
	  };

	  /**
	   * Enqueue a callback that will be executed after all the pending updates
	   * have processed.
	   *
	   * @param {ReactClass} publicInstance The instance to use as `this` context.
	   * @param {?function} callback Called after state is updated.
	   * @internal
	   */


	  ReactServerUpdateQueue.prototype.enqueueCallback = function enqueueCallback(publicInstance, callback, callerName) {
	    if (this.transaction.isInTransaction()) {
	      ReactUpdateQueue.enqueueCallback(publicInstance, callback, callerName);
	    }
	  };

	  /**
	   * Forces an update. This should only be invoked when it is known with
	   * certainty that we are **not** in a DOM transaction.
	   *
	   * You may want to call this when you know that some deeper aspect of the
	   * component's state has changed but `setState` was not called.
	   *
	   * This will not invoke `shouldComponentUpdate`, but it will invoke
	   * `componentWillUpdate` and `componentDidUpdate`.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @internal
	   */


	  ReactServerUpdateQueue.prototype.enqueueForceUpdate = function enqueueForceUpdate(publicInstance) {
	    if (this.transaction.isInTransaction()) {
	      ReactUpdateQueue.enqueueForceUpdate(publicInstance);
	    } else {
	      warnNoop(publicInstance, 'forceUpdate');
	    }
	  };

	  /**
	   * Replaces all of the state. Always use this or `setState` to mutate state.
	   * You should treat `this.state` as immutable.
	   *
	   * There is no guarantee that `this.state` will be immediately updated, so
	   * accessing `this.state` after calling this method may return the old value.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @param {object|function} completeState Next state.
	   * @internal
	   */


	  ReactServerUpdateQueue.prototype.enqueueReplaceState = function enqueueReplaceState(publicInstance, completeState) {
	    if (this.transaction.isInTransaction()) {
	      ReactUpdateQueue.enqueueReplaceState(publicInstance, completeState);
	    } else {
	      warnNoop(publicInstance, 'replaceState');
	    }
	  };

	  /**
	   * Sets a subset of the state. This only exists because _pendingState is
	   * internal. This provides a merging strategy that is not available to deep
	   * properties which is confusing. TODO: Expose pendingState or don't use it
	   * during the merge.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @param {object|function} partialState Next partial state to be merged with state.
	   * @internal
	   */


	  ReactServerUpdateQueue.prototype.enqueueSetState = function enqueueSetState(publicInstance, partialState) {
	    if (this.transaction.isInTransaction()) {
	      ReactUpdateQueue.enqueueSetState(publicInstance, partialState);
	    } else {
	      warnNoop(publicInstance, 'setState');
	    }
	  };

	  return ReactServerUpdateQueue;
	}();

	module.exports = ReactServerUpdateQueue;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 168 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2015-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var ReactCurrentOwner = __webpack_require__(44);
	var ReactInstanceMap = __webpack_require__(149);
	var ReactInstrumentation = __webpack_require__(94);
	var ReactUpdates = __webpack_require__(88);

	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	function enqueueUpdate(internalInstance) {
	  ReactUpdates.enqueueUpdate(internalInstance);
	}

	function formatUnexpectedArgument(arg) {
	  var type = typeof arg;
	  if (type !== 'object') {
	    return type;
	  }
	  var displayName = arg.constructor && arg.constructor.name || type;
	  var keys = Object.keys(arg);
	  if (keys.length > 0 && keys.length < 20) {
	    return displayName + ' (keys: ' + keys.join(', ') + ')';
	  }
	  return displayName;
	}

	function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
	  var internalInstance = ReactInstanceMap.get(publicInstance);
	  if (!internalInstance) {
	    if (process.env.NODE_ENV !== 'production') {
	      var ctor = publicInstance.constructor;
	      // Only warn when we have a callerName. Otherwise we should be silent.
	      // We're probably calling from enqueueCallback. We don't want to warn
	      // there because we already warned for the corresponding lifecycle method.
	      process.env.NODE_ENV !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, ctor && (ctor.displayName || ctor.name) || 'ReactClass') : void 0;
	    }
	    return null;
	  }

	  if (process.env.NODE_ENV !== 'production') {
	    process.env.NODE_ENV !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition (such as ' + "within `render` or another component's constructor). Render methods " + 'should be a pure function of props and state; constructor ' + 'side-effects are an anti-pattern, but can be moved to ' + '`componentWillMount`.', callerName) : void 0;
	  }

	  return internalInstance;
	}

	/**
	 * ReactUpdateQueue allows for state updates to be scheduled into a later
	 * reconciliation step.
	 */
	var ReactUpdateQueue = {
	  /**
	   * Checks whether or not this composite component is mounted.
	   * @param {ReactClass} publicInstance The instance we want to test.
	   * @return {boolean} True if mounted, false otherwise.
	   * @protected
	   * @final
	   */
	  isMounted: function (publicInstance) {
	    if (process.env.NODE_ENV !== 'production') {
	      var owner = ReactCurrentOwner.current;
	      if (owner !== null) {
	        process.env.NODE_ENV !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;
	        owner._warnedAboutRefsInRender = true;
	      }
	    }
	    var internalInstance = ReactInstanceMap.get(publicInstance);
	    if (internalInstance) {
	      // During componentWillMount and render this will still be null but after
	      // that will always render to something. At least for now. So we can use
	      // this hack.
	      return !!internalInstance._renderedComponent;
	    } else {
	      return false;
	    }
	  },

	  /**
	   * Enqueue a callback that will be executed after all the pending updates
	   * have processed.
	   *
	   * @param {ReactClass} publicInstance The instance to use as `this` context.
	   * @param {?function} callback Called after state is updated.
	   * @param {string} callerName Name of the calling function in the public API.
	   * @internal
	   */
	  enqueueCallback: function (publicInstance, callback, callerName) {
	    ReactUpdateQueue.validateCallback(callback, callerName);
	    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);

	    // Previously we would throw an error if we didn't have an internal
	    // instance. Since we want to make it a no-op instead, we mirror the same
	    // behavior we have in other enqueue* methods.
	    // We also need to ignore callbacks in componentWillMount. See
	    // enqueueUpdates.
	    if (!internalInstance) {
	      return null;
	    }

	    if (internalInstance._pendingCallbacks) {
	      internalInstance._pendingCallbacks.push(callback);
	    } else {
	      internalInstance._pendingCallbacks = [callback];
	    }
	    // TODO: The callback here is ignored when setState is called from
	    // componentWillMount. Either fix it or disallow doing so completely in
	    // favor of getInitialState. Alternatively, we can disallow
	    // componentWillMount during server-side rendering.
	    enqueueUpdate(internalInstance);
	  },

	  enqueueCallbackInternal: function (internalInstance, callback) {
	    if (internalInstance._pendingCallbacks) {
	      internalInstance._pendingCallbacks.push(callback);
	    } else {
	      internalInstance._pendingCallbacks = [callback];
	    }
	    enqueueUpdate(internalInstance);
	  },

	  /**
	   * Forces an update. This should only be invoked when it is known with
	   * certainty that we are **not** in a DOM transaction.
	   *
	   * You may want to call this when you know that some deeper aspect of the
	   * component's state has changed but `setState` was not called.
	   *
	   * This will not invoke `shouldComponentUpdate`, but it will invoke
	   * `componentWillUpdate` and `componentDidUpdate`.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @internal
	   */
	  enqueueForceUpdate: function (publicInstance) {
	    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'forceUpdate');

	    if (!internalInstance) {
	      return;
	    }

	    internalInstance._pendingForceUpdate = true;

	    enqueueUpdate(internalInstance);
	  },

	  /**
	   * Replaces all of the state. Always use this or `setState` to mutate state.
	   * You should treat `this.state` as immutable.
	   *
	   * There is no guarantee that `this.state` will be immediately updated, so
	   * accessing `this.state` after calling this method may return the old value.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @param {object} completeState Next state.
	   * @internal
	   */
	  enqueueReplaceState: function (publicInstance, completeState, callback) {
	    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceState');

	    if (!internalInstance) {
	      return;
	    }

	    internalInstance._pendingStateQueue = [completeState];
	    internalInstance._pendingReplaceState = true;

	    // Future-proof 15.5
	    if (callback !== undefined && callback !== null) {
	      ReactUpdateQueue.validateCallback(callback, 'replaceState');
	      if (internalInstance._pendingCallbacks) {
	        internalInstance._pendingCallbacks.push(callback);
	      } else {
	        internalInstance._pendingCallbacks = [callback];
	      }
	    }

	    enqueueUpdate(internalInstance);
	  },

	  /**
	   * Sets a subset of the state. This only exists because _pendingState is
	   * internal. This provides a merging strategy that is not available to deep
	   * properties which is confusing. TODO: Expose pendingState or don't use it
	   * during the merge.
	   *
	   * @param {ReactClass} publicInstance The instance that should rerender.
	   * @param {object} partialState Next partial state to be merged with state.
	   * @internal
	   */
	  enqueueSetState: function (publicInstance, partialState) {
	    if (process.env.NODE_ENV !== 'production') {
	      ReactInstrumentation.debugTool.onSetState();
	      process.env.NODE_ENV !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;
	    }

	    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');

	    if (!internalInstance) {
	      return;
	    }

	    var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);
	    queue.push(partialState);

	    enqueueUpdate(internalInstance);
	  },

	  enqueueElementInternal: function (internalInstance, nextElement, nextContext) {
	    internalInstance._pendingElement = nextElement;
	    // TODO: introduce _pendingContext instead of setting it directly.
	    internalInstance._context = nextContext;
	    enqueueUpdate(internalInstance);
	  },

	  validateCallback: function (callback, callerName) {
	    !(!callback || typeof callback === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.', callerName, formatUnexpectedArgument(callback)) : _prodInvariant('122', callerName, formatUnexpectedArgument(callback)) : void 0;
	  }
	};

	module.exports = ReactUpdateQueue;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 169 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2015-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var emptyFunction = __webpack_require__(36);
	var warning = __webpack_require__(35);

	var validateDOMNesting = emptyFunction;

	if (process.env.NODE_ENV !== 'production') {
	  // This validation code was written based on the HTML5 parsing spec:
	  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
	  //
	  // Note: this does not catch all invalid nesting, nor does it try to (as it's
	  // not clear what practical benefit doing so provides); instead, we warn only
	  // for cases where the parser will give a parse tree differing from what React
	  // intended. For example, <b><div></div></b> is invalid but we don't warn
	  // because it still parses correctly; we do warn for other cases like nested
	  // <p> tags where the beginning of the second element implicitly closes the
	  // first, causing a confusing mess.

	  // https://html.spec.whatwg.org/multipage/syntax.html#special
	  var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];

	  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
	  var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',

	  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
	  // TODO: Distinguish by namespace here -- for <title>, including it here
	  // errs on the side of fewer warnings
	  'foreignObject', 'desc', 'title'];

	  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
	  var buttonScopeTags = inScopeTags.concat(['button']);

	  // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
	  var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];

	  var emptyAncestorInfo = {
	    current: null,

	    formTag: null,
	    aTagInScope: null,
	    buttonTagInScope: null,
	    nobrTagInScope: null,
	    pTagInButtonScope: null,

	    listItemTagAutoclosing: null,
	    dlItemTagAutoclosing: null
	  };

	  var updatedAncestorInfo = function (oldInfo, tag, instance) {
	    var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
	    var info = { tag: tag, instance: instance };

	    if (inScopeTags.indexOf(tag) !== -1) {
	      ancestorInfo.aTagInScope = null;
	      ancestorInfo.buttonTagInScope = null;
	      ancestorInfo.nobrTagInScope = null;
	    }
	    if (buttonScopeTags.indexOf(tag) !== -1) {
	      ancestorInfo.pTagInButtonScope = null;
	    }

	    // See rules for 'li', 'dd', 'dt' start tags in
	    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
	    if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
	      ancestorInfo.listItemTagAutoclosing = null;
	      ancestorInfo.dlItemTagAutoclosing = null;
	    }

	    ancestorInfo.current = info;

	    if (tag === 'form') {
	      ancestorInfo.formTag = info;
	    }
	    if (tag === 'a') {
	      ancestorInfo.aTagInScope = info;
	    }
	    if (tag === 'button') {
	      ancestorInfo.buttonTagInScope = info;
	    }
	    if (tag === 'nobr') {
	      ancestorInfo.nobrTagInScope = info;
	    }
	    if (tag === 'p') {
	      ancestorInfo.pTagInButtonScope = info;
	    }
	    if (tag === 'li') {
	      ancestorInfo.listItemTagAutoclosing = info;
	    }
	    if (tag === 'dd' || tag === 'dt') {
	      ancestorInfo.dlItemTagAutoclosing = info;
	    }

	    return ancestorInfo;
	  };

	  /**
	   * Returns whether
	   */
	  var isTagValidWithParent = function (tag, parentTag) {
	    // First, let's check if we're in an unusual parsing mode...
	    switch (parentTag) {
	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
	      case 'select':
	        return tag === 'option' || tag === 'optgroup' || tag === '#text';
	      case 'optgroup':
	        return tag === 'option' || tag === '#text';
	      // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
	      // but
	      case 'option':
	        return tag === '#text';
	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
	      // No special behavior since these rules fall back to "in body" mode for
	      // all except special table nodes which cause bad parsing behavior anyway.

	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
	      case 'tr':
	        return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
	      case 'tbody':
	      case 'thead':
	      case 'tfoot':
	        return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
	      case 'colgroup':
	        return tag === 'col' || tag === 'template';
	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
	      case 'table':
	        return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
	      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
	      case 'head':
	        return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
	      // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
	      case 'html':
	        return tag === 'head' || tag === 'body';
	      case '#document':
	        return tag === 'html';
	    }

	    // Probably in the "in body" parsing mode, so we outlaw only tag combos
	    // where the parsing rules cause implicit opens or closes to be added.
	    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
	    switch (tag) {
	      case 'h1':
	      case 'h2':
	      case 'h3':
	      case 'h4':
	      case 'h5':
	      case 'h6':
	        return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';

	      case 'rp':
	      case 'rt':
	        return impliedEndTags.indexOf(parentTag) === -1;

	      case 'body':
	      case 'caption':
	      case 'col':
	      case 'colgroup':
	      case 'frame':
	      case 'head':
	      case 'html':
	      case 'tbody':
	      case 'td':
	      case 'tfoot':
	      case 'th':
	      case 'thead':
	      case 'tr':
	        // These tags are only valid with a few parents that have special child
	        // parsing rules -- if we're down here, then none of those matched and
	        // so we allow it only if we don't know what the parent is, as all other
	        // cases are invalid.
	        return parentTag == null;
	    }

	    return true;
	  };

	  /**
	   * Returns whether
	   */
	  var findInvalidAncestorForTag = function (tag, ancestorInfo) {
	    switch (tag) {
	      case 'address':
	      case 'article':
	      case 'aside':
	      case 'blockquote':
	      case 'center':
	      case 'details':
	      case 'dialog':
	      case 'dir':
	      case 'div':
	      case 'dl':
	      case 'fieldset':
	      case 'figcaption':
	      case 'figure':
	      case 'footer':
	      case 'header':
	      case 'hgroup':
	      case 'main':
	      case 'menu':
	      case 'nav':
	      case 'ol':
	      case 'p':
	      case 'section':
	      case 'summary':
	      case 'ul':
	      case 'pre':
	      case 'listing':
	      case 'table':
	      case 'hr':
	      case 'xmp':
	      case 'h1':
	      case 'h2':
	      case 'h3':
	      case 'h4':
	      case 'h5':
	      case 'h6':
	        return ancestorInfo.pTagInButtonScope;

	      case 'form':
	        return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;

	      case 'li':
	        return ancestorInfo.listItemTagAutoclosing;

	      case 'dd':
	      case 'dt':
	        return ancestorInfo.dlItemTagAutoclosing;

	      case 'button':
	        return ancestorInfo.buttonTagInScope;

	      case 'a':
	        // Spec says something about storing a list of markers, but it sounds
	        // equivalent to this check.
	        return ancestorInfo.aTagInScope;

	      case 'nobr':
	        return ancestorInfo.nobrTagInScope;
	    }

	    return null;
	  };

	  /**
	   * Given a ReactCompositeComponent instance, return a list of its recursive
	   * owners, starting at the root and ending with the instance itself.
	   */
	  var findOwnerStack = function (instance) {
	    if (!instance) {
	      return [];
	    }

	    var stack = [];
	    do {
	      stack.push(instance);
	    } while (instance = instance._currentElement._owner);
	    stack.reverse();
	    return stack;
	  };

	  var didWarn = {};

	  validateDOMNesting = function (childTag, childText, childInstance, ancestorInfo) {
	    ancestorInfo = ancestorInfo || emptyAncestorInfo;
	    var parentInfo = ancestorInfo.current;
	    var parentTag = parentInfo && parentInfo.tag;

	    if (childText != null) {
	      process.env.NODE_ENV !== 'production' ? warning(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null') : void 0;
	      childTag = '#text';
	    }

	    var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
	    var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
	    var problematic = invalidParent || invalidAncestor;

	    if (problematic) {
	      var ancestorTag = problematic.tag;
	      var ancestorInstance = problematic.instance;

	      var childOwner = childInstance && childInstance._currentElement._owner;
	      var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;

	      var childOwners = findOwnerStack(childOwner);
	      var ancestorOwners = findOwnerStack(ancestorOwner);

	      var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
	      var i;

	      var deepestCommon = -1;
	      for (i = 0; i < minStackLen; i++) {
	        if (childOwners[i] === ancestorOwners[i]) {
	          deepestCommon = i;
	        } else {
	          break;
	        }
	      }

	      var UNKNOWN = '(unknown)';
	      var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {
	        return inst.getName() || UNKNOWN;
	      });
	      var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {
	        return inst.getName() || UNKNOWN;
	      });
	      var ownerInfo = [].concat(
	      // If the parent and child instances have a common owner ancestor, start
	      // with that -- otherwise we just start with the parent's owners.
	      deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,
	      // If we're warning about an invalid (non-parent) ancestry, add '...'
	      invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');

	      var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;
	      if (didWarn[warnKey]) {
	        return;
	      }
	      didWarn[warnKey] = true;

	      var tagDisplayName = childTag;
	      var whitespaceInfo = '';
	      if (childTag === '#text') {
	        if (/\S/.test(childText)) {
	          tagDisplayName = 'Text nodes';
	        } else {
	          tagDisplayName = 'Whitespace text nodes';
	          whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.';
	        }
	      } else {
	        tagDisplayName = '<' + childTag + '>';
	      }

	      if (invalidParent) {
	        var info = '';
	        if (ancestorTag === 'table' && childTag === 'tr') {
	          info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
	        }
	        process.env.NODE_ENV !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s ' + 'See %s.%s', tagDisplayName, ancestorTag, whitespaceInfo, ownerInfo, info) : void 0;
	      } else {
	        process.env.NODE_ENV !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;
	      }
	    }
	  };

	  validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;

	  // For testing
	  validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {
	    ancestorInfo = ancestorInfo || emptyAncestorInfo;
	    var parentInfo = ancestorInfo.current;
	    var parentTag = parentInfo && parentInfo.tag;
	    return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
	  };
	}

	module.exports = validateDOMNesting;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 170 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2014-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var DOMLazyTree = __webpack_require__(114);
	var ReactDOMComponentTree = __webpack_require__(66);

	var ReactDOMEmptyComponent = function (instantiate) {
	  // ReactCompositeComponent uses this:
	  this._currentElement = null;
	  // ReactDOMComponentTree uses these:
	  this._hostNode = null;
	  this._hostParent = null;
	  this._hostContainerInfo = null;
	  this._domID = 0;
	};
	_assign(ReactDOMEmptyComponent.prototype, {
	  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
	    var domID = hostContainerInfo._idCounter++;
	    this._domID = domID;
	    this._hostParent = hostParent;
	    this._hostContainerInfo = hostContainerInfo;

	    var nodeValue = ' react-empty: ' + this._domID + ' ';
	    if (transaction.useCreateElement) {
	      var ownerDocument = hostContainerInfo._ownerDocument;
	      var node = ownerDocument.createComment(nodeValue);
	      ReactDOMComponentTree.precacheNode(this, node);
	      return DOMLazyTree(node);
	    } else {
	      if (transaction.renderToStaticMarkup) {
	        // Normally we'd insert a comment node, but since this is a situation
	        // where React won't take over (static pages), we can simply return
	        // nothing.
	        return '';
	      }
	      return '<!--' + nodeValue + '-->';
	    }
	  },
	  receiveComponent: function () {},
	  getHostNode: function () {
	    return ReactDOMComponentTree.getNodeFromInstance(this);
	  },
	  unmountComponent: function () {
	    ReactDOMComponentTree.uncacheNode(this);
	  }
	});

	module.exports = ReactDOMEmptyComponent;

/***/ },
/* 171 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2015-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var invariant = __webpack_require__(39);

	/**
	 * Return the lowest common ancestor of A and B, or null if they are in
	 * different trees.
	 */
	function getLowestCommonAncestor(instA, instB) {
	  !('_hostNode' in instA) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;
	  !('_hostNode' in instB) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;

	  var depthA = 0;
	  for (var tempA = instA; tempA; tempA = tempA._hostParent) {
	    depthA++;
	  }
	  var depthB = 0;
	  for (var tempB = instB; tempB; tempB = tempB._hostParent) {
	    depthB++;
	  }

	  // If A is deeper, crawl up.
	  while (depthA - depthB > 0) {
	    instA = instA._hostParent;
	    depthA--;
	  }

	  // If B is deeper, crawl up.
	  while (depthB - depthA > 0) {
	    instB = instB._hostParent;
	    depthB--;
	  }

	  // Walk in lockstep until we find a match.
	  var depth = depthA;
	  while (depth--) {
	    if (instA === instB) {
	      return instA;
	    }
	    instA = instA._hostParent;
	    instB = instB._hostParent;
	  }
	  return null;
	}

	/**
	 * Return if A is an ancestor of B.
	 */
	function isAncestor(instA, instB) {
	  !('_hostNode' in instA) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;
	  !('_hostNode' in instB) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;

	  while (instB) {
	    if (instB === instA) {
	      return true;
	    }
	    instB = instB._hostParent;
	  }
	  return false;
	}

	/**
	 * Return the parent instance of the passed-in instance.
	 */
	function getParentInstance(inst) {
	  !('_hostNode' in inst) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : _prodInvariant('36') : void 0;

	  return inst._hostParent;
	}

	/**
	 * Simulates the traversal of a two-phase, capture/bubble event dispatch.
	 */
	function traverseTwoPhase(inst, fn, arg) {
	  var path = [];
	  while (inst) {
	    path.push(inst);
	    inst = inst._hostParent;
	  }
	  var i;
	  for (i = path.length; i-- > 0;) {
	    fn(path[i], 'captured', arg);
	  }
	  for (i = 0; i < path.length; i++) {
	    fn(path[i], 'bubbled', arg);
	  }
	}

	/**
	 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
	 * should would receive a `mouseEnter` or `mouseLeave` event.
	 *
	 * Does not invoke the callback on the nearest common ancestor because nothing
	 * "entered" or "left" that element.
	 */
	function traverseEnterLeave(from, to, fn, argFrom, argTo) {
	  var common = from && to ? getLowestCommonAncestor(from, to) : null;
	  var pathFrom = [];
	  while (from && from !== common) {
	    pathFrom.push(from);
	    from = from._hostParent;
	  }
	  var pathTo = [];
	  while (to && to !== common) {
	    pathTo.push(to);
	    to = to._hostParent;
	  }
	  var i;
	  for (i = 0; i < pathFrom.length; i++) {
	    fn(pathFrom[i], 'bubbled', argFrom);
	  }
	  for (i = pathTo.length; i-- > 0;) {
	    fn(pathTo[i], 'captured', argTo);
	  }
	}

	module.exports = {
	  isAncestor: isAncestor,
	  getLowestCommonAncestor: getLowestCommonAncestor,
	  getParentInstance: getParentInstance,
	  traverseTwoPhase: traverseTwoPhase,
	  traverseEnterLeave: traverseEnterLeave
	};
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 172 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67),
	    _assign = __webpack_require__(31);

	var DOMChildrenOperations = __webpack_require__(113);
	var DOMLazyTree = __webpack_require__(114);
	var ReactDOMComponentTree = __webpack_require__(66);

	var escapeTextContentForBrowser = __webpack_require__(119);
	var invariant = __webpack_require__(39);
	var validateDOMNesting = __webpack_require__(169);

	/**
	 * Text nodes violate a couple assumptions that React makes about components:
	 *
	 *  - When mounting text into the DOM, adjacent text nodes are merged.
	 *  - Text nodes cannot be assigned a React root ID.
	 *
	 * This component is used to wrap strings between comment nodes so that they
	 * can undergo the same reconciliation that is applied to elements.
	 *
	 * TODO: Investigate representing React components in the DOM with text nodes.
	 *
	 * @class ReactDOMTextComponent
	 * @extends ReactComponent
	 * @internal
	 */
	var ReactDOMTextComponent = function (text) {
	  // TODO: This is really a ReactText (ReactNode), not a ReactElement
	  this._currentElement = text;
	  this._stringText = '' + text;
	  // ReactDOMComponentTree uses these:
	  this._hostNode = null;
	  this._hostParent = null;

	  // Properties
	  this._domID = 0;
	  this._mountIndex = 0;
	  this._closingComment = null;
	  this._commentNodes = null;
	};

	_assign(ReactDOMTextComponent.prototype, {
	  /**
	   * Creates the markup for this text node. This node is not intended to have
	   * any features besides containing text content.
	   *
	   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
	   * @return {string} Markup for this text node.
	   * @internal
	   */
	  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
	    if (process.env.NODE_ENV !== 'production') {
	      var parentInfo;
	      if (hostParent != null) {
	        parentInfo = hostParent._ancestorInfo;
	      } else if (hostContainerInfo != null) {
	        parentInfo = hostContainerInfo._ancestorInfo;
	      }
	      if (parentInfo) {
	        // parentInfo should always be present except for the top-level
	        // component when server rendering
	        validateDOMNesting(null, this._stringText, this, parentInfo);
	      }
	    }

	    var domID = hostContainerInfo._idCounter++;
	    var openingValue = ' react-text: ' + domID + ' ';
	    var closingValue = ' /react-text ';
	    this._domID = domID;
	    this._hostParent = hostParent;
	    if (transaction.useCreateElement) {
	      var ownerDocument = hostContainerInfo._ownerDocument;
	      var openingComment = ownerDocument.createComment(openingValue);
	      var closingComment = ownerDocument.createComment(closingValue);
	      var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment());
	      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment));
	      if (this._stringText) {
	        DOMLazyTree.queueChild(lazyTree, DOMLazyTree(ownerDocument.createTextNode(this._stringText)));
	      }
	      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment));
	      ReactDOMComponentTree.precacheNode(this, openingComment);
	      this._closingComment = closingComment;
	      return lazyTree;
	    } else {
	      var escapedText = escapeTextContentForBrowser(this._stringText);

	      if (transaction.renderToStaticMarkup) {
	        // Normally we'd wrap this between comment nodes for the reasons stated
	        // above, but since this is a situation where React won't take over
	        // (static pages), we can simply return the text as it is.
	        return escapedText;
	      }

	      return '<!--' + openingValue + '-->' + escapedText + '<!--' + closingValue + '-->';
	    }
	  },

	  /**
	   * Updates this component by updating the text content.
	   *
	   * @param {ReactText} nextText The next text content
	   * @param {ReactReconcileTransaction} transaction
	   * @internal
	   */
	  receiveComponent: function (nextText, transaction) {
	    if (nextText !== this._currentElement) {
	      this._currentElement = nextText;
	      var nextStringText = '' + nextText;
	      if (nextStringText !== this._stringText) {
	        // TODO: Save this as pending props and use performUpdateIfNecessary
	        // and/or updateComponent to do the actual update for consistency with
	        // other component types?
	        this._stringText = nextStringText;
	        var commentNodes = this.getHostNode();
	        DOMChildrenOperations.replaceDelimitedText(commentNodes[0], commentNodes[1], nextStringText);
	      }
	    }
	  },

	  getHostNode: function () {
	    var hostNode = this._commentNodes;
	    if (hostNode) {
	      return hostNode;
	    }
	    if (!this._closingComment) {
	      var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);
	      var node = openingComment.nextSibling;
	      while (true) {
	        !(node != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Missing closing comment for text component %s', this._domID) : _prodInvariant('67', this._domID) : void 0;
	        if (node.nodeType === 8 && node.nodeValue === ' /react-text ') {
	          this._closingComment = node;
	          break;
	        }
	        node = node.nextSibling;
	      }
	    }
	    hostNode = [this._hostNode, this._closingComment];
	    this._commentNodes = hostNode;
	    return hostNode;
	  },

	  unmountComponent: function () {
	    this._closingComment = null;
	    this._commentNodes = null;
	    ReactDOMComponentTree.uncacheNode(this);
	  }
	});

	module.exports = ReactDOMTextComponent;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 173 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var ReactUpdates = __webpack_require__(88);
	var Transaction = __webpack_require__(100);

	var emptyFunction = __webpack_require__(36);

	var RESET_BATCHED_UPDATES = {
	  initialize: emptyFunction,
	  close: function () {
	    ReactDefaultBatchingStrategy.isBatchingUpdates = false;
	  }
	};

	var FLUSH_BATCHED_UPDATES = {
	  initialize: emptyFunction,
	  close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)
	};

	var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];

	function ReactDefaultBatchingStrategyTransaction() {
	  this.reinitializeTransaction();
	}

	_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction, {
	  getTransactionWrappers: function () {
	    return TRANSACTION_WRAPPERS;
	  }
	});

	var transaction = new ReactDefaultBatchingStrategyTransaction();

	var ReactDefaultBatchingStrategy = {
	  isBatchingUpdates: false,

	  /**
	   * Call the provided function in a context within which calls to `setState`
	   * and friends are batched such that components aren't updated unnecessarily.
	   */
	  batchedUpdates: function (callback, a, b, c, d, e) {
	    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;

	    ReactDefaultBatchingStrategy.isBatchingUpdates = true;

	    // The code is written this way to avoid extra allocations
	    if (alreadyBatchingUpdates) {
	      return callback(a, b, c, d, e);
	    } else {
	      return transaction.perform(callback, null, a, b, c, d, e);
	    }
	  }
	};

	module.exports = ReactDefaultBatchingStrategy;

/***/ },
/* 174 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var EventListener = __webpack_require__(175);
	var ExecutionEnvironment = __webpack_require__(80);
	var PooledClass = __webpack_require__(82);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactUpdates = __webpack_require__(88);

	var getEventTarget = __webpack_require__(102);
	var getUnboundedScrollPosition = __webpack_require__(176);

	/**
	 * Find the deepest React component completely containing the root of the
	 * passed-in instance (for use when entire React trees are nested within each
	 * other). If React trees are not nested, returns null.
	 */
	function findParent(inst) {
	  // TODO: It may be a good idea to cache this to prevent unnecessary DOM
	  // traversal, but caching is difficult to do correctly without using a
	  // mutation observer to listen for all DOM changes.
	  while (inst._hostParent) {
	    inst = inst._hostParent;
	  }
	  var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);
	  var container = rootNode.parentNode;
	  return ReactDOMComponentTree.getClosestInstanceFromNode(container);
	}

	// Used to store ancestor hierarchy in top level callback
	function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
	  this.topLevelType = topLevelType;
	  this.nativeEvent = nativeEvent;
	  this.ancestors = [];
	}
	_assign(TopLevelCallbackBookKeeping.prototype, {
	  destructor: function () {
	    this.topLevelType = null;
	    this.nativeEvent = null;
	    this.ancestors.length = 0;
	  }
	});
	PooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler);

	function handleTopLevelImpl(bookKeeping) {
	  var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);
	  var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);

	  // Loop through the hierarchy, in case there's any nested components.
	  // It's important that we build the array of ancestors before calling any
	  // event handlers, because event handlers can modify the DOM, leading to
	  // inconsistencies with ReactMount's node cache. See #1105.
	  var ancestor = targetInst;
	  do {
	    bookKeeping.ancestors.push(ancestor);
	    ancestor = ancestor && findParent(ancestor);
	  } while (ancestor);

	  for (var i = 0; i < bookKeeping.ancestors.length; i++) {
	    targetInst = bookKeeping.ancestors[i];
	    ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
	  }
	}

	function scrollValueMonitor(cb) {
	  var scrollPosition = getUnboundedScrollPosition(window);
	  cb(scrollPosition);
	}

	var ReactEventListener = {
	  _enabled: true,
	  _handleTopLevel: null,

	  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,

	  setHandleTopLevel: function (handleTopLevel) {
	    ReactEventListener._handleTopLevel = handleTopLevel;
	  },

	  setEnabled: function (enabled) {
	    ReactEventListener._enabled = !!enabled;
	  },

	  isEnabled: function () {
	    return ReactEventListener._enabled;
	  },

	  /**
	   * Traps top-level events by using event bubbling.
	   *
	   * @param {string} topLevelType Record from `EventConstants`.
	   * @param {string} handlerBaseName Event name (e.g. "click").
	   * @param {object} element Element on which to attach listener.
	   * @return {?object} An object with a remove function which will forcefully
	   *                  remove the listener.
	   * @internal
	   */
	  trapBubbledEvent: function (topLevelType, handlerBaseName, element) {
	    if (!element) {
	      return null;
	    }
	    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));
	  },

	  /**
	   * Traps a top-level event by using event capturing.
	   *
	   * @param {string} topLevelType Record from `EventConstants`.
	   * @param {string} handlerBaseName Event name (e.g. "click").
	   * @param {object} element Element on which to attach listener.
	   * @return {?object} An object with a remove function which will forcefully
	   *                  remove the listener.
	   * @internal
	   */
	  trapCapturedEvent: function (topLevelType, handlerBaseName, element) {
	    if (!element) {
	      return null;
	    }
	    return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));
	  },

	  monitorScrollValue: function (refresh) {
	    var callback = scrollValueMonitor.bind(null, refresh);
	    EventListener.listen(window, 'scroll', callback);
	  },

	  dispatchEvent: function (topLevelType, nativeEvent) {
	    if (!ReactEventListener._enabled) {
	      return;
	    }

	    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);
	    try {
	      // Event queue being processed in the same cycle allows
	      // `preventDefault`.
	      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
	    } finally {
	      TopLevelCallbackBookKeeping.release(bookKeeping);
	    }
	  }
	};

	module.exports = ReactEventListener;

/***/ },
/* 175 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	var emptyFunction = __webpack_require__(36);

	/**
	 * Upstream version of event listener. Does not take into account specific
	 * nature of platform.
	 */
	var EventListener = {
	  /**
	   * Listen to DOM events during the bubble phase.
	   *
	   * @param {DOMEventTarget} target DOM element to register listener on.
	   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
	   * @param {function} callback Callback function.
	   * @return {object} Object with a `remove` method.
	   */
	  listen: function listen(target, eventType, callback) {
	    if (target.addEventListener) {
	      target.addEventListener(eventType, callback, false);
	      return {
	        remove: function remove() {
	          target.removeEventListener(eventType, callback, false);
	        }
	      };
	    } else if (target.attachEvent) {
	      target.attachEvent('on' + eventType, callback);
	      return {
	        remove: function remove() {
	          target.detachEvent('on' + eventType, callback);
	        }
	      };
	    }
	  },

	  /**
	   * Listen to DOM events during the capture phase.
	   *
	   * @param {DOMEventTarget} target DOM element to register listener on.
	   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
	   * @param {function} callback Callback function.
	   * @return {object} Object with a `remove` method.
	   */
	  capture: function capture(target, eventType, callback) {
	    if (target.addEventListener) {
	      target.addEventListener(eventType, callback, true);
	      return {
	        remove: function remove() {
	          target.removeEventListener(eventType, callback, true);
	        }
	      };
	    } else {
	      if (process.env.NODE_ENV !== 'production') {
	        console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');
	      }
	      return {
	        remove: emptyFunction
	      };
	    }
	  },

	  registerDefault: function registerDefault() {}
	};

	module.exports = EventListener;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 176 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	'use strict';

	/**
	 * Gets the scroll position of the supplied element or window.
	 *
	 * The return values are unbounded, unlike `getScrollPosition`. This means they
	 * may be negative or exceed the element boundaries (which is possible using
	 * inertial scrolling).
	 *
	 * @param {DOMWindow|DOMElement} scrollable
	 * @return {object} Map with `x` and `y` keys.
	 */

	function getUnboundedScrollPosition(scrollable) {
	  if (scrollable.Window && scrollable instanceof scrollable.Window) {
	    return {
	      x: scrollable.pageXOffset || scrollable.document.documentElement.scrollLeft,
	      y: scrollable.pageYOffset || scrollable.document.documentElement.scrollTop
	    };
	  }
	  return {
	    x: scrollable.scrollLeft,
	    y: scrollable.scrollTop
	  };
	}

	module.exports = getUnboundedScrollPosition;

/***/ },
/* 177 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMProperty = __webpack_require__(68);
	var EventPluginHub = __webpack_require__(74);
	var EventPluginUtils = __webpack_require__(76);
	var ReactComponentEnvironment = __webpack_require__(148);
	var ReactEmptyComponent = __webpack_require__(158);
	var ReactBrowserEventEmitter = __webpack_require__(138);
	var ReactHostComponent = __webpack_require__(159);
	var ReactUpdates = __webpack_require__(88);

	var ReactInjection = {
	  Component: ReactComponentEnvironment.injection,
	  DOMProperty: DOMProperty.injection,
	  EmptyComponent: ReactEmptyComponent.injection,
	  EventPluginHub: EventPluginHub.injection,
	  EventPluginUtils: EventPluginUtils.injection,
	  EventEmitter: ReactBrowserEventEmitter.injection,
	  HostComponent: ReactHostComponent.injection,
	  Updates: ReactUpdates.injection
	};

	module.exports = ReactInjection;

/***/ },
/* 178 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _assign = __webpack_require__(31);

	var CallbackQueue = __webpack_require__(89);
	var PooledClass = __webpack_require__(82);
	var ReactBrowserEventEmitter = __webpack_require__(138);
	var ReactInputSelection = __webpack_require__(179);
	var ReactInstrumentation = __webpack_require__(94);
	var Transaction = __webpack_require__(100);
	var ReactUpdateQueue = __webpack_require__(168);

	/**
	 * Ensures that, when possible, the selection range (currently selected text
	 * input) is not disturbed by performing the transaction.
	 */
	var SELECTION_RESTORATION = {
	  /**
	   * @return {Selection} Selection information.
	   */
	  initialize: ReactInputSelection.getSelectionInformation,
	  /**
	   * @param {Selection} sel Selection information returned from `initialize`.
	   */
	  close: ReactInputSelection.restoreSelection
	};

	/**
	 * Suppresses events (blur/focus) that could be inadvertently dispatched due to
	 * high level DOM manipulations (like temporarily removing a text input from the
	 * DOM).
	 */
	var EVENT_SUPPRESSION = {
	  /**
	   * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before
	   * the reconciliation.
	   */
	  initialize: function () {
	    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();
	    ReactBrowserEventEmitter.setEnabled(false);
	    return currentlyEnabled;
	  },

	  /**
	   * @param {boolean} previouslyEnabled Enabled status of
	   *   `ReactBrowserEventEmitter` before the reconciliation occurred. `close`
	   *   restores the previous value.
	   */
	  close: function (previouslyEnabled) {
	    ReactBrowserEventEmitter.setEnabled(previouslyEnabled);
	  }
	};

	/**
	 * Provides a queue for collecting `componentDidMount` and
	 * `componentDidUpdate` callbacks during the transaction.
	 */
	var ON_DOM_READY_QUEUEING = {
	  /**
	   * Initializes the internal `onDOMReady` queue.
	   */
	  initialize: function () {
	    this.reactMountReady.reset();
	  },

	  /**
	   * After DOM is flushed, invoke all registered `onDOMReady` callbacks.
	   */
	  close: function () {
	    this.reactMountReady.notifyAll();
	  }
	};

	/**
	 * Executed within the scope of the `Transaction` instance. Consider these as
	 * being member methods, but with an implied ordering while being isolated from
	 * each other.
	 */
	var TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];

	if (process.env.NODE_ENV !== 'production') {
	  TRANSACTION_WRAPPERS.push({
	    initialize: ReactInstrumentation.debugTool.onBeginFlush,
	    close: ReactInstrumentation.debugTool.onEndFlush
	  });
	}

	/**
	 * Currently:
	 * - The order that these are listed in the transaction is critical:
	 * - Suppresses events.
	 * - Restores selection range.
	 *
	 * Future:
	 * - Restore document/overflow scroll positions that were unintentionally
	 *   modified via DOM insertions above the top viewport boundary.
	 * - Implement/integrate with customized constraint based layout system and keep
	 *   track of which dimensions must be remeasured.
	 *
	 * @class ReactReconcileTransaction
	 */
	function ReactReconcileTransaction(useCreateElement) {
	  this.reinitializeTransaction();
	  // Only server-side rendering really needs this option (see
	  // `ReactServerRendering`), but server-side uses
	  // `ReactServerRenderingTransaction` instead. This option is here so that it's
	  // accessible and defaults to false when `ReactDOMComponent` and
	  // `ReactDOMTextComponent` checks it in `mountComponent`.`
	  this.renderToStaticMarkup = false;
	  this.reactMountReady = CallbackQueue.getPooled(null);
	  this.useCreateElement = useCreateElement;
	}

	var Mixin = {
	  /**
	   * @see Transaction
	   * @abstract
	   * @final
	   * @return {array<object>} List of operation wrap procedures.
	   *   TODO: convert to array<TransactionWrapper>
	   */
	  getTransactionWrappers: function () {
	    return TRANSACTION_WRAPPERS;
	  },

	  /**
	   * @return {object} The queue to collect `onDOMReady` callbacks with.
	   */
	  getReactMountReady: function () {
	    return this.reactMountReady;
	  },

	  /**
	   * @return {object} The queue to collect React async events.
	   */
	  getUpdateQueue: function () {
	    return ReactUpdateQueue;
	  },

	  /**
	   * Save current transaction state -- if the return value from this method is
	   * passed to `rollback`, the transaction will be reset to that state.
	   */
	  checkpoint: function () {
	    // reactMountReady is the our only stateful wrapper
	    return this.reactMountReady.checkpoint();
	  },

	  rollback: function (checkpoint) {
	    this.reactMountReady.rollback(checkpoint);
	  },

	  /**
	   * `PooledClass` looks for this, and will invoke this before allowing this
	   * instance to be reused.
	   */
	  destructor: function () {
	    CallbackQueue.release(this.reactMountReady);
	    this.reactMountReady = null;
	  }
	};

	_assign(ReactReconcileTransaction.prototype, Transaction, Mixin);

	PooledClass.addPoolingTo(ReactReconcileTransaction);

	module.exports = ReactReconcileTransaction;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 179 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactDOMSelection = __webpack_require__(180);

	var containsNode = __webpack_require__(182);
	var focusNode = __webpack_require__(127);
	var getActiveElement = __webpack_require__(185);

	function isInDocument(node) {
	  return containsNode(document.documentElement, node);
	}

	/**
	 * @ReactInputSelection: React input selection module. Based on Selection.js,
	 * but modified to be suitable for react and has a couple of bug fixes (doesn't
	 * assume buttons have range selections allowed).
	 * Input selection module for React.
	 */
	var ReactInputSelection = {
	  hasSelectionCapabilities: function (elem) {
	    var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
	    return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');
	  },

	  getSelectionInformation: function () {
	    var focusedElem = getActiveElement();
	    return {
	      focusedElem: focusedElem,
	      selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null
	    };
	  },

	  /**
	   * @restoreSelection: If any selection information was potentially lost,
	   * restore it. This is useful when performing operations that could remove dom
	   * nodes and place them back in, resulting in focus being lost.
	   */
	  restoreSelection: function (priorSelectionInformation) {
	    var curFocusedElem = getActiveElement();
	    var priorFocusedElem = priorSelectionInformation.focusedElem;
	    var priorSelectionRange = priorSelectionInformation.selectionRange;
	    if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
	      if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
	        ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);
	      }
	      focusNode(priorFocusedElem);
	    }
	  },

	  /**
	   * @getSelection: Gets the selection bounds of a focused textarea, input or
	   * contentEditable node.
	   * -@input: Look up selection bounds of this input
	   * -@return {start: selectionStart, end: selectionEnd}
	   */
	  getSelection: function (input) {
	    var selection;

	    if ('selectionStart' in input) {
	      // Modern browser with input or textarea.
	      selection = {
	        start: input.selectionStart,
	        end: input.selectionEnd
	      };
	    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {
	      // IE8 input.
	      var range = document.selection.createRange();
	      // There can only be one selection per document in IE, so it must
	      // be in our element.
	      if (range.parentElement() === input) {
	        selection = {
	          start: -range.moveStart('character', -input.value.length),
	          end: -range.moveEnd('character', -input.value.length)
	        };
	      }
	    } else {
	      // Content editable or old IE textarea.
	      selection = ReactDOMSelection.getOffsets(input);
	    }

	    return selection || { start: 0, end: 0 };
	  },

	  /**
	   * @setSelection: Sets the selection bounds of a textarea or input and focuses
	   * the input.
	   * -@input     Set selection bounds of this input or textarea
	   * -@offsets   Object of same form that is returned from get*
	   */
	  setSelection: function (input, offsets) {
	    var start = offsets.start;
	    var end = offsets.end;
	    if (end === undefined) {
	      end = start;
	    }

	    if ('selectionStart' in input) {
	      input.selectionStart = start;
	      input.selectionEnd = Math.min(end, input.value.length);
	    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {
	      var range = input.createTextRange();
	      range.collapse(true);
	      range.moveStart('character', start);
	      range.moveEnd('character', end - start);
	      range.select();
	    } else {
	      ReactDOMSelection.setOffsets(input, offsets);
	    }
	  }
	};

	module.exports = ReactInputSelection;

/***/ },
/* 180 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ExecutionEnvironment = __webpack_require__(80);

	var getNodeForCharacterOffset = __webpack_require__(181);
	var getTextContentAccessor = __webpack_require__(83);

	/**
	 * While `isCollapsed` is available on the Selection object and `collapsed`
	 * is available on the Range object, IE11 sometimes gets them wrong.
	 * If the anchor/focus nodes and offsets are the same, the range is collapsed.
	 */
	function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
	  return anchorNode === focusNode && anchorOffset === focusOffset;
	}

	/**
	 * Get the appropriate anchor and focus node/offset pairs for IE.
	 *
	 * The catch here is that IE's selection API doesn't provide information
	 * about whether the selection is forward or backward, so we have to
	 * behave as though it's always forward.
	 *
	 * IE text differs from modern selection in that it behaves as though
	 * block elements end with a new line. This means character offsets will
	 * differ between the two APIs.
	 *
	 * @param {DOMElement} node
	 * @return {object}
	 */
	function getIEOffsets(node) {
	  var selection = document.selection;
	  var selectedRange = selection.createRange();
	  var selectedLength = selectedRange.text.length;

	  // Duplicate selection so we can move range without breaking user selection.
	  var fromStart = selectedRange.duplicate();
	  fromStart.moveToElementText(node);
	  fromStart.setEndPoint('EndToStart', selectedRange);

	  var startOffset = fromStart.text.length;
	  var endOffset = startOffset + selectedLength;

	  return {
	    start: startOffset,
	    end: endOffset
	  };
	}

	/**
	 * @param {DOMElement} node
	 * @return {?object}
	 */
	function getModernOffsets(node) {
	  var selection = window.getSelection && window.getSelection();

	  if (!selection || selection.rangeCount === 0) {
	    return null;
	  }

	  var anchorNode = selection.anchorNode;
	  var anchorOffset = selection.anchorOffset;
	  var focusNode = selection.focusNode;
	  var focusOffset = selection.focusOffset;

	  var currentRange = selection.getRangeAt(0);

	  // In Firefox, range.startContainer and range.endContainer can be "anonymous
	  // divs", e.g. the up/down buttons on an <input type="number">. Anonymous
	  // divs do not seem to expose properties, triggering a "Permission denied
	  // error" if any of its properties are accessed. The only seemingly possible
	  // way to avoid erroring is to access a property that typically works for
	  // non-anonymous divs and catch any error that may otherwise arise. See
	  // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
	  try {
	    /* eslint-disable no-unused-expressions */
	    currentRange.startContainer.nodeType;
	    currentRange.endContainer.nodeType;
	    /* eslint-enable no-unused-expressions */
	  } catch (e) {
	    return null;
	  }

	  // If the node and offset values are the same, the selection is collapsed.
	  // `Selection.isCollapsed` is available natively, but IE sometimes gets
	  // this value wrong.
	  var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);

	  var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;

	  var tempRange = currentRange.cloneRange();
	  tempRange.selectNodeContents(node);
	  tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);

	  var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset);

	  var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
	  var end = start + rangeLength;

	  // Detect whether the selection is backward.
	  var detectionRange = document.createRange();
	  detectionRange.setStart(anchorNode, anchorOffset);
	  detectionRange.setEnd(focusNode, focusOffset);
	  var isBackward = detectionRange.collapsed;

	  return {
	    start: isBackward ? end : start,
	    end: isBackward ? start : end
	  };
	}

	/**
	 * @param {DOMElement|DOMTextNode} node
	 * @param {object} offsets
	 */
	function setIEOffsets(node, offsets) {
	  var range = document.selection.createRange().duplicate();
	  var start, end;

	  if (offsets.end === undefined) {
	    start = offsets.start;
	    end = start;
	  } else if (offsets.start > offsets.end) {
	    start = offsets.end;
	    end = offsets.start;
	  } else {
	    start = offsets.start;
	    end = offsets.end;
	  }

	  range.moveToElementText(node);
	  range.moveStart('character', start);
	  range.setEndPoint('EndToStart', range);
	  range.moveEnd('character', end - start);
	  range.select();
	}

	/**
	 * In modern non-IE browsers, we can support both forward and backward
	 * selections.
	 *
	 * Note: IE10+ supports the Selection object, but it does not support
	 * the `extend` method, which means that even in modern IE, it's not possible
	 * to programmatically create a backward selection. Thus, for all IE
	 * versions, we use the old IE API to create our selections.
	 *
	 * @param {DOMElement|DOMTextNode} node
	 * @param {object} offsets
	 */
	function setModernOffsets(node, offsets) {
	  if (!window.getSelection) {
	    return;
	  }

	  var selection = window.getSelection();
	  var length = node[getTextContentAccessor()].length;
	  var start = Math.min(offsets.start, length);
	  var end = offsets.end === undefined ? start : Math.min(offsets.end, length);

	  // IE 11 uses modern selection, but doesn't support the extend method.
	  // Flip backward selections, so we can set with a single range.
	  if (!selection.extend && start > end) {
	    var temp = end;
	    end = start;
	    start = temp;
	  }

	  var startMarker = getNodeForCharacterOffset(node, start);
	  var endMarker = getNodeForCharacterOffset(node, end);

	  if (startMarker && endMarker) {
	    var range = document.createRange();
	    range.setStart(startMarker.node, startMarker.offset);
	    selection.removeAllRanges();

	    if (start > end) {
	      selection.addRange(range);
	      selection.extend(endMarker.node, endMarker.offset);
	    } else {
	      range.setEnd(endMarker.node, endMarker.offset);
	      selection.addRange(range);
	    }
	  }
	}

	var useIEOffsets = ExecutionEnvironment.canUseDOM && 'selection' in document && !('getSelection' in window);

	var ReactDOMSelection = {
	  /**
	   * @param {DOMElement} node
	   */
	  getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,

	  /**
	   * @param {DOMElement|DOMTextNode} node
	   * @param {object} offsets
	   */
	  setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets
	};

	module.exports = ReactDOMSelection;

/***/ },
/* 181 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * Given any node return the first leaf node without children.
	 *
	 * @param {DOMElement|DOMTextNode} node
	 * @return {DOMElement|DOMTextNode}
	 */

	function getLeafNode(node) {
	  while (node && node.firstChild) {
	    node = node.firstChild;
	  }
	  return node;
	}

	/**
	 * Get the next sibling within a container. This will walk up the
	 * DOM if a node's siblings have been exhausted.
	 *
	 * @param {DOMElement|DOMTextNode} node
	 * @return {?DOMElement|DOMTextNode}
	 */
	function getSiblingNode(node) {
	  while (node) {
	    if (node.nextSibling) {
	      return node.nextSibling;
	    }
	    node = node.parentNode;
	  }
	}

	/**
	 * Get object describing the nodes which contain characters at offset.
	 *
	 * @param {DOMElement|DOMTextNode} root
	 * @param {number} offset
	 * @return {?object}
	 */
	function getNodeForCharacterOffset(root, offset) {
	  var node = getLeafNode(root);
	  var nodeStart = 0;
	  var nodeEnd = 0;

	  while (node) {
	    if (node.nodeType === 3) {
	      nodeEnd = nodeStart + node.textContent.length;

	      if (nodeStart <= offset && nodeEnd >= offset) {
	        return {
	          node: node,
	          offset: offset - nodeStart
	        };
	      }

	      nodeStart = nodeEnd;
	    }

	    node = getLeafNode(getSiblingNode(node));
	  }
	}

	module.exports = getNodeForCharacterOffset;

/***/ },
/* 182 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	var isTextNode = __webpack_require__(183);

	/*eslint-disable no-bitwise */

	/**
	 * Checks if a given DOM node contains or is another DOM node.
	 */
	function containsNode(outerNode, innerNode) {
	  if (!outerNode || !innerNode) {
	    return false;
	  } else if (outerNode === innerNode) {
	    return true;
	  } else if (isTextNode(outerNode)) {
	    return false;
	  } else if (isTextNode(innerNode)) {
	    return containsNode(outerNode, innerNode.parentNode);
	  } else if ('contains' in outerNode) {
	    return outerNode.contains(innerNode);
	  } else if (outerNode.compareDocumentPosition) {
	    return !!(outerNode.compareDocumentPosition(innerNode) & 16);
	  } else {
	    return false;
	  }
	}

	module.exports = containsNode;

/***/ },
/* 183 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	var isNode = __webpack_require__(184);

	/**
	 * @param {*} object The object to check.
	 * @return {boolean} Whether or not the object is a DOM text node.
	 */
	function isTextNode(object) {
	  return isNode(object) && object.nodeType == 3;
	}

	module.exports = isTextNode;

/***/ },
/* 184 */
/***/ function(module, exports) {

	'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	/**
	 * @param {*} object The object to check.
	 * @return {boolean} Whether or not the object is a DOM node.
	 */
	function isNode(object) {
	  var doc = object ? object.ownerDocument || object : document;
	  var defaultView = doc.defaultView || window;
	  return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
	}

	module.exports = isNode;

/***/ },
/* 185 */
/***/ function(module, exports) {

	'use strict';

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * @typechecks
	 */

	/* eslint-disable fb-www/typeof-undefined */

	/**
	 * Same as document.activeElement but wraps in a try-catch block. In IE it is
	 * not safe to call document.activeElement if there is nothing focused.
	 *
	 * The activeElement will be null only if the document or document body is not
	 * yet defined.
	 *
	 * @param {?DOMDocument} doc Defaults to current document.
	 * @return {?DOMElement}
	 */
	function getActiveElement(doc) /*?DOMElement*/{
	  doc = doc || (typeof document !== 'undefined' ? document : undefined);
	  if (typeof doc === 'undefined') {
	    return null;
	  }
	  try {
	    return doc.activeElement || doc.body;
	  } catch (e) {
	    return doc.body;
	  }
	}

	module.exports = getActiveElement;

/***/ },
/* 186 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var NS = {
	  xlink: 'http://www.w3.org/1999/xlink',
	  xml: 'http://www.w3.org/XML/1998/namespace'
	};

	// We use attributes for everything SVG so let's avoid some duplication and run
	// code instead.
	// The following are all specified in the HTML config already so we exclude here.
	// - class (as className)
	// - color
	// - height
	// - id
	// - lang
	// - max
	// - media
	// - method
	// - min
	// - name
	// - style
	// - target
	// - type
	// - width
	var ATTRS = {
	  accentHeight: 'accent-height',
	  accumulate: 0,
	  additive: 0,
	  alignmentBaseline: 'alignment-baseline',
	  allowReorder: 'allowReorder',
	  alphabetic: 0,
	  amplitude: 0,
	  arabicForm: 'arabic-form',
	  ascent: 0,
	  attributeName: 'attributeName',
	  attributeType: 'attributeType',
	  autoReverse: 'autoReverse',
	  azimuth: 0,
	  baseFrequency: 'baseFrequency',
	  baseProfile: 'baseProfile',
	  baselineShift: 'baseline-shift',
	  bbox: 0,
	  begin: 0,
	  bias: 0,
	  by: 0,
	  calcMode: 'calcMode',
	  capHeight: 'cap-height',
	  clip: 0,
	  clipPath: 'clip-path',
	  clipRule: 'clip-rule',
	  clipPathUnits: 'clipPathUnits',
	  colorInterpolation: 'color-interpolation',
	  colorInterpolationFilters: 'color-interpolation-filters',
	  colorProfile: 'color-profile',
	  colorRendering: 'color-rendering',
	  contentScriptType: 'contentScriptType',
	  contentStyleType: 'contentStyleType',
	  cursor: 0,
	  cx: 0,
	  cy: 0,
	  d: 0,
	  decelerate: 0,
	  descent: 0,
	  diffuseConstant: 'diffuseConstant',
	  direction: 0,
	  display: 0,
	  divisor: 0,
	  dominantBaseline: 'dominant-baseline',
	  dur: 0,
	  dx: 0,
	  dy: 0,
	  edgeMode: 'edgeMode',
	  elevation: 0,
	  enableBackground: 'enable-background',
	  end: 0,
	  exponent: 0,
	  externalResourcesRequired: 'externalResourcesRequired',
	  fill: 0,
	  fillOpacity: 'fill-opacity',
	  fillRule: 'fill-rule',
	  filter: 0,
	  filterRes: 'filterRes',
	  filterUnits: 'filterUnits',
	  floodColor: 'flood-color',
	  floodOpacity: 'flood-opacity',
	  focusable: 0,
	  fontFamily: 'font-family',
	  fontSize: 'font-size',
	  fontSizeAdjust: 'font-size-adjust',
	  fontStretch: 'font-stretch',
	  fontStyle: 'font-style',
	  fontVariant: 'font-variant',
	  fontWeight: 'font-weight',
	  format: 0,
	  from: 0,
	  fx: 0,
	  fy: 0,
	  g1: 0,
	  g2: 0,
	  glyphName: 'glyph-name',
	  glyphOrientationHorizontal: 'glyph-orientation-horizontal',
	  glyphOrientationVertical: 'glyph-orientation-vertical',
	  glyphRef: 'glyphRef',
	  gradientTransform: 'gradientTransform',
	  gradientUnits: 'gradientUnits',
	  hanging: 0,
	  horizAdvX: 'horiz-adv-x',
	  horizOriginX: 'horiz-origin-x',
	  ideographic: 0,
	  imageRendering: 'image-rendering',
	  'in': 0,
	  in2: 0,
	  intercept: 0,
	  k: 0,
	  k1: 0,
	  k2: 0,
	  k3: 0,
	  k4: 0,
	  kernelMatrix: 'kernelMatrix',
	  kernelUnitLength: 'kernelUnitLength',
	  kerning: 0,
	  keyPoints: 'keyPoints',
	  keySplines: 'keySplines',
	  keyTimes: 'keyTimes',
	  lengthAdjust: 'lengthAdjust',
	  letterSpacing: 'letter-spacing',
	  lightingColor: 'lighting-color',
	  limitingConeAngle: 'limitingConeAngle',
	  local: 0,
	  markerEnd: 'marker-end',
	  markerMid: 'marker-mid',
	  markerStart: 'marker-start',
	  markerHeight: 'markerHeight',
	  markerUnits: 'markerUnits',
	  markerWidth: 'markerWidth',
	  mask: 0,
	  maskContentUnits: 'maskContentUnits',
	  maskUnits: 'maskUnits',
	  mathematical: 0,
	  mode: 0,
	  numOctaves: 'numOctaves',
	  offset: 0,
	  opacity: 0,
	  operator: 0,
	  order: 0,
	  orient: 0,
	  orientation: 0,
	  origin: 0,
	  overflow: 0,
	  overlinePosition: 'overline-position',
	  overlineThickness: 'overline-thickness',
	  paintOrder: 'paint-order',
	  panose1: 'panose-1',
	  pathLength: 'pathLength',
	  patternContentUnits: 'patternContentUnits',
	  patternTransform: 'patternTransform',
	  patternUnits: 'patternUnits',
	  pointerEvents: 'pointer-events',
	  points: 0,
	  pointsAtX: 'pointsAtX',
	  pointsAtY: 'pointsAtY',
	  pointsAtZ: 'pointsAtZ',
	  preserveAlpha: 'preserveAlpha',
	  preserveAspectRatio: 'preserveAspectRatio',
	  primitiveUnits: 'primitiveUnits',
	  r: 0,
	  radius: 0,
	  refX: 'refX',
	  refY: 'refY',
	  renderingIntent: 'rendering-intent',
	  repeatCount: 'repeatCount',
	  repeatDur: 'repeatDur',
	  requiredExtensions: 'requiredExtensions',
	  requiredFeatures: 'requiredFeatures',
	  restart: 0,
	  result: 0,
	  rotate: 0,
	  rx: 0,
	  ry: 0,
	  scale: 0,
	  seed: 0,
	  shapeRendering: 'shape-rendering',
	  slope: 0,
	  spacing: 0,
	  specularConstant: 'specularConstant',
	  specularExponent: 'specularExponent',
	  speed: 0,
	  spreadMethod: 'spreadMethod',
	  startOffset: 'startOffset',
	  stdDeviation: 'stdDeviation',
	  stemh: 0,
	  stemv: 0,
	  stitchTiles: 'stitchTiles',
	  stopColor: 'stop-color',
	  stopOpacity: 'stop-opacity',
	  strikethroughPosition: 'strikethrough-position',
	  strikethroughThickness: 'strikethrough-thickness',
	  string: 0,
	  stroke: 0,
	  strokeDasharray: 'stroke-dasharray',
	  strokeDashoffset: 'stroke-dashoffset',
	  strokeLinecap: 'stroke-linecap',
	  strokeLinejoin: 'stroke-linejoin',
	  strokeMiterlimit: 'stroke-miterlimit',
	  strokeOpacity: 'stroke-opacity',
	  strokeWidth: 'stroke-width',
	  surfaceScale: 'surfaceScale',
	  systemLanguage: 'systemLanguage',
	  tableValues: 'tableValues',
	  targetX: 'targetX',
	  targetY: 'targetY',
	  textAnchor: 'text-anchor',
	  textDecoration: 'text-decoration',
	  textRendering: 'text-rendering',
	  textLength: 'textLength',
	  to: 0,
	  transform: 0,
	  u1: 0,
	  u2: 0,
	  underlinePosition: 'underline-position',
	  underlineThickness: 'underline-thickness',
	  unicode: 0,
	  unicodeBidi: 'unicode-bidi',
	  unicodeRange: 'unicode-range',
	  unitsPerEm: 'units-per-em',
	  vAlphabetic: 'v-alphabetic',
	  vHanging: 'v-hanging',
	  vIdeographic: 'v-ideographic',
	  vMathematical: 'v-mathematical',
	  values: 0,
	  vectorEffect: 'vector-effect',
	  version: 0,
	  vertAdvY: 'vert-adv-y',
	  vertOriginX: 'vert-origin-x',
	  vertOriginY: 'vert-origin-y',
	  viewBox: 'viewBox',
	  viewTarget: 'viewTarget',
	  visibility: 0,
	  widths: 0,
	  wordSpacing: 'word-spacing',
	  writingMode: 'writing-mode',
	  x: 0,
	  xHeight: 'x-height',
	  x1: 0,
	  x2: 0,
	  xChannelSelector: 'xChannelSelector',
	  xlinkActuate: 'xlink:actuate',
	  xlinkArcrole: 'xlink:arcrole',
	  xlinkHref: 'xlink:href',
	  xlinkRole: 'xlink:role',
	  xlinkShow: 'xlink:show',
	  xlinkTitle: 'xlink:title',
	  xlinkType: 'xlink:type',
	  xmlBase: 'xml:base',
	  xmlns: 0,
	  xmlnsXlink: 'xmlns:xlink',
	  xmlLang: 'xml:lang',
	  xmlSpace: 'xml:space',
	  y: 0,
	  y1: 0,
	  y2: 0,
	  yChannelSelector: 'yChannelSelector',
	  z: 0,
	  zoomAndPan: 'zoomAndPan'
	};

	var SVGDOMPropertyConfig = {
	  Properties: {},
	  DOMAttributeNamespaces: {
	    xlinkActuate: NS.xlink,
	    xlinkArcrole: NS.xlink,
	    xlinkHref: NS.xlink,
	    xlinkRole: NS.xlink,
	    xlinkShow: NS.xlink,
	    xlinkTitle: NS.xlink,
	    xlinkType: NS.xlink,
	    xmlBase: NS.xml,
	    xmlLang: NS.xml,
	    xmlSpace: NS.xml
	  },
	  DOMAttributeNames: {}
	};

	Object.keys(ATTRS).forEach(function (key) {
	  SVGDOMPropertyConfig.Properties[key] = 0;
	  if (ATTRS[key]) {
	    SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key];
	  }
	});

	module.exports = SVGDOMPropertyConfig;

/***/ },
/* 187 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var EventPropagators = __webpack_require__(73);
	var ExecutionEnvironment = __webpack_require__(80);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactInputSelection = __webpack_require__(179);
	var SyntheticEvent = __webpack_require__(85);

	var getActiveElement = __webpack_require__(185);
	var isTextInputElement = __webpack_require__(104);
	var shallowEqual = __webpack_require__(156);

	var skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11;

	var eventTypes = {
	  select: {
	    phasedRegistrationNames: {
	      bubbled: 'onSelect',
	      captured: 'onSelectCapture'
	    },
	    dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange']
	  }
	};

	var activeElement = null;
	var activeElementInst = null;
	var lastSelection = null;
	var mouseDown = false;

	// Track whether a listener exists for this plugin. If none exist, we do
	// not extract events. See #3639.
	var hasListener = false;

	/**
	 * Get an object which is a unique representation of the current selection.
	 *
	 * The return value will not be consistent across nodes or browsers, but
	 * two identical selections on the same node will return identical objects.
	 *
	 * @param {DOMElement} node
	 * @return {object}
	 */
	function getSelection(node) {
	  if ('selectionStart' in node && ReactInputSelection.hasSelectionCapabilities(node)) {
	    return {
	      start: node.selectionStart,
	      end: node.selectionEnd
	    };
	  } else if (window.getSelection) {
	    var selection = window.getSelection();
	    return {
	      anchorNode: selection.anchorNode,
	      anchorOffset: selection.anchorOffset,
	      focusNode: selection.focusNode,
	      focusOffset: selection.focusOffset
	    };
	  } else if (document.selection) {
	    var range = document.selection.createRange();
	    return {
	      parentElement: range.parentElement(),
	      text: range.text,
	      top: range.boundingTop,
	      left: range.boundingLeft
	    };
	  }
	}

	/**
	 * Poll selection to see whether it's changed.
	 *
	 * @param {object} nativeEvent
	 * @return {?SyntheticEvent}
	 */
	function constructSelectEvent(nativeEvent, nativeEventTarget) {
	  // Ensure we have the right element, and that the user is not dragging a
	  // selection (this matches native `select` event behavior). In HTML5, select
	  // fires only on input and textarea thus if there's no focused element we
	  // won't dispatch.
	  if (mouseDown || activeElement == null || activeElement !== getActiveElement()) {
	    return null;
	  }

	  // Only fire when selection has actually changed.
	  var currentSelection = getSelection(activeElement);
	  if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {
	    lastSelection = currentSelection;

	    var syntheticEvent = SyntheticEvent.getPooled(eventTypes.select, activeElementInst, nativeEvent, nativeEventTarget);

	    syntheticEvent.type = 'select';
	    syntheticEvent.target = activeElement;

	    EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent);

	    return syntheticEvent;
	  }

	  return null;
	}

	/**
	 * This plugin creates an `onSelect` event that normalizes select events
	 * across form elements.
	 *
	 * Supported elements are:
	 * - input (see `isTextInputElement`)
	 * - textarea
	 * - contentEditable
	 *
	 * This differs from native browser implementations in the following ways:
	 * - Fires on contentEditable fields as well as inputs.
	 * - Fires for collapsed selection.
	 * - Fires after user input.
	 */
	var SelectEventPlugin = {
	  eventTypes: eventTypes,

	  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	    if (!hasListener) {
	      return null;
	    }

	    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;

	    switch (topLevelType) {
	      // Track the input node that has focus.
	      case 'topFocus':
	        if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
	          activeElement = targetNode;
	          activeElementInst = targetInst;
	          lastSelection = null;
	        }
	        break;
	      case 'topBlur':
	        activeElement = null;
	        activeElementInst = null;
	        lastSelection = null;
	        break;
	      // Don't fire the event while the user is dragging. This matches the
	      // semantics of the native select event.
	      case 'topMouseDown':
	        mouseDown = true;
	        break;
	      case 'topContextMenu':
	      case 'topMouseUp':
	        mouseDown = false;
	        return constructSelectEvent(nativeEvent, nativeEventTarget);
	      // Chrome and IE fire non-standard event when selection is changed (and
	      // sometimes when it hasn't). IE's event fires out of order with respect
	      // to key and input events on deletion, so we discard it.
	      //
	      // Firefox doesn't support selectionchange, so check selection status
	      // after each key entry. The selection changes after keydown and before
	      // keyup, but we check on keydown as well in the case of holding down a
	      // key, when multiple keydown events are fired but only one keyup is.
	      // This is also our approach for IE handling, for the reason above.
	      case 'topSelectionChange':
	        if (skipSelectionChangeEvent) {
	          break;
	        }
	      // falls through
	      case 'topKeyDown':
	      case 'topKeyUp':
	        return constructSelectEvent(nativeEvent, nativeEventTarget);
	    }

	    return null;
	  },

	  didPutListener: function (inst, registrationName, listener) {
	    if (registrationName === 'onSelect') {
	      hasListener = true;
	    }
	  }
	};

	module.exports = SelectEventPlugin;

/***/ },
/* 188 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var EventListener = __webpack_require__(175);
	var EventPropagators = __webpack_require__(73);
	var ReactDOMComponentTree = __webpack_require__(66);
	var SyntheticAnimationEvent = __webpack_require__(189);
	var SyntheticClipboardEvent = __webpack_require__(190);
	var SyntheticEvent = __webpack_require__(85);
	var SyntheticFocusEvent = __webpack_require__(191);
	var SyntheticKeyboardEvent = __webpack_require__(192);
	var SyntheticMouseEvent = __webpack_require__(107);
	var SyntheticDragEvent = __webpack_require__(195);
	var SyntheticTouchEvent = __webpack_require__(196);
	var SyntheticTransitionEvent = __webpack_require__(197);
	var SyntheticUIEvent = __webpack_require__(108);
	var SyntheticWheelEvent = __webpack_require__(198);

	var emptyFunction = __webpack_require__(36);
	var getEventCharCode = __webpack_require__(193);
	var invariant = __webpack_require__(39);

	/**
	 * Turns
	 * ['abort', ...]
	 * into
	 * eventTypes = {
	 *   'abort': {
	 *     phasedRegistrationNames: {
	 *       bubbled: 'onAbort',
	 *       captured: 'onAbortCapture',
	 *     },
	 *     dependencies: ['topAbort'],
	 *   },
	 *   ...
	 * };
	 * topLevelEventsToDispatchConfig = {
	 *   'topAbort': { sameConfig }
	 * };
	 */
	var eventTypes = {};
	var topLevelEventsToDispatchConfig = {};
	['abort', 'animationEnd', 'animationIteration', 'animationStart', 'blur', 'canPlay', 'canPlayThrough', 'click', 'contextMenu', 'copy', 'cut', 'doubleClick', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'focus', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'progress', 'rateChange', 'reset', 'scroll', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'touchCancel', 'touchEnd', 'touchMove', 'touchStart', 'transitionEnd', 'volumeChange', 'waiting', 'wheel'].forEach(function (event) {
	  var capitalizedEvent = event[0].toUpperCase() + event.slice(1);
	  var onEvent = 'on' + capitalizedEvent;
	  var topEvent = 'top' + capitalizedEvent;

	  var type = {
	    phasedRegistrationNames: {
	      bubbled: onEvent,
	      captured: onEvent + 'Capture'
	    },
	    dependencies: [topEvent]
	  };
	  eventTypes[event] = type;
	  topLevelEventsToDispatchConfig[topEvent] = type;
	});

	var onClickListeners = {};

	function getDictionaryKey(inst) {
	  // Prevents V8 performance issue:
	  // https://github.com/facebook/react/pull/7232
	  return '.' + inst._rootNodeID;
	}

	function isInteractive(tag) {
	  return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
	}

	var SimpleEventPlugin = {
	  eventTypes: eventTypes,

	  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
	    var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
	    if (!dispatchConfig) {
	      return null;
	    }
	    var EventConstructor;
	    switch (topLevelType) {
	      case 'topAbort':
	      case 'topCanPlay':
	      case 'topCanPlayThrough':
	      case 'topDurationChange':
	      case 'topEmptied':
	      case 'topEncrypted':
	      case 'topEnded':
	      case 'topError':
	      case 'topInput':
	      case 'topInvalid':
	      case 'topLoad':
	      case 'topLoadedData':
	      case 'topLoadedMetadata':
	      case 'topLoadStart':
	      case 'topPause':
	      case 'topPlay':
	      case 'topPlaying':
	      case 'topProgress':
	      case 'topRateChange':
	      case 'topReset':
	      case 'topSeeked':
	      case 'topSeeking':
	      case 'topStalled':
	      case 'topSubmit':
	      case 'topSuspend':
	      case 'topTimeUpdate':
	      case 'topVolumeChange':
	      case 'topWaiting':
	        // HTML Events
	        // @see http://www.w3.org/TR/html5/index.html#events-0
	        EventConstructor = SyntheticEvent;
	        break;
	      case 'topKeyPress':
	        // Firefox creates a keypress event for function keys too. This removes
	        // the unwanted keypress events. Enter is however both printable and
	        // non-printable. One would expect Tab to be as well (but it isn't).
	        if (getEventCharCode(nativeEvent) === 0) {
	          return null;
	        }
	      /* falls through */
	      case 'topKeyDown':
	      case 'topKeyUp':
	        EventConstructor = SyntheticKeyboardEvent;
	        break;
	      case 'topBlur':
	      case 'topFocus':
	        EventConstructor = SyntheticFocusEvent;
	        break;
	      case 'topClick':
	        // Firefox creates a click event on right mouse clicks. This removes the
	        // unwanted click events.
	        if (nativeEvent.button === 2) {
	          return null;
	        }
	      /* falls through */
	      case 'topDoubleClick':
	      case 'topMouseDown':
	      case 'topMouseMove':
	      case 'topMouseUp':
	      // TODO: Disabled elements should not respond to mouse events
	      /* falls through */
	      case 'topMouseOut':
	      case 'topMouseOver':
	      case 'topContextMenu':
	        EventConstructor = SyntheticMouseEvent;
	        break;
	      case 'topDrag':
	      case 'topDragEnd':
	      case 'topDragEnter':
	      case 'topDragExit':
	      case 'topDragLeave':
	      case 'topDragOver':
	      case 'topDragStart':
	      case 'topDrop':
	        EventConstructor = SyntheticDragEvent;
	        break;
	      case 'topTouchCancel':
	      case 'topTouchEnd':
	      case 'topTouchMove':
	      case 'topTouchStart':
	        EventConstructor = SyntheticTouchEvent;
	        break;
	      case 'topAnimationEnd':
	      case 'topAnimationIteration':
	      case 'topAnimationStart':
	        EventConstructor = SyntheticAnimationEvent;
	        break;
	      case 'topTransitionEnd':
	        EventConstructor = SyntheticTransitionEvent;
	        break;
	      case 'topScroll':
	        EventConstructor = SyntheticUIEvent;
	        break;
	      case 'topWheel':
	        EventConstructor = SyntheticWheelEvent;
	        break;
	      case 'topCopy':
	      case 'topCut':
	      case 'topPaste':
	        EventConstructor = SyntheticClipboardEvent;
	        break;
	    }
	    !EventConstructor ? process.env.NODE_ENV !== 'production' ? invariant(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : _prodInvariant('86', topLevelType) : void 0;
	    var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
	    EventPropagators.accumulateTwoPhaseDispatches(event);
	    return event;
	  },

	  didPutListener: function (inst, registrationName, listener) {
	    // Mobile Safari does not fire properly bubble click events on
	    // non-interactive elements, which means delegated click listeners do not
	    // fire. The workaround for this bug involves attaching an empty click
	    // listener on the target node.
	    // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
	    if (registrationName === 'onClick' && !isInteractive(inst._tag)) {
	      var key = getDictionaryKey(inst);
	      var node = ReactDOMComponentTree.getNodeFromInstance(inst);
	      if (!onClickListeners[key]) {
	        onClickListeners[key] = EventListener.listen(node, 'click', emptyFunction);
	      }
	    }
	  },

	  willDeleteListener: function (inst, registrationName) {
	    if (registrationName === 'onClick' && !isInteractive(inst._tag)) {
	      var key = getDictionaryKey(inst);
	      onClickListeners[key].remove();
	      delete onClickListeners[key];
	    }
	  }
	};

	module.exports = SimpleEventPlugin;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 189 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticEvent = __webpack_require__(85);

	/**
	 * @interface Event
	 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
	 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
	 */
	var AnimationEventInterface = {
	  animationName: null,
	  elapsedTime: null,
	  pseudoElement: null
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticEvent}
	 */
	function SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);

	module.exports = SyntheticAnimationEvent;

/***/ },
/* 190 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticEvent = __webpack_require__(85);

	/**
	 * @interface Event
	 * @see http://www.w3.org/TR/clipboard-apis/
	 */
	var ClipboardEventInterface = {
	  clipboardData: function (event) {
	    return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
	  }
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);

	module.exports = SyntheticClipboardEvent;

/***/ },
/* 191 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticUIEvent = __webpack_require__(108);

	/**
	 * @interface FocusEvent
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/
	 */
	var FocusEventInterface = {
	  relatedTarget: null
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);

	module.exports = SyntheticFocusEvent;

/***/ },
/* 192 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticUIEvent = __webpack_require__(108);

	var getEventCharCode = __webpack_require__(193);
	var getEventKey = __webpack_require__(194);
	var getEventModifierState = __webpack_require__(110);

	/**
	 * @interface KeyboardEvent
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/
	 */
	var KeyboardEventInterface = {
	  key: getEventKey,
	  location: null,
	  ctrlKey: null,
	  shiftKey: null,
	  altKey: null,
	  metaKey: null,
	  repeat: null,
	  locale: null,
	  getModifierState: getEventModifierState,
	  // Legacy Interface
	  charCode: function (event) {
	    // `charCode` is the result of a KeyPress event and represents the value of
	    // the actual printable character.

	    // KeyPress is deprecated, but its replacement is not yet final and not
	    // implemented in any major browser. Only KeyPress has charCode.
	    if (event.type === 'keypress') {
	      return getEventCharCode(event);
	    }
	    return 0;
	  },
	  keyCode: function (event) {
	    // `keyCode` is the result of a KeyDown/Up event and represents the value of
	    // physical keyboard key.

	    // The actual meaning of the value depends on the users' keyboard layout
	    // which cannot be detected. Assuming that it is a US keyboard layout
	    // provides a surprisingly accurate mapping for US and European users.
	    // Due to this, it is left to the user to implement at this time.
	    if (event.type === 'keydown' || event.type === 'keyup') {
	      return event.keyCode;
	    }
	    return 0;
	  },
	  which: function (event) {
	    // `which` is an alias for either `keyCode` or `charCode` depending on the
	    // type of the event.
	    if (event.type === 'keypress') {
	      return getEventCharCode(event);
	    }
	    if (event.type === 'keydown' || event.type === 'keyup') {
	      return event.keyCode;
	    }
	    return 0;
	  }
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);

	module.exports = SyntheticKeyboardEvent;

/***/ },
/* 193 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	/**
	 * `charCode` represents the actual "character code" and is safe to use with
	 * `String.fromCharCode`. As such, only keys that correspond to printable
	 * characters produce a valid `charCode`, the only exception to this is Enter.
	 * The Tab-key is considered non-printable and does not have a `charCode`,
	 * presumably because it does not produce a tab-character in browsers.
	 *
	 * @param {object} nativeEvent Native browser event.
	 * @return {number} Normalized `charCode` property.
	 */

	function getEventCharCode(nativeEvent) {
	  var charCode;
	  var keyCode = nativeEvent.keyCode;

	  if ('charCode' in nativeEvent) {
	    charCode = nativeEvent.charCode;

	    // FF does not set `charCode` for the Enter-key, check against `keyCode`.
	    if (charCode === 0 && keyCode === 13) {
	      charCode = 13;
	    }
	  } else {
	    // IE8 does not implement `charCode`, but `keyCode` has the correct value.
	    charCode = keyCode;
	  }

	  // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
	  // Must not discard the (non-)printable Enter-key.
	  if (charCode >= 32 || charCode === 13) {
	    return charCode;
	  }

	  return 0;
	}

	module.exports = getEventCharCode;

/***/ },
/* 194 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var getEventCharCode = __webpack_require__(193);

	/**
	 * Normalization of deprecated HTML5 `key` values
	 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
	 */
	var normalizeKey = {
	  Esc: 'Escape',
	  Spacebar: ' ',
	  Left: 'ArrowLeft',
	  Up: 'ArrowUp',
	  Right: 'ArrowRight',
	  Down: 'ArrowDown',
	  Del: 'Delete',
	  Win: 'OS',
	  Menu: 'ContextMenu',
	  Apps: 'ContextMenu',
	  Scroll: 'ScrollLock',
	  MozPrintableKey: 'Unidentified'
	};

	/**
	 * Translation from legacy `keyCode` to HTML5 `key`
	 * Only special keys supported, all others depend on keyboard layout or browser
	 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
	 */
	var translateToKey = {
	  8: 'Backspace',
	  9: 'Tab',
	  12: 'Clear',
	  13: 'Enter',
	  16: 'Shift',
	  17: 'Control',
	  18: 'Alt',
	  19: 'Pause',
	  20: 'CapsLock',
	  27: 'Escape',
	  32: ' ',
	  33: 'PageUp',
	  34: 'PageDown',
	  35: 'End',
	  36: 'Home',
	  37: 'ArrowLeft',
	  38: 'ArrowUp',
	  39: 'ArrowRight',
	  40: 'ArrowDown',
	  45: 'Insert',
	  46: 'Delete',
	  112: 'F1',
	  113: 'F2',
	  114: 'F3',
	  115: 'F4',
	  116: 'F5',
	  117: 'F6',
	  118: 'F7',
	  119: 'F8',
	  120: 'F9',
	  121: 'F10',
	  122: 'F11',
	  123: 'F12',
	  144: 'NumLock',
	  145: 'ScrollLock',
	  224: 'Meta'
	};

	/**
	 * @param {object} nativeEvent Native browser event.
	 * @return {string} Normalized `key` property.
	 */
	function getEventKey(nativeEvent) {
	  if (nativeEvent.key) {
	    // Normalize inconsistent values reported by browsers due to
	    // implementations of a working draft specification.

	    // FireFox implements `key` but returns `MozPrintableKey` for all
	    // printable characters (normalized to `Unidentified`), ignore it.
	    var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
	    if (key !== 'Unidentified') {
	      return key;
	    }
	  }

	  // Browser does not implement `key`, polyfill as much of it as we can.
	  if (nativeEvent.type === 'keypress') {
	    var charCode = getEventCharCode(nativeEvent);

	    // The enter-key is technically both printable and non-printable and can
	    // thus be captured by `keypress`, no other non-printable key should.
	    return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
	  }
	  if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
	    // While user keyboard layout determines the actual meaning of each
	    // `keyCode` value, almost all function keys have a universal value.
	    return translateToKey[nativeEvent.keyCode] || 'Unidentified';
	  }
	  return '';
	}

	module.exports = getEventKey;

/***/ },
/* 195 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticMouseEvent = __webpack_require__(107);

	/**
	 * @interface DragEvent
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/
	 */
	var DragEventInterface = {
	  dataTransfer: null
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);

	module.exports = SyntheticDragEvent;

/***/ },
/* 196 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticUIEvent = __webpack_require__(108);

	var getEventModifierState = __webpack_require__(110);

	/**
	 * @interface TouchEvent
	 * @see http://www.w3.org/TR/touch-events/
	 */
	var TouchEventInterface = {
	  touches: null,
	  targetTouches: null,
	  changedTouches: null,
	  altKey: null,
	  metaKey: null,
	  ctrlKey: null,
	  shiftKey: null,
	  getModifierState: getEventModifierState
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticUIEvent}
	 */
	function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);

	module.exports = SyntheticTouchEvent;

/***/ },
/* 197 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticEvent = __webpack_require__(85);

	/**
	 * @interface Event
	 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
	 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
	 */
	var TransitionEventInterface = {
	  propertyName: null,
	  elapsedTime: null,
	  pseudoElement: null
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticEvent}
	 */
	function SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);

	module.exports = SyntheticTransitionEvent;

/***/ },
/* 198 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var SyntheticMouseEvent = __webpack_require__(107);

	/**
	 * @interface WheelEvent
	 * @see http://www.w3.org/TR/DOM-Level-3-Events/
	 */
	var WheelEventInterface = {
	  deltaX: function (event) {
	    return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
	    'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
	  },
	  deltaY: function (event) {
	    return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
	    'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
	    'wheelDelta' in event ? -event.wheelDelta : 0;
	  },
	  deltaZ: null,

	  // Browsers without "deltaMode" is reporting in raw wheel delta where one
	  // notch on the scroll is always +/- 120, roughly equivalent to pixels.
	  // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
	  // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
	  deltaMode: null
	};

	/**
	 * @param {object} dispatchConfig Configuration used to dispatch this event.
	 * @param {string} dispatchMarker Marker identifying the event target.
	 * @param {object} nativeEvent Native browser event.
	 * @extends {SyntheticMouseEvent}
	 */
	function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
	  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
	}

	SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);

	module.exports = SyntheticWheelEvent;

/***/ },
/* 199 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var DOMLazyTree = __webpack_require__(114);
	var DOMProperty = __webpack_require__(68);
	var React = __webpack_require__(29);
	var ReactBrowserEventEmitter = __webpack_require__(138);
	var ReactCurrentOwner = __webpack_require__(44);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactDOMContainerInfo = __webpack_require__(200);
	var ReactDOMFeatureFlags = __webpack_require__(201);
	var ReactFeatureFlags = __webpack_require__(90);
	var ReactInstanceMap = __webpack_require__(149);
	var ReactInstrumentation = __webpack_require__(94);
	var ReactMarkupChecksum = __webpack_require__(202);
	var ReactReconciler = __webpack_require__(91);
	var ReactUpdateQueue = __webpack_require__(168);
	var ReactUpdates = __webpack_require__(88);

	var emptyObject = __webpack_require__(38);
	var instantiateReactComponent = __webpack_require__(151);
	var invariant = __webpack_require__(39);
	var setInnerHTML = __webpack_require__(116);
	var shouldUpdateReactComponent = __webpack_require__(157);
	var warning = __webpack_require__(35);

	var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
	var ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;

	var ELEMENT_NODE_TYPE = 1;
	var DOC_NODE_TYPE = 9;
	var DOCUMENT_FRAGMENT_NODE_TYPE = 11;

	var instancesByReactRootID = {};

	/**
	 * Finds the index of the first character
	 * that's not common between the two given strings.
	 *
	 * @return {number} the index of the character where the strings diverge
	 */
	function firstDifferenceIndex(string1, string2) {
	  var minLen = Math.min(string1.length, string2.length);
	  for (var i = 0; i < minLen; i++) {
	    if (string1.charAt(i) !== string2.charAt(i)) {
	      return i;
	    }
	  }
	  return string1.length === string2.length ? -1 : minLen;
	}

	/**
	 * @param {DOMElement|DOMDocument} container DOM element that may contain
	 * a React component
	 * @return {?*} DOM element that may have the reactRoot ID, or null.
	 */
	function getReactRootElementInContainer(container) {
	  if (!container) {
	    return null;
	  }

	  if (container.nodeType === DOC_NODE_TYPE) {
	    return container.documentElement;
	  } else {
	    return container.firstChild;
	  }
	}

	function internalGetID(node) {
	  // If node is something like a window, document, or text node, none of
	  // which support attributes or a .getAttribute method, gracefully return
	  // the empty string, as if the attribute were missing.
	  return node.getAttribute && node.getAttribute(ATTR_NAME) || '';
	}

	/**
	 * Mounts this component and inserts it into the DOM.
	 *
	 * @param {ReactComponent} componentInstance The instance to mount.
	 * @param {DOMElement} container DOM element to mount into.
	 * @param {ReactReconcileTransaction} transaction
	 * @param {boolean} shouldReuseMarkup If true, do not insert markup
	 */
	function mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) {
	  var markerName;
	  if (ReactFeatureFlags.logTopLevelRenders) {
	    var wrappedElement = wrapperInstance._currentElement.props.child;
	    var type = wrappedElement.type;
	    markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name);
	    console.time(markerName);
	  }

	  var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context, 0 /* parentDebugID */
	  );

	  if (markerName) {
	    console.timeEnd(markerName);
	  }

	  wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;
	  ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction);
	}

	/**
	 * Batched mount.
	 *
	 * @param {ReactComponent} componentInstance The instance to mount.
	 * @param {DOMElement} container DOM element to mount into.
	 * @param {boolean} shouldReuseMarkup If true, do not insert markup
	 */
	function batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) {
	  var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(
	  /* useCreateElement */
	  !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement);
	  transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context);
	  ReactUpdates.ReactReconcileTransaction.release(transaction);
	}

	/**
	 * Unmounts a component and removes it from the DOM.
	 *
	 * @param {ReactComponent} instance React component instance.
	 * @param {DOMElement} container DOM element to unmount from.
	 * @final
	 * @internal
	 * @see {ReactMount.unmountComponentAtNode}
	 */
	function unmountComponentFromNode(instance, container, safely) {
	  if (process.env.NODE_ENV !== 'production') {
	    ReactInstrumentation.debugTool.onBeginFlush();
	  }
	  ReactReconciler.unmountComponent(instance, safely);
	  if (process.env.NODE_ENV !== 'production') {
	    ReactInstrumentation.debugTool.onEndFlush();
	  }

	  if (container.nodeType === DOC_NODE_TYPE) {
	    container = container.documentElement;
	  }

	  // http://jsperf.com/emptying-a-node
	  while (container.lastChild) {
	    container.removeChild(container.lastChild);
	  }
	}

	/**
	 * True if the supplied DOM node has a direct React-rendered child that is
	 * not a React root element. Useful for warning in `render`,
	 * `unmountComponentAtNode`, etc.
	 *
	 * @param {?DOMElement} node The candidate DOM node.
	 * @return {boolean} True if the DOM element contains a direct child that was
	 * rendered by React but is not a root element.
	 * @internal
	 */
	function hasNonRootReactChild(container) {
	  var rootEl = getReactRootElementInContainer(container);
	  if (rootEl) {
	    var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);
	    return !!(inst && inst._hostParent);
	  }
	}

	/**
	 * True if the supplied DOM node is a React DOM element and
	 * it has been rendered by another copy of React.
	 *
	 * @param {?DOMElement} node The candidate DOM node.
	 * @return {boolean} True if the DOM has been rendered by another copy of React
	 * @internal
	 */
	function nodeIsRenderedByOtherInstance(container) {
	  var rootEl = getReactRootElementInContainer(container);
	  return !!(rootEl && isReactNode(rootEl) && !ReactDOMComponentTree.getInstanceFromNode(rootEl));
	}

	/**
	 * True if the supplied DOM node is a valid node element.
	 *
	 * @param {?DOMElement} node The candidate DOM node.
	 * @return {boolean} True if the DOM is a valid DOM node.
	 * @internal
	 */
	function isValidContainer(node) {
	  return !!(node && (node.nodeType === ELEMENT_NODE_TYPE || node.nodeType === DOC_NODE_TYPE || node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE));
	}

	/**
	 * True if the supplied DOM node is a valid React node element.
	 *
	 * @param {?DOMElement} node The candidate DOM node.
	 * @return {boolean} True if the DOM is a valid React DOM node.
	 * @internal
	 */
	function isReactNode(node) {
	  return isValidContainer(node) && (node.hasAttribute(ROOT_ATTR_NAME) || node.hasAttribute(ATTR_NAME));
	}

	function getHostRootInstanceInContainer(container) {
	  var rootEl = getReactRootElementInContainer(container);
	  var prevHostInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);
	  return prevHostInstance && !prevHostInstance._hostParent ? prevHostInstance : null;
	}

	function getTopLevelWrapperInContainer(container) {
	  var root = getHostRootInstanceInContainer(container);
	  return root ? root._hostContainerInfo._topLevelWrapper : null;
	}

	/**
	 * Temporary (?) hack so that we can store all top-level pending updates on
	 * composites instead of having to worry about different types of components
	 * here.
	 */
	var topLevelRootCounter = 1;
	var TopLevelWrapper = function () {
	  this.rootID = topLevelRootCounter++;
	};
	TopLevelWrapper.prototype.isReactComponent = {};
	if (process.env.NODE_ENV !== 'production') {
	  TopLevelWrapper.displayName = 'TopLevelWrapper';
	}
	TopLevelWrapper.prototype.render = function () {
	  return this.props.child;
	};
	TopLevelWrapper.isReactTopLevelWrapper = true;

	/**
	 * Mounting is the process of initializing a React component by creating its
	 * representative DOM elements and inserting them into a supplied `container`.
	 * Any prior content inside `container` is destroyed in the process.
	 *
	 *   ReactMount.render(
	 *     component,
	 *     document.getElementById('container')
	 *   );
	 *
	 *   <div id="container">                   <-- Supplied `container`.
	 *     <div data-reactid=".3">              <-- Rendered reactRoot of React
	 *       // ...                                 component.
	 *     </div>
	 *   </div>
	 *
	 * Inside of `container`, the first element rendered is the "reactRoot".
	 */
	var ReactMount = {
	  TopLevelWrapper: TopLevelWrapper,

	  /**
	   * Used by devtools. The keys are not important.
	   */
	  _instancesByReactRootID: instancesByReactRootID,

	  /**
	   * This is a hook provided to support rendering React components while
	   * ensuring that the apparent scroll position of its `container` does not
	   * change.
	   *
	   * @param {DOMElement} container The `container` being rendered into.
	   * @param {function} renderCallback This must be called once to do the render.
	   */
	  scrollMonitor: function (container, renderCallback) {
	    renderCallback();
	  },

	  /**
	   * Take a component that's already mounted into the DOM and replace its props
	   * @param {ReactComponent} prevComponent component instance already in the DOM
	   * @param {ReactElement} nextElement component instance to render
	   * @param {DOMElement} container container to render into
	   * @param {?function} callback function triggered on completion
	   */
	  _updateRootComponent: function (prevComponent, nextElement, nextContext, container, callback) {
	    ReactMount.scrollMonitor(container, function () {
	      ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement, nextContext);
	      if (callback) {
	        ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
	      }
	    });

	    return prevComponent;
	  },

	  /**
	   * Render a new component into the DOM. Hooked by hooks!
	   *
	   * @param {ReactElement} nextElement element to render
	   * @param {DOMElement} container container to render into
	   * @param {boolean} shouldReuseMarkup if we should skip the markup insertion
	   * @return {ReactComponent} nextComponent
	   */
	  _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {
	    // Various parts of our code (such as ReactCompositeComponent's
	    // _renderValidatedComponent) assume that calls to render aren't nested;
	    // verify that that's the case.
	    process.env.NODE_ENV !== 'production' ? warning(ReactCurrentOwner.current == null, '_renderNewRootComponent(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from ' + 'render is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;

	    !isValidContainer(container) ? process.env.NODE_ENV !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : _prodInvariant('37') : void 0;

	    ReactBrowserEventEmitter.ensureScrollValueMonitoring();
	    var componentInstance = instantiateReactComponent(nextElement, false);

	    // The initial render is synchronous but any updates that happen during
	    // rendering, in componentWillMount or componentDidMount, will be batched
	    // according to the current batching strategy.

	    ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);

	    var wrapperID = componentInstance._instance.rootID;
	    instancesByReactRootID[wrapperID] = componentInstance;

	    return componentInstance;
	  },

	  /**
	   * Renders a React component into the DOM in the supplied `container`.
	   *
	   * If the React component was previously rendered into `container`, this will
	   * perform an update on it and only mutate the DOM as necessary to reflect the
	   * latest React component.
	   *
	   * @param {ReactComponent} parentComponent The conceptual parent of this render tree.
	   * @param {ReactElement} nextElement Component element to render.
	   * @param {DOMElement} container DOM element to render into.
	   * @param {?function} callback function triggered on completion
	   * @return {ReactComponent} Component instance rendered in `container`.
	   */
	  renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
	    !(parentComponent != null && ReactInstanceMap.has(parentComponent)) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : _prodInvariant('38') : void 0;
	    return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback);
	  },

	  _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
	    ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');
	    !React.isValidElement(nextElement) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? " Instead of passing a string like 'div', pass " + "React.createElement('div') or <div />." : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : // Check if it quacks like an element
	    nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : _prodInvariant('39', typeof nextElement === 'string' ? " Instead of passing a string like 'div', pass " + "React.createElement('div') or <div />." : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : void 0;

	    process.env.NODE_ENV !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0;

	    var nextWrappedElement = React.createElement(TopLevelWrapper, {
	      child: nextElement
	    });

	    var nextContext;
	    if (parentComponent) {
	      var parentInst = ReactInstanceMap.get(parentComponent);
	      nextContext = parentInst._processChildContext(parentInst._context);
	    } else {
	      nextContext = emptyObject;
	    }

	    var prevComponent = getTopLevelWrapperInContainer(container);

	    if (prevComponent) {
	      var prevWrappedElement = prevComponent._currentElement;
	      var prevElement = prevWrappedElement.props.child;
	      if (shouldUpdateReactComponent(prevElement, nextElement)) {
	        var publicInst = prevComponent._renderedComponent.getPublicInstance();
	        var updatedCallback = callback && function () {
	          callback.call(publicInst);
	        };
	        ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);
	        return publicInst;
	      } else {
	        ReactMount.unmountComponentAtNode(container);
	      }
	    }

	    var reactRootElement = getReactRootElementInContainer(container);
	    var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);
	    var containerHasNonRootReactChild = hasNonRootReactChild(container);

	    if (process.env.NODE_ENV !== 'production') {
	      process.env.NODE_ENV !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0;

	      if (!containerHasReactMarkup || reactRootElement.nextSibling) {
	        var rootElementSibling = reactRootElement;
	        while (rootElementSibling) {
	          if (internalGetID(rootElementSibling)) {
	            process.env.NODE_ENV !== 'production' ? warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.') : void 0;
	            break;
	          }
	          rootElementSibling = rootElementSibling.nextSibling;
	        }
	      }
	    }

	    var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;
	    var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();
	    if (callback) {
	      callback.call(component);
	    }
	    return component;
	  },

	  /**
	   * Renders a React component into the DOM in the supplied `container`.
	   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render
	   *
	   * If the React component was previously rendered into `container`, this will
	   * perform an update on it and only mutate the DOM as necessary to reflect the
	   * latest React component.
	   *
	   * @param {ReactElement} nextElement Component element to render.
	   * @param {DOMElement} container DOM element to render into.
	   * @param {?function} callback function triggered on completion
	   * @return {ReactComponent} Component instance rendered in `container`.
	   */
	  render: function (nextElement, container, callback) {
	    return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);
	  },

	  /**
	   * Unmounts and destroys the React component rendered in the `container`.
	   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode
	   *
	   * @param {DOMElement} container DOM element containing a React component.
	   * @return {boolean} True if a component was found in and unmounted from
	   *                   `container`
	   */
	  unmountComponentAtNode: function (container) {
	    // Various parts of our code (such as ReactCompositeComponent's
	    // _renderValidatedComponent) assume that calls to render aren't nested;
	    // verify that that's the case. (Strictly speaking, unmounting won't cause a
	    // render but we still don't expect to be in a render call here.)
	    process.env.NODE_ENV !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;

	    !isValidContainer(container) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : _prodInvariant('40') : void 0;

	    if (process.env.NODE_ENV !== 'production') {
	      process.env.NODE_ENV !== 'production' ? warning(!nodeIsRenderedByOtherInstance(container), "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.') : void 0;
	    }

	    var prevComponent = getTopLevelWrapperInContainer(container);
	    if (!prevComponent) {
	      // Check if the node being unmounted was rendered by React, but isn't a
	      // root node.
	      var containerHasNonRootReactChild = hasNonRootReactChild(container);

	      // Check if the container itself is a React root node.
	      var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME);

	      if (process.env.NODE_ENV !== 'production') {
	        process.env.NODE_ENV !== 'production' ? warning(!containerHasNonRootReactChild, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0;
	      }

	      return false;
	    }
	    delete instancesByReactRootID[prevComponent._instance.rootID];
	    ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false);
	    return true;
	  },

	  _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) {
	    !isValidContainer(container) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : _prodInvariant('41') : void 0;

	    if (shouldReuseMarkup) {
	      var rootElement = getReactRootElementInContainer(container);
	      if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {
	        ReactDOMComponentTree.precacheNode(instance, rootElement);
	        return;
	      } else {
	        var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
	        rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);

	        var rootMarkup = rootElement.outerHTML;
	        rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum);

	        var normalizedMarkup = markup;
	        if (process.env.NODE_ENV !== 'production') {
	          // because rootMarkup is retrieved from the DOM, various normalizations
	          // will have occurred which will not be present in `markup`. Here,
	          // insert markup into a <div> or <iframe> depending on the container
	          // type to perform the same normalizations before comparing.
	          var normalizer;
	          if (container.nodeType === ELEMENT_NODE_TYPE) {
	            normalizer = document.createElement('div');
	            normalizer.innerHTML = markup;
	            normalizedMarkup = normalizer.innerHTML;
	          } else {
	            normalizer = document.createElement('iframe');
	            document.body.appendChild(normalizer);
	            normalizer.contentDocument.write(markup);
	            normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;
	            document.body.removeChild(normalizer);
	          }
	        }

	        var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);
	        var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);

	        !(container.nodeType !== DOC_NODE_TYPE) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'You\'re trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure. React cannot handle this case due to cross-browser quirks by rendering at the document root. You should look for environment dependent code in your components and ensure the props are the same client and server side:\n%s', difference) : _prodInvariant('42', difference) : void 0;

	        if (process.env.NODE_ENV !== 'production') {
	          process.env.NODE_ENV !== 'production' ? warning(false, 'React attempted to reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are ' + 'using server rendering and the markup generated on the ' + 'server was not what the client was expecting. React injected ' + 'new markup to compensate which works but you have lost many ' + 'of the benefits of server rendering. Instead, figure out ' + 'why the markup being generated is different on the client ' + 'or server:\n%s', difference) : void 0;
	        }
	      }
	    }

	    !(container.nodeType !== DOC_NODE_TYPE) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'You\'re trying to render a component to the document but you didn\'t use server rendering. We can\'t do this without using server rendering due to cross-browser quirks. See ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('43') : void 0;

	    if (transaction.useCreateElement) {
	      while (container.lastChild) {
	        container.removeChild(container.lastChild);
	      }
	      DOMLazyTree.insertTreeBefore(container, markup, null);
	    } else {
	      setInnerHTML(container, markup);
	      ReactDOMComponentTree.precacheNode(instance, container.firstChild);
	    }

	    if (process.env.NODE_ENV !== 'production') {
	      var hostNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);
	      if (hostNode._debugID !== 0) {
	        ReactInstrumentation.debugTool.onHostOperation({
	          instanceID: hostNode._debugID,
	          type: 'mount',
	          payload: markup.toString()
	        });
	      }
	    }
	  }
	};

	module.exports = ReactMount;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 200 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var validateDOMNesting = __webpack_require__(169);

	var DOC_NODE_TYPE = 9;

	function ReactDOMContainerInfo(topLevelWrapper, node) {
	  var info = {
	    _topLevelWrapper: topLevelWrapper,
	    _idCounter: 1,
	    _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null,
	    _node: node,
	    _tag: node ? node.nodeName.toLowerCase() : null,
	    _namespaceURI: node ? node.namespaceURI : null
	  };
	  if (process.env.NODE_ENV !== 'production') {
	    info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null;
	  }
	  return info;
	}

	module.exports = ReactDOMContainerInfo;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 201 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactDOMFeatureFlags = {
	  useCreateElement: true,
	  useFiber: false
	};

	module.exports = ReactDOMFeatureFlags;

/***/ },
/* 202 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var adler32 = __webpack_require__(203);

	var TAG_END = /\/?>/;
	var COMMENT_START = /^<\!\-\-/;

	var ReactMarkupChecksum = {
	  CHECKSUM_ATTR_NAME: 'data-react-checksum',

	  /**
	   * @param {string} markup Markup string
	   * @return {string} Markup string with checksum attribute attached
	   */
	  addChecksumToMarkup: function (markup) {
	    var checksum = adler32(markup);

	    // Add checksum (handle both parent tags, comments and self-closing tags)
	    if (COMMENT_START.test(markup)) {
	      return markup;
	    } else {
	      return markup.replace(TAG_END, ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '"$&');
	    }
	  },

	  /**
	   * @param {string} markup to use
	   * @param {DOMElement} element root React element
	   * @returns {boolean} whether or not the markup is the same
	   */
	  canReuseMarkup: function (markup, element) {
	    var existingChecksum = element.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
	    existingChecksum = existingChecksum && parseInt(existingChecksum, 10);
	    var markupChecksum = adler32(markup);
	    return markupChecksum === existingChecksum;
	  }
	};

	module.exports = ReactMarkupChecksum;

/***/ },
/* 203 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 * 
	 */

	'use strict';

	var MOD = 65521;

	// adler32 is not cryptographically strong, and is only used to sanity check that
	// markup generated on the server matches the markup generated on the client.
	// This implementation (a modified version of the SheetJS version) has been optimized
	// for our use case, at the expense of conforming to the adler32 specification
	// for non-ascii inputs.
	function adler32(data) {
	  var a = 1;
	  var b = 0;
	  var i = 0;
	  var l = data.length;
	  var m = l & ~0x3;
	  while (i < m) {
	    var n = Math.min(i + 4096, m);
	    for (; i < n; i += 4) {
	      b += (a += data.charCodeAt(i)) + (a += data.charCodeAt(i + 1)) + (a += data.charCodeAt(i + 2)) + (a += data.charCodeAt(i + 3));
	    }
	    a %= MOD;
	    b %= MOD;
	  }
	  for (; i < l; i++) {
	    b += a += data.charCodeAt(i);
	  }
	  a %= MOD;
	  b %= MOD;
	  return a | b << 16;
	}

	module.exports = adler32;

/***/ },
/* 204 */
/***/ function(module, exports) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	module.exports = '15.6.2';

/***/ },
/* 205 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var _prodInvariant = __webpack_require__(67);

	var ReactCurrentOwner = __webpack_require__(44);
	var ReactDOMComponentTree = __webpack_require__(66);
	var ReactInstanceMap = __webpack_require__(149);

	var getHostComponentFromComposite = __webpack_require__(206);
	var invariant = __webpack_require__(39);
	var warning = __webpack_require__(35);

	/**
	 * Returns the DOM node rendered by this element.
	 *
	 * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode
	 *
	 * @param {ReactComponent|DOMElement} componentOrElement
	 * @return {?DOMElement} The root node of this element.
	 */
	function findDOMNode(componentOrElement) {
	  if (process.env.NODE_ENV !== 'production') {
	    var owner = ReactCurrentOwner.current;
	    if (owner !== null) {
	      process.env.NODE_ENV !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;
	      owner._warnedAboutRefsInRender = true;
	    }
	  }
	  if (componentOrElement == null) {
	    return null;
	  }
	  if (componentOrElement.nodeType === 1) {
	    return componentOrElement;
	  }

	  var inst = ReactInstanceMap.get(componentOrElement);
	  if (inst) {
	    inst = getHostComponentFromComposite(inst);
	    return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null;
	  }

	  if (typeof componentOrElement.render === 'function') {
	     true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'findDOMNode was called on an unmounted component.') : _prodInvariant('44') : void 0;
	  } else {
	     true ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', Object.keys(componentOrElement)) : _prodInvariant('45', Object.keys(componentOrElement)) : void 0;
	  }
	}

	module.exports = findDOMNode;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 206 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactNodeTypes = __webpack_require__(153);

	function getHostComponentFromComposite(inst) {
	  var type;

	  while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {
	    inst = inst._renderedComponent;
	  }

	  if (type === ReactNodeTypes.HOST) {
	    return inst._renderedComponent;
	  } else if (type === ReactNodeTypes.EMPTY) {
	    return null;
	  }
	}

	module.exports = getHostComponentFromComposite;

/***/ },
/* 207 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactMount = __webpack_require__(199);

	module.exports = ReactMount.renderSubtreeIntoContainer;

/***/ },
/* 208 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMProperty = __webpack_require__(68);
	var EventPluginRegistry = __webpack_require__(75);
	var ReactComponentTreeHook = __webpack_require__(51);

	var warning = __webpack_require__(35);

	if (process.env.NODE_ENV !== 'production') {
	  var reactProps = {
	    children: true,
	    dangerouslySetInnerHTML: true,
	    key: true,
	    ref: true,

	    autoFocus: true,
	    defaultValue: true,
	    valueLink: true,
	    defaultChecked: true,
	    checkedLink: true,
	    innerHTML: true,
	    suppressContentEditableWarning: true,
	    onFocusIn: true,
	    onFocusOut: true
	  };
	  var warnedProperties = {};

	  var validateProperty = function (tagName, name, debugID) {
	    if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) {
	      return true;
	    }
	    if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
	      return true;
	    }
	    if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) {
	      return true;
	    }
	    warnedProperties[name] = true;
	    var lowerCasedName = name.toLowerCase();

	    // data-* attributes should be lowercase; suggest the lowercase version
	    var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;

	    var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : null;

	    if (standardName != null) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'Unknown DOM property %s. Did you mean %s?%s', name, standardName, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
	      return true;
	    } else if (registrationName != null) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'Unknown event handler property %s. Did you mean `%s`?%s', name, registrationName, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
	      return true;
	    } else {
	      // We were unable to guess which prop the user intended.
	      // It is likely that the user was just blindly spreading/forwarding props
	      // Components should be careful to only render valid props/attributes.
	      // Warning will be invoked in warnUnknownProperties to allow grouping.
	      return false;
	    }
	  };
	}

	var warnUnknownProperties = function (debugID, element) {
	  var unknownProps = [];
	  for (var key in element.props) {
	    var isValid = validateProperty(element.type, key, debugID);
	    if (!isValid) {
	      unknownProps.push(key);
	    }
	  }

	  var unknownPropString = unknownProps.map(function (prop) {
	    return '`' + prop + '`';
	  }).join(', ');

	  if (unknownProps.length === 1) {
	    process.env.NODE_ENV !== 'production' ? warning(false, 'Unknown prop %s on <%s> tag. Remove this prop from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
	  } else if (unknownProps.length > 1) {
	    process.env.NODE_ENV !== 'production' ? warning(false, 'Unknown props %s on <%s> tag. Remove these props from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
	  }
	};

	function handleElement(debugID, element) {
	  if (element == null || typeof element.type !== 'string') {
	    return;
	  }
	  if (element.type.indexOf('-') >= 0 || element.props.is) {
	    return;
	  }
	  warnUnknownProperties(debugID, element);
	}

	var ReactDOMUnknownPropertyHook = {
	  onBeforeMountComponent: function (debugID, element) {
	    handleElement(debugID, element);
	  },
	  onBeforeUpdateComponent: function (debugID, element) {
	    handleElement(debugID, element);
	  }
	};

	module.exports = ReactDOMUnknownPropertyHook;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 209 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var ReactComponentTreeHook = __webpack_require__(51);

	var warning = __webpack_require__(35);

	var didWarnValueNull = false;

	function handleElement(debugID, element) {
	  if (element == null) {
	    return;
	  }
	  if (element.type !== 'input' && element.type !== 'textarea' && element.type !== 'select') {
	    return;
	  }
	  if (element.props != null && element.props.value === null && !didWarnValueNull) {
	    process.env.NODE_ENV !== 'production' ? warning(false, '`value` prop on `%s` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', element.type, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;

	    didWarnValueNull = true;
	  }
	}

	var ReactDOMNullInputValuePropHook = {
	  onBeforeMountComponent: function (debugID, element) {
	    handleElement(debugID, element);
	  },
	  onBeforeUpdateComponent: function (debugID, element) {
	    handleElement(debugID, element);
	  }
	};

	module.exports = ReactDOMNullInputValuePropHook;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 210 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(process) {/**
	 * Copyright (c) 2013-present, Facebook, Inc.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */

	'use strict';

	var DOMProperty = __webpack_require__(68);
	var ReactComponentTreeHook = __webpack_require__(51);

	var warning = __webpack_require__(35);

	var warnedProperties = {};
	var rARIA = new RegExp('^(aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');

	function validateProperty(tagName, name, debugID) {
	  if (warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
	    return true;
	  }

	  if (rARIA.test(name)) {
	    var lowerCasedName = name.toLowerCase();
	    var standardName = DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;

	    // If this is an aria-* attribute, but is not listed in the known DOM
	    // DOM properties, then it is an invalid aria-* attribute.
	    if (standardName == null) {
	      warnedProperties[name] = true;
	      return false;
	    }
	    // aria-* attributes should be lowercase; suggest the lowercase version.
	    if (name !== standardName) {
	      process.env.NODE_ENV !== 'production' ? warning(false, 'Unknown ARIA attribute %s. Did you mean %s?%s', name, standardName, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
	      warnedProperties[name] = true;
	      return true;
	    }
	  }

	  return true;
	}

	function warnInvalidARIAProps(debugID, element) {
	  var invalidProps = [];

	  for (var key in element.props) {
	    var isValid = validateProperty(element.type, key, debugID);
	    if (!isValid) {
	      invalidProps.push(key);
	    }
	  }

	  var unknownPropString = invalidProps.map(function (prop) {
	    return '`' + prop + '`';
	  }).join(', ');

	  if (invalidProps.length === 1) {
	    process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid aria prop %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, element.type, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
	  } else if (invalidProps.length > 1) {
	    process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid aria props %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, element.type, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
	  }
	}

	function handleElement(debugID, element) {
	  if (element == null || typeof element.type !== 'string') {
	    return;
	  }
	  if (element.type.indexOf('-') >= 0 || element.props.is) {
	    return;
	  }

	  warnInvalidARIAProps(debugID, element);
	}

	var ReactDOMInvalidARIAHook = {
	  onBeforeMountComponent: function (debugID, element) {
	    if (process.env.NODE_ENV !== 'production') {
	      handleElement(debugID, element);
	    }
	  },
	  onBeforeUpdateComponent: function (debugID, element) {
	    if (process.env.NODE_ENV !== 'production') {
	      handleElement(debugID, element);
	    }
	  }
	};

	module.exports = ReactDOMInvalidARIAHook;
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(30)))

/***/ },
/* 211 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(setImmediate) {/*!
	 * typeahead.js 1.0.1
	 * https://github.com/twitter/typeahead.js
	 * Copyright 2013-2016 Twitter, Inc. and other contributors; Licensed MIT
	 */

	(function(root, factory) {
	    if (true) {
	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(5) ], __WEBPACK_AMD_DEFINE_RESULT__ = function(a0) {
	            return root["Bloodhound"] = factory(a0);
	        }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	    } else if (typeof module === "object" && module.exports) {
	        module.exports = factory(require("jquery"));
	    } else {
	        root["Bloodhound"] = factory(root["jQuery"]);
	    }
	})(this, function($) {
	    var _ = function() {
	        "use strict";
	        return {
	            isMsie: function() {
	                return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
	            },
	            isBlankString: function(str) {
	                return !str || /^\s*$/.test(str);
	            },
	            escapeRegExChars: function(str) {
	                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
	            },
	            isString: function(obj) {
	                return typeof obj === "string";
	            },
	            isNumber: function(obj) {
	                return typeof obj === "number";
	            },
	            isArray: $.isArray,
	            isFunction: $.isFunction,
	            isObject: $.isPlainObject,
	            isUndefined: function(obj) {
	                return typeof obj === "undefined";
	            },
	            isElement: function(obj) {
	                return !!(obj && obj.nodeType === 1);
	            },
	            isJQuery: function(obj) {
	                return obj instanceof $;
	            },
	            toStr: function toStr(s) {
	                return _.isUndefined(s) || s === null ? "" : s + "";
	            },
	            bind: $.proxy,
	            each: function(collection, cb) {
	                $.each(collection, reverseArgs);
	                function reverseArgs(index, value) {
	                    return cb(value, index);
	                }
	            },
	            map: $.map,
	            filter: $.grep,
	            every: function(obj, test) {
	                var result = true;
	                if (!obj) {
	                    return result;
	                }
	                $.each(obj, function(key, val) {
	                    if (!(result = test.call(null, val, key, obj))) {
	                        return false;
	                    }
	                });
	                return !!result;
	            },
	            some: function(obj, test) {
	                var result = false;
	                if (!obj) {
	                    return result;
	                }
	                $.each(obj, function(key, val) {
	                    if (result = test.call(null, val, key, obj)) {
	                        return false;
	                    }
	                });
	                return !!result;
	            },
	            mixin: $.extend,
	            identity: function(x) {
	                return x;
	            },
	            clone: function(obj) {
	                return $.extend(true, {}, obj);
	            },
	            getIdGenerator: function() {
	                var counter = 0;
	                return function() {
	                    return counter++;
	                };
	            },
	            templatify: function templatify(obj) {
	                return $.isFunction(obj) ? obj : template;
	                function template() {
	                    return String(obj);
	                }
	            },
	            defer: function(fn) {
	                setTimeout(fn, 0);
	            },
	            debounce: function(func, wait, immediate) {
	                var timeout, result;
	                return function() {
	                    var context = this, args = arguments, later, callNow;
	                    later = function() {
	                        timeout = null;
	                        if (!immediate) {
	                            result = func.apply(context, args);
	                        }
	                    };
	                    callNow = immediate && !timeout;
	                    clearTimeout(timeout);
	                    timeout = setTimeout(later, wait);
	                    if (callNow) {
	                        result = func.apply(context, args);
	                    }
	                    return result;
	                };
	            },
	            throttle: function(func, wait) {
	                var context, args, timeout, result, previous, later;
	                previous = 0;
	                later = function() {
	                    previous = new Date();
	                    timeout = null;
	                    result = func.apply(context, args);
	                };
	                return function() {
	                    var now = new Date(), remaining = wait - (now - previous);
	                    context = this;
	                    args = arguments;
	                    if (remaining <= 0) {
	                        clearTimeout(timeout);
	                        timeout = null;
	                        previous = now;
	                        result = func.apply(context, args);
	                    } else if (!timeout) {
	                        timeout = setTimeout(later, remaining);
	                    }
	                    return result;
	                };
	            },
	            stringify: function(val) {
	                return _.isString(val) ? val : JSON.stringify(val);
	            },
	            guid: function() {
	                function _p8(s) {
	                    var p = (Math.random().toString(16) + "000000000").substr(2, 8);
	                    return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
	                }
	                return "tt-" + _p8() + _p8(true) + _p8(true) + _p8();
	            },
	            noop: function() {}
	        };
	    }();
	    var VERSION = "1.0.1";
	    var tokenizers = function() {
	        "use strict";
	        return {
	            nonword: nonword,
	            whitespace: whitespace,
	            ngram: ngram,
	            obj: {
	                nonword: getObjTokenizer(nonword),
	                whitespace: getObjTokenizer(whitespace),
	                ngram: getObjTokenizer(ngram)
	            }
	        };
	        function whitespace(str) {
	            str = _.toStr(str);
	            return str ? str.split(/\s+/) : [];
	        }
	        function nonword(str) {
	            str = _.toStr(str);
	            return str ? str.split(/\W+/) : [];
	        }
	        function ngram(str) {
	            str = _.toStr(str);
	            var tokens = [], word = "";
	            _.each(str.split(""), function(char) {
	                if (char.match(/\s+/)) {
	                    word = "";
	                } else {
	                    tokens.push(word + char);
	                    word += char;
	                }
	            });
	            return tokens;
	        }
	        function getObjTokenizer(tokenizer) {
	            return function setKey(keys) {
	                keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
	                return function tokenize(o) {
	                    var tokens = [];
	                    _.each(keys, function(k) {
	                        tokens = tokens.concat(tokenizer(_.toStr(o[k])));
	                    });
	                    return tokens;
	                };
	            };
	        }
	    }();
	    var LruCache = function() {
	        "use strict";
	        function LruCache(maxSize) {
	            this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
	            this.reset();
	            if (this.maxSize <= 0) {
	                this.set = this.get = $.noop;
	            }
	        }
	        _.mixin(LruCache.prototype, {
	            set: function set(key, val) {
	                var tailItem = this.list.tail, node;
	                if (this.size >= this.maxSize) {
	                    this.list.remove(tailItem);
	                    delete this.hash[tailItem.key];
	                    this.size--;
	                }
	                if (node = this.hash[key]) {
	                    node.val = val;
	                    this.list.moveToFront(node);
	                } else {
	                    node = new Node(key, val);
	                    this.list.add(node);
	                    this.hash[key] = node;
	                    this.size++;
	                }
	            },
	            get: function get(key) {
	                var node = this.hash[key];
	                if (node) {
	                    this.list.moveToFront(node);
	                    return node.val;
	                }
	            },
	            reset: function reset() {
	                this.size = 0;
	                this.hash = {};
	                this.list = new List();
	            }
	        });
	        function List() {
	            this.head = this.tail = null;
	        }
	        _.mixin(List.prototype, {
	            add: function add(node) {
	                if (this.head) {
	                    node.next = this.head;
	                    this.head.prev = node;
	                }
	                this.head = node;
	                this.tail = this.tail || node;
	            },
	            remove: function remove(node) {
	                node.prev ? node.prev.next = node.next : this.head = node.next;
	                node.next ? node.next.prev = node.prev : this.tail = node.prev;
	            },
	            moveToFront: function(node) {
	                this.remove(node);
	                this.add(node);
	            }
	        });
	        function Node(key, val) {
	            this.key = key;
	            this.val = val;
	            this.prev = this.next = null;
	        }
	        return LruCache;
	    }();
	    var PersistentStorage = function() {
	        "use strict";
	        var LOCAL_STORAGE;
	        try {
	            LOCAL_STORAGE = window.localStorage;
	            LOCAL_STORAGE.setItem("~~~", "!");
	            LOCAL_STORAGE.removeItem("~~~");
	        } catch (err) {
	            LOCAL_STORAGE = null;
	        }
	        function PersistentStorage(namespace, override) {
	            this.prefix = [ "__", namespace, "__" ].join("");
	            this.ttlKey = "__ttl__";
	            this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
	            this.ls = override || LOCAL_STORAGE;
	            !this.ls && this._noop();
	        }
	        _.mixin(PersistentStorage.prototype, {
	            _prefix: function(key) {
	                return this.prefix + key;
	            },
	            _ttlKey: function(key) {
	                return this._prefix(key) + this.ttlKey;
	            },
	            _noop: function() {
	                this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
	            },
	            _safeSet: function(key, val) {
	                try {
	                    this.ls.setItem(key, val);
	                } catch (err) {
	                    if (err.name === "QuotaExceededError") {
	                        this.clear();
	                        this._noop();
	                    }
	                }
	            },
	            get: function(key) {
	                if (this.isExpired(key)) {
	                    this.remove(key);
	                }
	                return decode(this.ls.getItem(this._prefix(key)));
	            },
	            set: function(key, val, ttl) {
	                if (_.isNumber(ttl)) {
	                    this._safeSet(this._ttlKey(key), encode(now() + ttl));
	                } else {
	                    this.ls.removeItem(this._ttlKey(key));
	                }
	                return this._safeSet(this._prefix(key), encode(val));
	            },
	            remove: function(key) {
	                this.ls.removeItem(this._ttlKey(key));
	                this.ls.removeItem(this._prefix(key));
	                return this;
	            },
	            clear: function() {
	                var i, keys = gatherMatchingKeys(this.keyMatcher);
	                for (i = keys.length; i--; ) {
	                    this.remove(keys[i]);
	                }
	                return this;
	            },
	            isExpired: function(key) {
	                var ttl = decode(this.ls.getItem(this._ttlKey(key)));
	                return _.isNumber(ttl) && now() > ttl ? true : false;
	            }
	        });
	        return PersistentStorage;
	        function now() {
	            return new Date().getTime();
	        }
	        function encode(val) {
	            return JSON.stringify(_.isUndefined(val) ? null : val);
	        }
	        function decode(val) {
	            return $.parseJSON(val);
	        }
	        function gatherMatchingKeys(keyMatcher) {
	            var i, key, keys = [], len = LOCAL_STORAGE.length;
	            for (i = 0; i < len; i++) {
	                if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
	                    keys.push(key.replace(keyMatcher, ""));
	                }
	            }
	            return keys;
	        }
	    }();
	    var Transport = function() {
	        "use strict";
	        var pendingRequestsCount = 0, pendingRequests = {}, sharedCache = new LruCache(10);
	        function Transport(o) {
	            o = o || {};
	            this.maxPendingRequests = o.maxPendingRequests || 6;
	            this.cancelled = false;
	            this.lastReq = null;
	            this._send = o.transport;
	            this._get = o.limiter ? o.limiter(this._get) : this._get;
	            this._cache = o.cache === false ? new LruCache(0) : sharedCache;
	        }
	        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
	            this.maxPendingRequests = num;
	        };
	        Transport.resetCache = function resetCache() {
	            sharedCache.reset();
	        };
	        _.mixin(Transport.prototype, {
	            _fingerprint: function fingerprint(o) {
	                o = o || {};
	                return o.url + o.type + $.param(o.data || {});
	            },
	            _get: function(o, cb) {
	                var that = this, fingerprint, jqXhr;
	                fingerprint = this._fingerprint(o);
	                if (this.cancelled || fingerprint !== this.lastReq) {
	                    return;
	                }
	                if (jqXhr = pendingRequests[fingerprint]) {
	                    jqXhr.done(done).fail(fail);
	                } else if (pendingRequestsCount < this.maxPendingRequests) {
	                    pendingRequestsCount++;
	                    pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
	                } else {
	                    this.onDeckRequestArgs = [].slice.call(arguments, 0);
	                }
	                function done(resp) {
	                    cb(null, resp);
	                    that._cache.set(fingerprint, resp);
	                }
	                function fail() {
	                    cb(true);
	                }
	                function always() {
	                    pendingRequestsCount--;
	                    delete pendingRequests[fingerprint];
	                    if (that.onDeckRequestArgs) {
	                        that._get.apply(that, that.onDeckRequestArgs);
	                        that.onDeckRequestArgs = null;
	                    }
	                }
	            },
	            get: function(o, cb) {
	                var resp, fingerprint;
	                cb = cb || $.noop;
	                o = _.isString(o) ? {
	                    url: o
	                } : o || {};
	                fingerprint = this._fingerprint(o);
	                this.cancelled = false;
	                this.lastReq = fingerprint;
	                if (resp = this._cache.get(fingerprint)) {
	                    cb(null, resp);
	                } else {
	                    this._get(o, cb);
	                }
	            },
	            cancel: function() {
	                this.cancelled = true;
	            }
	        });
	        return Transport;
	    }();
	    var SearchIndex = window.SearchIndex = function() {
	        "use strict";
	        var CHILDREN = "c", IDS = "i";
	        function SearchIndex(o) {
	            o = o || {};
	            if (!o.datumTokenizer || !o.queryTokenizer) {
	                $.error("datumTokenizer and queryTokenizer are both required");
	            }
	            this.identify = o.identify || _.stringify;
	            this.datumTokenizer = o.datumTokenizer;
	            this.queryTokenizer = o.queryTokenizer;
	            this.matchAnyQueryToken = o.matchAnyQueryToken;
	            this.reset();
	        }
	        _.mixin(SearchIndex.prototype, {
	            bootstrap: function bootstrap(o) {
	                this.datums = o.datums;
	                this.trie = o.trie;
	            },
	            add: function(data) {
	                var that = this;
	                data = _.isArray(data) ? data : [ data ];
	                _.each(data, function(datum) {
	                    var id, tokens;
	                    that.datums[id = that.identify(datum)] = datum;
	                    tokens = normalizeTokens(that.datumTokenizer(datum));
	                    _.each(tokens, function(token) {
	                        var node, chars, ch;
	                        node = that.trie;
	                        chars = token.split("");
	                        while (ch = chars.shift()) {
	                            node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
	                            node[IDS].push(id);
	                        }
	                    });
	                });
	            },
	            get: function get(ids) {
	                var that = this;
	                return _.map(ids, function(id) {
	                    return that.datums[id];
	                });
	            },
	            search: function search(query) {
	                var that = this, tokens, matches;
	                tokens = normalizeTokens(this.queryTokenizer(query));
	                _.each(tokens, function(token) {
	                    var node, chars, ch, ids;
	                    if (matches && matches.length === 0 && !that.matchAnyQueryToken) {
	                        return false;
	                    }
	                    node = that.trie;
	                    chars = token.split("");
	                    while (node && (ch = chars.shift())) {
	                        node = node[CHILDREN][ch];
	                    }
	                    if (node && chars.length === 0) {
	                        ids = node[IDS].slice(0);
	                        matches = matches ? getIntersection(matches, ids) : ids;
	                    } else {
	                        if (!that.matchAnyQueryToken) {
	                            matches = [];
	                            return false;
	                        }
	                    }
	                });
	                return matches ? _.map(unique(matches), function(id) {
	                    return that.datums[id];
	                }) : [];
	            },
	            all: function all() {
	                var values = [];
	                for (var key in this.datums) {
	                    values.push(this.datums[key]);
	                }
	                return values;
	            },
	            reset: function reset() {
	                this.datums = {};
	                this.trie = newNode();
	            },
	            serialize: function serialize() {
	                return {
	                    datums: this.datums,
	                    trie: this.trie
	                };
	            }
	        });
	        return SearchIndex;
	        function normalizeTokens(tokens) {
	            tokens = _.filter(tokens, function(token) {
	                return !!token;
	            });
	            tokens = _.map(tokens, function(token) {
	                return token.toLowerCase();
	            });
	            return tokens;
	        }
	        function newNode() {
	            var node = {};
	            node[IDS] = [];
	            node[CHILDREN] = {};
	            return node;
	        }
	        function unique(array) {
	            var seen = {}, uniques = [];
	            for (var i = 0, len = array.length; i < len; i++) {
	                if (!seen[array[i]]) {
	                    seen[array[i]] = true;
	                    uniques.push(array[i]);
	                }
	            }
	            return uniques;
	        }
	        function getIntersection(arrayA, arrayB) {
	            var ai = 0, bi = 0, intersection = [];
	            arrayA = arrayA.sort();
	            arrayB = arrayB.sort();
	            var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
	            while (ai < lenArrayA && bi < lenArrayB) {
	                if (arrayA[ai] < arrayB[bi]) {
	                    ai++;
	                } else if (arrayA[ai] > arrayB[bi]) {
	                    bi++;
	                } else {
	                    intersection.push(arrayA[ai]);
	                    ai++;
	                    bi++;
	                }
	            }
	            return intersection;
	        }
	    }();
	    var Prefetch = function() {
	        "use strict";
	        var keys;
	        keys = {
	            data: "data",
	            protocol: "protocol",
	            thumbprint: "thumbprint"
	        };
	        function Prefetch(o) {
	            this.url = o.url;
	            this.ttl = o.ttl;
	            this.cache = o.cache;
	            this.prepare = o.prepare;
	            this.transform = o.transform;
	            this.transport = o.transport;
	            this.thumbprint = o.thumbprint;
	            this.storage = new PersistentStorage(o.cacheKey);
	        }
	        _.mixin(Prefetch.prototype, {
	            _settings: function settings() {
	                return {
	                    url: this.url,
	                    type: "GET",
	                    dataType: "json"
	                };
	            },
	            store: function store(data) {
	                if (!this.cache) {
	                    return;
	                }
	                this.storage.set(keys.data, data, this.ttl);
	                this.storage.set(keys.protocol, location.protocol, this.ttl);
	                this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
	            },
	            fromCache: function fromCache() {
	                var stored = {}, isExpired;
	                if (!this.cache) {
	                    return null;
	                }
	                stored.data = this.storage.get(keys.data);
	                stored.protocol = this.storage.get(keys.protocol);
	                stored.thumbprint = this.storage.get(keys.thumbprint);
	                isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
	                return stored.data && !isExpired ? stored.data : null;
	            },
	            fromNetwork: function(cb) {
	                var that = this, settings;
	                if (!cb) {
	                    return;
	                }
	                settings = this.prepare(this._settings());
	                this.transport(settings).fail(onError).done(onResponse);
	                function onError() {
	                    cb(true);
	                }
	                function onResponse(resp) {
	                    cb(null, that.transform(resp));
	                }
	            },
	            clear: function clear() {
	                this.storage.clear();
	                return this;
	            }
	        });
	        return Prefetch;
	    }();
	    var Remote = function() {
	        "use strict";
	        function Remote(o) {
	            this.url = o.url;
	            this.prepare = o.prepare;
	            this.transform = o.transform;
	            this.indexResponse = o.indexResponse;
	            this.transport = new Transport({
	                cache: o.cache,
	                limiter: o.limiter,
	                transport: o.transport,
	                maxPendingRequests: o.maxPendingRequests
	            });
	        }
	        _.mixin(Remote.prototype, {
	            _settings: function settings() {
	                return {
	                    url: this.url,
	                    type: "GET",
	                    dataType: "json"
	                };
	            },
	            get: function get(query, cb) {
	                var that = this, settings;
	                if (!cb) {
	                    return;
	                }
	                query = query || "";
	                settings = this.prepare(query, this._settings());
	                return this.transport.get(settings, onResponse);
	                function onResponse(err, resp) {
	                    err ? cb([]) : cb(that.transform(resp));
	                }
	            },
	            cancelLastRequest: function cancelLastRequest() {
	                this.transport.cancel();
	            }
	        });
	        return Remote;
	    }();
	    var oParser = function() {
	        "use strict";
	        return function parse(o) {
	            var defaults, sorter;
	            defaults = {
	                initialize: true,
	                identify: _.stringify,
	                datumTokenizer: null,
	                queryTokenizer: null,
	                matchAnyQueryToken: false,
	                sufficient: 5,
	                indexRemote: false,
	                sorter: null,
	                local: [],
	                prefetch: null,
	                remote: null
	            };
	            o = _.mixin(defaults, o || {});
	            !o.datumTokenizer && $.error("datumTokenizer is required");
	            !o.queryTokenizer && $.error("queryTokenizer is required");
	            sorter = o.sorter;
	            o.sorter = sorter ? function(x) {
	                return x.sort(sorter);
	            } : _.identity;
	            o.local = _.isFunction(o.local) ? o.local() : o.local;
	            o.prefetch = parsePrefetch(o.prefetch);
	            o.remote = parseRemote(o.remote);
	            return o;
	        };
	        function parsePrefetch(o) {
	            var defaults;
	            if (!o) {
	                return null;
	            }
	            defaults = {
	                url: null,
	                ttl: 24 * 60 * 60 * 1e3,
	                cache: true,
	                cacheKey: null,
	                thumbprint: "",
	                prepare: _.identity,
	                transform: _.identity,
	                transport: null
	            };
	            o = _.isString(o) ? {
	                url: o
	            } : o;
	            o = _.mixin(defaults, o);
	            !o.url && $.error("prefetch requires url to be set");
	            o.transform = o.filter || o.transform;
	            o.cacheKey = o.cacheKey || o.url;
	            o.thumbprint = VERSION + o.thumbprint;
	            o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
	            return o;
	        }
	        function parseRemote(o) {
	            var defaults;
	            if (!o) {
	                return;
	            }
	            defaults = {
	                url: null,
	                cache: true,
	                prepare: null,
	                replace: null,
	                wildcard: null,
	                limiter: null,
	                rateLimitBy: "debounce",
	                rateLimitWait: 300,
	                transform: _.identity,
	                transport: null
	            };
	            o = _.isString(o) ? {
	                url: o
	            } : o;
	            o = _.mixin(defaults, o);
	            !o.url && $.error("remote requires url to be set");
	            o.transform = o.filter || o.transform;
	            o.prepare = toRemotePrepare(o);
	            o.limiter = toLimiter(o);
	            o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
	            delete o.replace;
	            delete o.wildcard;
	            delete o.rateLimitBy;
	            delete o.rateLimitWait;
	            return o;
	        }
	        function toRemotePrepare(o) {
	            var prepare, replace, wildcard;
	            prepare = o.prepare;
	            replace = o.replace;
	            wildcard = o.wildcard;
	            if (prepare) {
	                return prepare;
	            }
	            if (replace) {
	                prepare = prepareByReplace;
	            } else if (o.wildcard) {
	                prepare = prepareByWildcard;
	            } else {
	                prepare = idenityPrepare;
	            }
	            return prepare;
	            function prepareByReplace(query, settings) {
	                settings.url = replace(settings.url, query);
	                return settings;
	            }
	            function prepareByWildcard(query, settings) {
	                settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
	                return settings;
	            }
	            function idenityPrepare(query, settings) {
	                return settings;
	            }
	        }
	        function toLimiter(o) {
	            var limiter, method, wait;
	            limiter = o.limiter;
	            method = o.rateLimitBy;
	            wait = o.rateLimitWait;
	            if (!limiter) {
	                limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
	            }
	            return limiter;
	            function debounce(wait) {
	                return function debounce(fn) {
	                    return _.debounce(fn, wait);
	                };
	            }
	            function throttle(wait) {
	                return function throttle(fn) {
	                    return _.throttle(fn, wait);
	                };
	            }
	        }
	        function callbackToDeferred(fn) {
	            return function wrapper(o) {
	                var deferred = $.Deferred();
	                fn(o, onSuccess, onError);
	                return deferred;
	                function onSuccess(resp) {
	                    _.defer(function() {
	                        deferred.resolve(resp);
	                    });
	                }
	                function onError(err) {
	                    _.defer(function() {
	                        deferred.reject(err);
	                    });
	                }
	            };
	        }
	    }();
	    var Bloodhound = function() {
	        "use strict";
	        var old;
	        old = window && window.Bloodhound;
	        function Bloodhound(o) {
	            o = oParser(o);
	            this.sorter = o.sorter;
	            this.identify = o.identify;
	            this.sufficient = o.sufficient;
	            this.indexRemote = o.indexRemote;
	            this.local = o.local;
	            this.remote = o.remote ? new Remote(o.remote) : null;
	            this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
	            this.index = new SearchIndex({
	                identify: this.identify,
	                datumTokenizer: o.datumTokenizer,
	                queryTokenizer: o.queryTokenizer
	            });
	            o.initialize !== false && this.initialize();
	        }
	        Bloodhound.noConflict = function noConflict() {
	            window && (window.Bloodhound = old);
	            return Bloodhound;
	        };
	        Bloodhound.tokenizers = tokenizers;
	        _.mixin(Bloodhound.prototype, {
	            __ttAdapter: function ttAdapter() {
	                var that = this;
	                return this.remote ? withAsync : withoutAsync;
	                function withAsync(query, sync, async) {
	                    return that.search(query, sync, async);
	                }
	                function withoutAsync(query, sync) {
	                    return that.search(query, sync);
	                }
	            },
	            _loadPrefetch: function loadPrefetch() {
	                var that = this, deferred, serialized;
	                deferred = $.Deferred();
	                if (!this.prefetch) {
	                    deferred.resolve();
	                } else if (serialized = this.prefetch.fromCache()) {
	                    this.index.bootstrap(serialized);
	                    deferred.resolve();
	                } else {
	                    this.prefetch.fromNetwork(done);
	                }
	                return deferred.promise();
	                function done(err, data) {
	                    if (err) {
	                        return deferred.reject();
	                    }
	                    that.add(data);
	                    that.prefetch.store(that.index.serialize());
	                    deferred.resolve();
	                }
	            },
	            _initialize: function initialize() {
	                var that = this, deferred;
	                this.clear();
	                (this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
	                return this.initPromise;
	                function addLocalToIndex() {
	                    that.add(that.local);
	                }
	            },
	            initialize: function initialize(force) {
	                return !this.initPromise || force ? this._initialize() : this.initPromise;
	            },
	            add: function add(data) {
	                this.index.add(data);
	                return this;
	            },
	            get: function get(ids) {
	                ids = _.isArray(ids) ? ids : [].slice.call(arguments);
	                return this.index.get(ids);
	            },
	            search: function search(query, sync, async) {
	                var that = this, local;
	                sync = sync || _.noop;
	                async = async || _.noop;
	                local = this.sorter(this.index.search(query));
	                sync(this.remote ? local.slice() : local);
	                if (this.remote && local.length < this.sufficient) {
	                    this.remote.get(query, processRemote);
	                } else if (this.remote) {
	                    this.remote.cancelLastRequest();
	                }
	                return this;
	                function processRemote(remote) {
	                    var nonDuplicates = [];
	                    _.each(remote, function(r) {
	                        !_.some(local, function(l) {
	                            return that.identify(r) === that.identify(l);
	                        }) && nonDuplicates.push(r);
	                    });
	                    that.indexRemote && that.add(nonDuplicates);
	                    async(nonDuplicates);
	                }
	            },
	            all: function all() {
	                return this.index.all();
	            },
	            clear: function clear() {
	                this.index.reset();
	                return this;
	            },
	            clearPrefetchCache: function clearPrefetchCache() {
	                this.prefetch && this.prefetch.clear();
	                return this;
	            },
	            clearRemoteCache: function clearRemoteCache() {
	                Transport.resetCache();
	                return this;
	            },
	            ttAdapter: function ttAdapter() {
	                return this.__ttAdapter();
	            }
	        });
	        return Bloodhound;
	    }();
	    return Bloodhound;
	});

	(function(root, factory) {
	    if (true) {
	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(5) ], __WEBPACK_AMD_DEFINE_RESULT__ = function(a0) {
	            return factory(a0);
	        }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	    } else if (typeof module === "object" && module.exports) {
	        module.exports = factory(require("jquery"));
	    } else {
	        factory(root["jQuery"]);
	    }
	})(this, function($) {
	    var _ = function() {
	        "use strict";
	        return {
	            isMsie: function() {
	                return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
	            },
	            isBlankString: function(str) {
	                return !str || /^\s*$/.test(str);
	            },
	            escapeRegExChars: function(str) {
	                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
	            },
	            isString: function(obj) {
	                return typeof obj === "string";
	            },
	            isNumber: function(obj) {
	                return typeof obj === "number";
	            },
	            isArray: $.isArray,
	            isFunction: $.isFunction,
	            isObject: $.isPlainObject,
	            isUndefined: function(obj) {
	                return typeof obj === "undefined";
	            },
	            isElement: function(obj) {
	                return !!(obj && obj.nodeType === 1);
	            },
	            isJQuery: function(obj) {
	                return obj instanceof $;
	            },
	            toStr: function toStr(s) {
	                return _.isUndefined(s) || s === null ? "" : s + "";
	            },
	            bind: $.proxy,
	            each: function(collection, cb) {
	                $.each(collection, reverseArgs);
	                function reverseArgs(index, value) {
	                    return cb(value, index);
	                }
	            },
	            map: $.map,
	            filter: $.grep,
	            every: function(obj, test) {
	                var result = true;
	                if (!obj) {
	                    return result;
	                }
	                $.each(obj, function(key, val) {
	                    if (!(result = test.call(null, val, key, obj))) {
	                        return false;
	                    }
	                });
	                return !!result;
	            },
	            some: function(obj, test) {
	                var result = false;
	                if (!obj) {
	                    return result;
	                }
	                $.each(obj, function(key, val) {
	                    if (result = test.call(null, val, key, obj)) {
	                        return false;
	                    }
	                });
	                return !!result;
	            },
	            mixin: $.extend,
	            identity: function(x) {
	                return x;
	            },
	            clone: function(obj) {
	                return $.extend(true, {}, obj);
	            },
	            getIdGenerator: function() {
	                var counter = 0;
	                return function() {
	                    return counter++;
	                };
	            },
	            templatify: function templatify(obj) {
	                return $.isFunction(obj) ? obj : template;
	                function template() {
	                    return String(obj);
	                }
	            },
	            defer: function(fn) {
	                setTimeout(fn, 0);
	            },
	            debounce: function(func, wait, immediate) {
	                var timeout, result;
	                return function() {
	                    var context = this, args = arguments, later, callNow;
	                    later = function() {
	                        timeout = null;
	                        if (!immediate) {
	                            result = func.apply(context, args);
	                        }
	                    };
	                    callNow = immediate && !timeout;
	                    clearTimeout(timeout);
	                    timeout = setTimeout(later, wait);
	                    if (callNow) {
	                        result = func.apply(context, args);
	                    }
	                    return result;
	                };
	            },
	            throttle: function(func, wait) {
	                var context, args, timeout, result, previous, later;
	                previous = 0;
	                later = function() {
	                    previous = new Date();
	                    timeout = null;
	                    result = func.apply(context, args);
	                };
	                return function() {
	                    var now = new Date(), remaining = wait - (now - previous);
	                    context = this;
	                    args = arguments;
	                    if (remaining <= 0) {
	                        clearTimeout(timeout);
	                        timeout = null;
	                        previous = now;
	                        result = func.apply(context, args);
	                    } else if (!timeout) {
	                        timeout = setTimeout(later, remaining);
	                    }
	                    return result;
	                };
	            },
	            stringify: function(val) {
	                return _.isString(val) ? val : JSON.stringify(val);
	            },
	            guid: function() {
	                function _p8(s) {
	                    var p = (Math.random().toString(16) + "000000000").substr(2, 8);
	                    return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
	                }
	                return "tt-" + _p8() + _p8(true) + _p8(true) + _p8();
	            },
	            noop: function() {}
	        };
	    }();
	    var WWW = function() {
	        "use strict";
	        var defaultClassNames = {
	            wrapper: "twitter-typeahead",
	            input: "tt-input",
	            hint: "tt-hint",
	            menu: "tt-menu",
	            dataset: "tt-dataset",
	            suggestion: "tt-suggestion",
	            selectable: "tt-selectable",
	            empty: "tt-empty",
	            open: "tt-open",
	            cursor: "tt-cursor",
	            highlight: "tt-highlight"
	        };
	        return build;
	        function build(o) {
	            var www, classes;
	            classes = _.mixin({}, defaultClassNames, o);
	            www = {
	                css: buildCss(),
	                classes: classes,
	                html: buildHtml(classes),
	                selectors: buildSelectors(classes)
	            };
	            return {
	                css: www.css,
	                html: www.html,
	                classes: www.classes,
	                selectors: www.selectors,
	                mixin: function(o) {
	                    _.mixin(o, www);
	                }
	            };
	        }
	        function buildHtml(c) {
	            return {
	                wrapper: '<span class="' + c.wrapper + '"></span>',
	                menu: '<div role="listbox" class="' + c.menu + '"></div>'
	            };
	        }
	        function buildSelectors(classes) {
	            var selectors = {};
	            _.each(classes, function(v, k) {
	                selectors[k] = "." + v;
	            });
	            return selectors;
	        }
	        function buildCss() {
	            var css = {
	                wrapper: {
	                    position: "relative",
	                    display: "inline-block"
	                },
	                hint: {
	                    position: "absolute",
	                    top: "0",
	                    left: "0",
	                    borderColor: "transparent",
	                    boxShadow: "none",
	                    opacity: "1"
	                },
	                input: {
	                    position: "relative",
	                    verticalAlign: "top",
	                    backgroundColor: "transparent"
	                },
	                inputWithNoHint: {
	                    position: "relative",
	                    verticalAlign: "top"
	                },
	                menu: {
	                    position: "absolute",
	                    top: "100%",
	                    left: "0",
	                    zIndex: "100",
	                    display: "none"
	                },
	                ltr: {
	                    left: "0",
	                    right: "auto"
	                },
	                rtl: {
	                    left: "auto",
	                    right: " 0"
	                }
	            };
	            if (_.isMsie()) {
	                _.mixin(css.input, {
	                    backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
	                });
	            }
	            return css;
	        }
	    }();
	    var EventBus = function() {
	        "use strict";
	        var namespace, deprecationMap;
	        namespace = "typeahead:";
	        deprecationMap = {
	            render: "rendered",
	            cursorchange: "cursorchanged",
	            select: "selected",
	            autocomplete: "autocompleted"
	        };
	        function EventBus(o) {
	            if (!o || !o.el) {
	                $.error("EventBus initialized without el");
	            }
	            this.$el = $(o.el);
	        }
	        _.mixin(EventBus.prototype, {
	            _trigger: function(type, args) {
	                var $e = $.Event(namespace + type);
	                this.$el.trigger.call(this.$el, $e, args || []);
	                return $e;
	            },
	            before: function(type) {
	                var args, $e;
	                args = [].slice.call(arguments, 1);
	                $e = this._trigger("before" + type, args);
	                return $e.isDefaultPrevented();
	            },
	            trigger: function(type) {
	                var deprecatedType;
	                this._trigger(type, [].slice.call(arguments, 1));
	                if (deprecatedType = deprecationMap[type]) {
	                    this._trigger(deprecatedType, [].slice.call(arguments, 1));
	                }
	            }
	        });
	        return EventBus;
	    }();
	    var EventEmitter = function() {
	        "use strict";
	        var splitter = /\s+/, nextTick = getNextTick();
	        return {
	            onSync: onSync,
	            onAsync: onAsync,
	            off: off,
	            trigger: trigger
	        };
	        function on(method, types, cb, context) {
	            var type;
	            if (!cb) {
	                return this;
	            }
	            types = types.split(splitter);
	            cb = context ? bindContext(cb, context) : cb;
	            this._callbacks = this._callbacks || {};
	            while (type = types.shift()) {
	                this._callbacks[type] = this._callbacks[type] || {
	                    sync: [],
	                    async: []
	                };
	                this._callbacks[type][method].push(cb);
	            }
	            return this;
	        }
	        function onAsync(types, cb, context) {
	            return on.call(this, "async", types, cb, context);
	        }
	        function onSync(types, cb, context) {
	            return on.call(this, "sync", types, cb, context);
	        }
	        function off(types) {
	            var type;
	            if (!this._callbacks) {
	                return this;
	            }
	            types = types.split(splitter);
	            while (type = types.shift()) {
	                delete this._callbacks[type];
	            }
	            return this;
	        }
	        function trigger(types) {
	            var type, callbacks, args, syncFlush, asyncFlush;
	            if (!this._callbacks) {
	                return this;
	            }
	            types = types.split(splitter);
	            args = [].slice.call(arguments, 1);
	            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
	                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
	                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
	                syncFlush() && nextTick(asyncFlush);
	            }
	            return this;
	        }
	        function getFlush(callbacks, context, args) {
	            return flush;
	            function flush() {
	                var cancelled;
	                for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
	                    cancelled = callbacks[i].apply(context, args) === false;
	                }
	                return !cancelled;
	            }
	        }
	        function getNextTick() {
	            var nextTickFn;
	            if (window.setImmediate) {
	                nextTickFn = function nextTickSetImmediate(fn) {
	                    setImmediate(function() {
	                        fn();
	                    });
	                };
	            } else {
	                nextTickFn = function nextTickSetTimeout(fn) {
	                    setTimeout(function() {
	                        fn();
	                    }, 0);
	                };
	            }
	            return nextTickFn;
	        }
	        function bindContext(fn, context) {
	            return fn.bind ? fn.bind(context) : function() {
	                fn.apply(context, [].slice.call(arguments, 0));
	            };
	        }
	    }();
	    var highlight = function(doc) {
	        "use strict";
	        var defaults = {
	            node: null,
	            pattern: null,
	            tagName: "strong",
	            className: null,
	            wordsOnly: false,
	            caseSensitive: false,
	            diacriticInsensitive: false
	        };
	        var accented = {
	            A: "[AaªÀ-Åà-åĀ-ąǍǎȀ-ȃȦȧᴬᵃḀḁẚẠ-ảₐ℀℁℻⒜Ⓐⓐ㍱-㍴㎀-㎄㎈㎉㎩-㎯㏂㏊㏟㏿Ａａ]",
	            B: "[BbᴮᵇḂ-ḇℬ⒝Ⓑⓑ㍴㎅-㎇㏃㏈㏔㏝Ｂｂ]",
	            C: "[CcÇçĆ-čᶜ℀ℂ℃℅℆ℭⅭⅽ⒞Ⓒⓒ㍶㎈㎉㎝㎠㎤㏄-㏇Ｃｃ]",
	            D: "[DdĎďǄ-ǆǱ-ǳᴰᵈḊ-ḓⅅⅆⅮⅾ⒟Ⓓⓓ㋏㍲㍷-㍹㎗㎭-㎯㏅㏈Ｄｄ]",
	            E: "[EeÈ-Ëè-ëĒ-ěȄ-ȇȨȩᴱᵉḘ-ḛẸ-ẽₑ℡ℯℰⅇ⒠Ⓔⓔ㉐㋍㋎Ｅｅ]",
	            F: "[FfᶠḞḟ℉ℱ℻⒡Ⓕⓕ㎊-㎌㎙ﬀ-ﬄＦｆ]",
	            G: "[GgĜ-ģǦǧǴǵᴳᵍḠḡℊ⒢Ⓖⓖ㋌㋍㎇㎍-㎏㎓㎬㏆㏉㏒㏿Ｇｇ]",
	            H: "[HhĤĥȞȟʰᴴḢ-ḫẖℋ-ℎ⒣Ⓗⓗ㋌㍱㎐-㎔㏊㏋㏗Ｈｈ]",
	            I: "[IiÌ-Ïì-ïĨ-İĲĳǏǐȈ-ȋᴵᵢḬḭỈ-ịⁱℐℑℹⅈⅠ-ⅣⅥ-ⅨⅪⅫⅰ-ⅳⅵ-ⅸⅺⅻ⒤Ⓘⓘ㍺㏌㏕ﬁﬃＩｉ]",
	            J: "[JjĲ-ĵǇ-ǌǰʲᴶⅉ⒥ⒿⓙⱼＪｊ]",
	            K: "[KkĶķǨǩᴷᵏḰ-ḵK⒦Ⓚⓚ㎄㎅㎉㎏㎑㎘㎞㎢㎦㎪㎸㎾㏀㏆㏍-㏏Ｋｋ]",
	            L: "[LlĹ-ŀǇ-ǉˡᴸḶḷḺ-ḽℒℓ℡Ⅼⅼ⒧Ⓛⓛ㋏㎈㎉㏐-㏓㏕㏖㏿ﬂﬄＬｌ]",
	            M: "[MmᴹᵐḾ-ṃ℠™ℳⅯⅿ⒨Ⓜⓜ㍷-㍹㎃㎆㎎㎒㎖㎙-㎨㎫㎳㎷㎹㎽㎿㏁㏂㏎㏐㏔-㏖㏘㏙㏞㏟Ｍｍ]",
	            N: "[NnÑñŃ-ŉǊ-ǌǸǹᴺṄ-ṋⁿℕ№⒩Ⓝⓝ㎁㎋㎚㎱㎵㎻㏌㏑Ｎｎ]",
	            O: "[OoºÒ-Öò-öŌ-őƠơǑǒǪǫȌ-ȏȮȯᴼᵒỌ-ỏₒ℅№ℴ⒪Ⓞⓞ㍵㏇㏒㏖Ｏｏ]",
	            P: "[PpᴾᵖṔ-ṗℙ⒫Ⓟⓟ㉐㍱㍶㎀㎊㎩-㎬㎰㎴㎺㏋㏗-㏚Ｐｐ]",
	            Q: "[Qqℚ⒬Ⓠⓠ㏃Ｑｑ]",
	            R: "[RrŔ-řȐ-ȓʳᴿᵣṘ-ṛṞṟ₨ℛ-ℝ⒭Ⓡⓡ㋍㍴㎭-㎯㏚㏛Ｒｒ]",
	            S: "[SsŚ-šſȘșˢṠ-ṣ₨℁℠⒮Ⓢⓢ㎧㎨㎮-㎳㏛㏜ﬆＳｓ]",
	            T: "[TtŢ-ťȚțᵀᵗṪ-ṱẗ℡™⒯Ⓣⓣ㉐㋏㎔㏏ﬅﬆＴｔ]",
	            U: "[UuÙ-Üù-üŨ-ųƯưǓǔȔ-ȗᵁᵘᵤṲ-ṷỤ-ủ℆⒰Ⓤⓤ㍳㍺Ｕｕ]",
	            V: "[VvᵛᵥṼ-ṿⅣ-Ⅷⅳ-ⅷ⒱Ⓥⓥⱽ㋎㍵㎴-㎹㏜㏞Ｖｖ]",
	            W: "[WwŴŵʷᵂẀ-ẉẘ⒲Ⓦⓦ㎺-㎿㏝Ｗｗ]",
	            X: "[XxˣẊ-ẍₓ℻Ⅸ-Ⅻⅸ-ⅻ⒳Ⓧⓧ㏓Ｘｘ]",
	            Y: "[YyÝýÿŶ-ŸȲȳʸẎẏẙỲ-ỹ⒴Ⓨⓨ㏉Ｙｙ]",
	            Z: "[ZzŹ-žǱ-ǳᶻẐ-ẕℤℨ⒵Ⓩⓩ㎐-㎔Ｚｚ]"
	        };
	        return function hightlight(o) {
	            var regex;
	            o = _.mixin({}, defaults, o);
	            if (!o.node || !o.pattern) {
	                return;
	            }
	            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
	            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly, o.diacriticInsensitive);
	            traverse(o.node, hightlightTextNode);
	            function hightlightTextNode(textNode) {
	                var match, patternNode, wrapperNode;
	                if (match = regex.exec(textNode.data)) {
	                    wrapperNode = doc.createElement(o.tagName);
	                    o.className && (wrapperNode.className = o.className);
	                    patternNode = textNode.splitText(match.index);
	                    patternNode.splitText(match[0].length);
	                    wrapperNode.appendChild(patternNode.cloneNode(true));
	                    textNode.parentNode.replaceChild(wrapperNode, patternNode);
	                }
	                return !!match;
	            }
	            function traverse(el, hightlightTextNode) {
	                var childNode, TEXT_NODE_TYPE = 3;
	                for (var i = 0; i < el.childNodes.length; i++) {
	                    childNode = el.childNodes[i];
	                    if (childNode.nodeType === TEXT_NODE_TYPE) {
	                        i += hightlightTextNode(childNode) ? 1 : 0;
	                    } else {
	                        traverse(childNode, hightlightTextNode);
	                    }
	                }
	            }
	        };
	        function accent_replacer(chr) {
	            return accented[chr.toUpperCase()] || chr;
	        }
	        function getRegex(patterns, caseSensitive, wordsOnly, diacriticInsensitive) {
	            var escapedPatterns = [], regexStr;
	            for (var i = 0, len = patterns.length; i < len; i++) {
	                var escapedWord = _.escapeRegExChars(patterns[i]);
	                if (diacriticInsensitive) {
	                    escapedWord = escapedWord.replace(/\S/g, accent_replacer);
	                }
	                escapedPatterns.push(escapedWord);
	            }
	            regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
	            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
	        }
	    }(window.document);
	    var Input = function() {
	        "use strict";
	        var specialKeyCodeMap;
	        specialKeyCodeMap = {
	            9: "tab",
	            27: "esc",
	            37: "left",
	            39: "right",
	            13: "enter",
	            38: "up",
	            40: "down"
	        };
	        function Input(o, www) {
	            o = o || {};
	            if (!o.input) {
	                $.error("input is missing");
	            }
	            www.mixin(this);
	            this.$hint = $(o.hint);
	            this.$input = $(o.input);
	            this.$input.attr({
	                "aria-activedescendant": "",
	                "aria-owns": this.$input.attr("id") + "_listbox",
	                role: "combobox",
	                "aria-readonly": "true",
	                "aria-autocomplete": "list"
	            });
	            $(www.menu).attr("id", this.$input.attr("id") + "_listbox");
	            this.query = this.$input.val();
	            this.queryWhenFocused = this.hasFocus() ? this.query : null;
	            this.$overflowHelper = buildOverflowHelper(this.$input);
	            this._checkLanguageDirection();
	            if (this.$hint.length === 0) {
	                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
	            }
	            this.onSync("cursorchange", this._updateDescendent);
	        }
	        Input.normalizeQuery = function(str) {
	            return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
	        };
	        _.mixin(Input.prototype, EventEmitter, {
	            _onBlur: function onBlur() {
	                this.resetInputValue();
	                this.trigger("blurred");
	            },
	            _onFocus: function onFocus() {
	                this.queryWhenFocused = this.query;
	                this.trigger("focused");
	            },
	            _onKeydown: function onKeydown($e) {
	                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
	                this._managePreventDefault(keyName, $e);
	                if (keyName && this._shouldTrigger(keyName, $e)) {
	                    this.trigger(keyName + "Keyed", $e);
	                }
	            },
	            _onInput: function onInput() {
	                this._setQuery(this.getInputValue());
	                this.clearHintIfInvalid();
	                this._checkLanguageDirection();
	            },
	            _managePreventDefault: function managePreventDefault(keyName, $e) {
	                var preventDefault;
	                switch (keyName) {
	                  case "up":
	                  case "down":
	                    preventDefault = !withModifier($e);
	                    break;

	                  default:
	                    preventDefault = false;
	                }
	                preventDefault && $e.preventDefault();
	            },
	            _shouldTrigger: function shouldTrigger(keyName, $e) {
	                var trigger;
	                switch (keyName) {
	                  case "tab":
	                    trigger = !withModifier($e);
	                    break;

	                  default:
	                    trigger = true;
	                }
	                return trigger;
	            },
	            _checkLanguageDirection: function checkLanguageDirection() {
	                var dir = (this.$input.css("direction") || "ltr").toLowerCase();
	                if (this.dir !== dir) {
	                    this.dir = dir;
	                    this.$hint.attr("dir", dir);
	                    this.trigger("langDirChanged", dir);
	                }
	            },
	            _setQuery: function setQuery(val, silent) {
	                var areEquivalent, hasDifferentWhitespace;
	                areEquivalent = areQueriesEquivalent(val, this.query);
	                hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
	                this.query = val;
	                if (!silent && !areEquivalent) {
	                    this.trigger("queryChanged", this.query);
	                } else if (!silent && hasDifferentWhitespace) {
	                    this.trigger("whitespaceChanged", this.query);
	                }
	            },
	            _updateDescendent: function updateDescendent(event, id) {
	                this.$input.attr("aria-activedescendant", id);
	            },
	            bind: function() {
	                var that = this, onBlur, onFocus, onKeydown, onInput;
	                onBlur = _.bind(this._onBlur, this);
	                onFocus = _.bind(this._onFocus, this);
	                onKeydown = _.bind(this._onKeydown, this);
	                onInput = _.bind(this._onInput, this);
	                this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
	                if (!_.isMsie() || _.isMsie() > 9) {
	                    this.$input.on("input.tt", onInput);
	                } else {
	                    this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
	                        if (specialKeyCodeMap[$e.which || $e.keyCode]) {
	                            return;
	                        }
	                        _.defer(_.bind(that._onInput, that, $e));
	                    });
	                }
	                return this;
	            },
	            focus: function focus() {
	                this.$input.focus();
	            },
	            blur: function blur() {
	                this.$input.blur();
	            },
	            getLangDir: function getLangDir() {
	                return this.dir;
	            },
	            getQuery: function getQuery() {
	                return this.query || "";
	            },
	            setQuery: function setQuery(val, silent) {
	                this.setInputValue(val);
	                this._setQuery(val, silent);
	            },
	            hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
	                return this.query !== this.queryWhenFocused;
	            },
	            getInputValue: function getInputValue() {
	                return this.$input.val();
	            },
	            setInputValue: function setInputValue(value) {
	                this.$input.val(value);
	                this.clearHintIfInvalid();
	                this._checkLanguageDirection();
	            },
	            resetInputValue: function resetInputValue() {
	                this.setInputValue(this.query);
	            },
	            getHint: function getHint() {
	                return this.$hint.val();
	            },
	            setHint: function setHint(value) {
	                this.$hint.val(value);
	            },
	            clearHint: function clearHint() {
	                this.setHint("");
	            },
	            clearHintIfInvalid: function clearHintIfInvalid() {
	                var val, hint, valIsPrefixOfHint, isValid;
	                val = this.getInputValue();
	                hint = this.getHint();
	                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
	                isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
	                !isValid && this.clearHint();
	            },
	            hasFocus: function hasFocus() {
	                return this.$input.is(":focus");
	            },
	            hasOverflow: function hasOverflow() {
	                var constraint = this.$input.width() - 2;
	                this.$overflowHelper.text(this.getInputValue());
	                return this.$overflowHelper.width() >= constraint;
	            },
	            isCursorAtEnd: function() {
	                var valueLength, selectionStart, range;
	                valueLength = this.$input.val().length;
	                selectionStart = this.$input[0].selectionStart;
	                if (_.isNumber(selectionStart)) {
	                    return selectionStart === valueLength;
	                } else if (document.selection) {
	                    range = document.selection.createRange();
	                    range.moveStart("character", -valueLength);
	                    return valueLength === range.text.length;
	                }
	                return true;
	            },
	            destroy: function destroy() {
	                this.$hint.off(".tt");
	                this.$input.off(".tt");
	                this.$overflowHelper.remove();
	                this.$hint = this.$input = this.$overflowHelper = $("<div>");
	            }
	        });
	        return Input;
	        function buildOverflowHelper($input) {
	            return $('<pre aria-hidden="true"></pre>').css({
	                position: "absolute",
	                visibility: "hidden",
	                whiteSpace: "pre",
	                fontFamily: $input.css("font-family"),
	                fontSize: $input.css("font-size"),
	                fontStyle: $input.css("font-style"),
	                fontVariant: $input.css("font-variant"),
	                fontWeight: $input.css("font-weight"),
	                wordSpacing: $input.css("word-spacing"),
	                letterSpacing: $input.css("letter-spacing"),
	                textIndent: $input.css("text-indent"),
	                textRendering: $input.css("text-rendering"),
	                textTransform: $input.css("text-transform")
	            }).insertAfter($input);
	        }
	        function areQueriesEquivalent(a, b) {
	            return Input.normalizeQuery(a) === Input.normalizeQuery(b);
	        }
	        function withModifier($e) {
	            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
	        }
	    }();
	    var Dataset = function() {
	        "use strict";
	        var keys, nameGenerator;
	        keys = {
	            dataset: "tt-selectable-dataset",
	            val: "tt-selectable-display",
	            obj: "tt-selectable-object"
	        };
	        nameGenerator = _.getIdGenerator();
	        function Dataset(o, www) {
	            o = o || {};
	            o.templates = o.templates || {};
	            o.templates.notFound = o.templates.notFound || o.templates.empty;
	            if (!o.source) {
	                $.error("missing source");
	            }
	            if (!o.node) {
	                $.error("missing node");
	            }
	            if (o.name && !isValidName(o.name)) {
	                $.error("invalid dataset name: " + o.name);
	            }
	            www.mixin(this);
	            this.highlight = !!o.highlight;
	            this.name = _.toStr(o.name || nameGenerator());
	            this.limit = o.limit || 5;
	            this.displayFn = getDisplayFn(o.display || o.displayKey);
	            this.templates = getTemplates(o.templates, this.displayFn);
	            this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
	            this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
	            this._resetLastSuggestion();
	            this.$el = $(o.node).attr("role", "presentation").addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
	        }
	        Dataset.extractData = function extractData(el) {
	            var $el = $(el);
	            if ($el.data(keys.obj)) {
	                return {
	                    dataset: $el.data(keys.dataset) || "",
	                    val: $el.data(keys.val) || "",
	                    obj: $el.data(keys.obj) || null
	                };
	            }
	            return null;
	        };
	        _.mixin(Dataset.prototype, EventEmitter, {
	            _overwrite: function overwrite(query, suggestions) {
	                suggestions = suggestions || [];
	                if (suggestions.length) {
	                    this._renderSuggestions(query, suggestions);
	                } else if (this.async && this.templates.pending) {
	                    this._renderPending(query);
	                } else if (!this.async && this.templates.notFound) {
	                    this._renderNotFound(query);
	                } else {
	                    this._empty();
	                }
	                this.trigger("rendered", suggestions, false, this.name);
	            },
	            _append: function append(query, suggestions) {
	                suggestions = suggestions || [];
	                if (suggestions.length && this.$lastSuggestion.length) {
	                    this._appendSuggestions(query, suggestions);
	                } else if (suggestions.length) {
	                    this._renderSuggestions(query, suggestions);
	                } else if (!this.$lastSuggestion.length && this.templates.notFound) {
	                    this._renderNotFound(query);
	                }
	                this.trigger("rendered", suggestions, true, this.name);
	            },
	            _renderSuggestions: function renderSuggestions(query, suggestions) {
	                var $fragment;
	                $fragment = this._getSuggestionsFragment(query, suggestions);
	                this.$lastSuggestion = $fragment.children().last();
	                this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
	            },
	            _appendSuggestions: function appendSuggestions(query, suggestions) {
	                var $fragment, $lastSuggestion;
	                $fragment = this._getSuggestionsFragment(query, suggestions);
	                $lastSuggestion = $fragment.children().last();
	                this.$lastSuggestion.after($fragment);
	                this.$lastSuggestion = $lastSuggestion;
	            },
	            _renderPending: function renderPending(query) {
	                var template = this.templates.pending;
	                this._resetLastSuggestion();
	                template && this.$el.html(template({
	                    query: query,
	                    dataset: this.name
	                }));
	            },
	            _renderNotFound: function renderNotFound(query) {
	                var template = this.templates.notFound;
	                this._resetLastSuggestion();
	                template && this.$el.html(template({
	                    query: query,
	                    dataset: this.name
	                }));
	            },
	            _empty: function empty() {
	                this.$el.empty();
	                this._resetLastSuggestion();
	            },
	            _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
	                var that = this, fragment;
	                fragment = document.createDocumentFragment();
	                _.each(suggestions, function getSuggestionNode(suggestion) {
	                    var $el, context;
	                    context = that._injectQuery(query, suggestion);
	                    $el = $(that.templates.suggestion(context)).data(keys.dataset, that.name).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
	                    fragment.appendChild($el[0]);
	                });
	                this.highlight && highlight({
	                    className: this.classes.highlight,
	                    node: fragment,
	                    pattern: query
	                });
	                return $(fragment);
	            },
	            _getFooter: function getFooter(query, suggestions) {
	                return this.templates.footer ? this.templates.footer({
	                    query: query,
	                    suggestions: suggestions,
	                    dataset: this.name
	                }) : null;
	            },
	            _getHeader: function getHeader(query, suggestions) {
	                return this.templates.header ? this.templates.header({
	                    query: query,
	                    suggestions: suggestions,
	                    dataset: this.name
	                }) : null;
	            },
	            _resetLastSuggestion: function resetLastSuggestion() {
	                this.$lastSuggestion = $();
	            },
	            _injectQuery: function injectQuery(query, obj) {
	                return _.isObject(obj) ? _.mixin({
	                    _query: query
	                }, obj) : obj;
	            },
	            update: function update(query) {
	                var that = this, canceled = false, syncCalled = false, rendered = 0;
	                this.cancel();
	                this.cancel = function cancel() {
	                    canceled = true;
	                    that.cancel = $.noop;
	                    that.async && that.trigger("asyncCanceled", query, that.name);
	                };
	                this.source(query, sync, async);
	                !syncCalled && sync([]);
	                function sync(suggestions) {
	                    if (syncCalled) {
	                        return;
	                    }
	                    syncCalled = true;
	                    suggestions = (suggestions || []).slice(0, that.limit);
	                    rendered = suggestions.length;
	                    that._overwrite(query, suggestions);
	                    if (rendered < that.limit && that.async) {
	                        that.trigger("asyncRequested", query, that.name);
	                    }
	                }
	                function async(suggestions) {
	                    suggestions = suggestions || [];
	                    if (!canceled && rendered < that.limit) {
	                        that.cancel = $.noop;
	                        var idx = Math.abs(rendered - that.limit);
	                        rendered += idx;
	                        that._append(query, suggestions.slice(0, idx));
	                        that.async && that.trigger("asyncReceived", query, that.name);
	                    }
	                }
	            },
	            cancel: $.noop,
	            clear: function clear() {
	                this._empty();
	                this.cancel();
	                this.trigger("cleared");
	            },
	            isEmpty: function isEmpty() {
	                return this.$el.is(":empty");
	            },
	            destroy: function destroy() {
	                this.$el = $("<div>");
	            }
	        });
	        return Dataset;
	        function getDisplayFn(display) {
	            display = display || _.stringify;
	            return _.isFunction(display) ? display : displayFn;
	            function displayFn(obj) {
	                return obj[display];
	            }
	        }
	        function getTemplates(templates, displayFn) {
	            return {
	                notFound: templates.notFound && _.templatify(templates.notFound),
	                pending: templates.pending && _.templatify(templates.pending),
	                header: templates.header && _.templatify(templates.header),
	                footer: templates.footer && _.templatify(templates.footer),
	                suggestion: templates.suggestion || suggestionTemplate
	            };
	            function suggestionTemplate(context) {
	                return $('<div role="option">').attr("id", _.guid()).text(displayFn(context));
	            }
	        }
	        function isValidName(str) {
	            return /^[_a-zA-Z0-9-]+$/.test(str);
	        }
	    }();
	    var Menu = function() {
	        "use strict";
	        function Menu(o, www) {
	            var that = this;
	            o = o || {};
	            if (!o.node) {
	                $.error("node is required");
	            }
	            www.mixin(this);
	            this.$node = $(o.node);
	            this.query = null;
	            this.datasets = _.map(o.datasets, initializeDataset);
	            function initializeDataset(oDataset) {
	                var node = that.$node.find(oDataset.node).first();
	                oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
	                return new Dataset(oDataset, www);
	            }
	        }
	        _.mixin(Menu.prototype, EventEmitter, {
	            _onSelectableClick: function onSelectableClick($e) {
	                this.trigger("selectableClicked", $($e.currentTarget));
	            },
	            _onRendered: function onRendered(type, dataset, suggestions, async) {
	                this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
	                this.trigger("datasetRendered", dataset, suggestions, async);
	            },
	            _onCleared: function onCleared() {
	                this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
	                this.trigger("datasetCleared");
	            },
	            _propagate: function propagate() {
	                this.trigger.apply(this, arguments);
	            },
	            _allDatasetsEmpty: function allDatasetsEmpty() {
	                return _.every(this.datasets, _.bind(function isDatasetEmpty(dataset) {
	                    var isEmpty = dataset.isEmpty();
	                    this.$node.attr("aria-expanded", !isEmpty);
	                    return isEmpty;
	                }, this));
	            },
	            _getSelectables: function getSelectables() {
	                return this.$node.find(this.selectors.selectable);
	            },
	            _removeCursor: function _removeCursor() {
	                var $selectable = this.getActiveSelectable();
	                $selectable && $selectable.removeClass(this.classes.cursor);
	            },
	            _ensureVisible: function ensureVisible($el) {
	                var elTop, elBottom, nodeScrollTop, nodeHeight;
	                elTop = $el.position().top;
	                elBottom = elTop + $el.outerHeight(true);
	                nodeScrollTop = this.$node.scrollTop();
	                nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
	                if (elTop < 0) {
	                    this.$node.scrollTop(nodeScrollTop + elTop);
	                } else if (nodeHeight < elBottom) {
	                    this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
	                }
	            },
	            bind: function() {
	                var that = this, onSelectableClick;
	                onSelectableClick = _.bind(this._onSelectableClick, this);
	                this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
	                this.$node.on("mouseover", this.selectors.selectable, function() {
	                    that.setCursor($(this));
	                });
	                this.$node.on("mouseleave", function() {
	                    that._removeCursor();
	                });
	                _.each(this.datasets, function(dataset) {
	                    dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
	                });
	                return this;
	            },
	            isOpen: function isOpen() {
	                return this.$node.hasClass(this.classes.open);
	            },
	            open: function open() {
	                this.$node.scrollTop(0);
	                this.$node.addClass(this.classes.open);
	            },
	            close: function close() {
	                this.$node.attr("aria-expanded", false);
	                this.$node.removeClass(this.classes.open);
	                this._removeCursor();
	            },
	            setLanguageDirection: function setLanguageDirection(dir) {
	                this.$node.attr("dir", dir);
	            },
	            selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
	                var $selectables, $oldCursor, oldIndex, newIndex;
	                $oldCursor = this.getActiveSelectable();
	                $selectables = this._getSelectables();
	                oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
	                newIndex = oldIndex + delta;
	                newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
	                newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
	                return newIndex === -1 ? null : $selectables.eq(newIndex);
	            },
	            setCursor: function setCursor($selectable) {
	                this._removeCursor();
	                if ($selectable = $selectable && $selectable.first()) {
	                    $selectable.addClass(this.classes.cursor);
	                    this._ensureVisible($selectable);
	                }
	            },
	            getSelectableData: function getSelectableData($el) {
	                return $el && $el.length ? Dataset.extractData($el) : null;
	            },
	            getActiveSelectable: function getActiveSelectable() {
	                var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
	                return $selectable.length ? $selectable : null;
	            },
	            getTopSelectable: function getTopSelectable() {
	                var $selectable = this._getSelectables().first();
	                return $selectable.length ? $selectable : null;
	            },
	            update: function update(query) {
	                var isValidUpdate = query !== this.query;
	                if (isValidUpdate) {
	                    this.query = query;
	                    _.each(this.datasets, updateDataset);
	                }
	                return isValidUpdate;
	                function updateDataset(dataset) {
	                    dataset.update(query);
	                }
	            },
	            empty: function empty() {
	                _.each(this.datasets, clearDataset);
	                this.query = null;
	                this.$node.addClass(this.classes.empty);
	                function clearDataset(dataset) {
	                    dataset.clear();
	                }
	            },
	            destroy: function destroy() {
	                this.$node.off(".tt");
	                this.$node = $("<div>");
	                _.each(this.datasets, destroyDataset);
	                function destroyDataset(dataset) {
	                    dataset.destroy();
	                }
	            }
	        });
	        return Menu;
	    }();
	    var Status = function() {
	        "use strict";
	        function Status(options) {
	            this.el = '<span role="status" aria-live="polite" class="visuallyhidden"></span>';
	            this.$el = $(this.el);
	            options.$input.after(this.$el);
	            _.each(options.menu.datasets, _.bind(function(dataset) {
	                if (dataset.onSync) {
	                    dataset.onSync("rendered", _.bind(this.update, this));
	                    dataset.onSync("cleared", _.bind(this.cleared, this));
	                }
	            }, this));
	        }
	        _.mixin(Status.prototype, {
	            update: function update(event, suggestions) {
	                var length = suggestions.length;
	                var words;
	                if (length === 1) {
	                    words = {
	                        result: "result",
	                        is: "is"
	                    };
	                } else {
	                    words = {
	                        result: "results",
	                        is: "are"
	                    };
	                }
	                this.$el.text(length + " " + words.result + " " + words.is + " available, use up and down arrow keys to navigate.");
	            },
	            cleared: function() {
	                this.$el.text("");
	            }
	        });
	        return Status;
	    }();
	    var DefaultMenu = function() {
	        "use strict";
	        var s = Menu.prototype;
	        function DefaultMenu() {
	            Menu.apply(this, [].slice.call(arguments, 0));
	        }
	        _.mixin(DefaultMenu.prototype, Menu.prototype, {
	            open: function open() {
	                !this._allDatasetsEmpty() && this._show();
	                return s.open.apply(this, [].slice.call(arguments, 0));
	            },
	            close: function close() {
	                this._hide();
	                return s.close.apply(this, [].slice.call(arguments, 0));
	            },
	            _onRendered: function onRendered() {
	                if (this._allDatasetsEmpty()) {
	                    this._hide();
	                } else {
	                    this.isOpen() && this._show();
	                }
	                return s._onRendered.apply(this, [].slice.call(arguments, 0));
	            },
	            _onCleared: function onCleared() {
	                if (this._allDatasetsEmpty()) {
	                    this._hide();
	                } else {
	                    this.isOpen() && this._show();
	                }
	                return s._onCleared.apply(this, [].slice.call(arguments, 0));
	            },
	            setLanguageDirection: function setLanguageDirection(dir) {
	                this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
	                return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
	            },
	            _hide: function hide() {
	                this.$node.hide();
	            },
	            _show: function show() {
	                this.$node.css("display", "block");
	            }
	        });
	        return DefaultMenu;
	    }();
	    var Typeahead = function() {
	        "use strict";
	        function Typeahead(o, www) {
	            var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
	            o = o || {};
	            if (!o.input) {
	                $.error("missing input");
	            }
	            if (!o.menu) {
	                $.error("missing menu");
	            }
	            if (!o.eventBus) {
	                $.error("missing event bus");
	            }
	            www.mixin(this);
	            this.eventBus = o.eventBus;
	            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
	            this.input = o.input;
	            this.menu = o.menu;
	            this.enabled = true;
	            this.active = false;
	            this.input.hasFocus() && this.activate();
	            this.dir = this.input.getLangDir();
	            this._hacks();
	            this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
	            onFocused = c(this, "activate", "open", "_onFocused");
	            onBlurred = c(this, "deactivate", "_onBlurred");
	            onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
	            onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
	            onEscKeyed = c(this, "isActive", "_onEscKeyed");
	            onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
	            onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
	            onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
	            onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
	            onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
	            onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
	            this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this);
	        }
	        _.mixin(Typeahead.prototype, {
	            _hacks: function hacks() {
	                var $input, $menu;
	                $input = this.input.$input || $("<div>");
	                $menu = this.menu.$node || $("<div>");
	                $input.on("blur.tt", function($e) {
	                    var active, isActive, hasActive;
	                    active = document.activeElement;
	                    isActive = $menu.is(active);
	                    hasActive = $menu.has(active).length > 0;
	                    if (_.isMsie() && (isActive || hasActive)) {
	                        $e.preventDefault();
	                        $e.stopImmediatePropagation();
	                        _.defer(function() {
	                            $input.focus();
	                        });
	                    }
	                });
	                $menu.on("mousedown.tt", function($e) {
	                    $e.preventDefault();
	                });
	            },
	            _onSelectableClicked: function onSelectableClicked(type, $el) {
	                this.select($el);
	            },
	            _onDatasetCleared: function onDatasetCleared() {
	                this._updateHint();
	            },
	            _onDatasetRendered: function onDatasetRendered(type, suggestions, async, dataset) {
	                this._updateHint();
	                this.eventBus.trigger("render", suggestions, async, dataset);
	            },
	            _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
	                this.eventBus.trigger("asyncrequest", query, dataset);
	            },
	            _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
	                this.eventBus.trigger("asynccancel", query, dataset);
	            },
	            _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
	                this.eventBus.trigger("asyncreceive", query, dataset);
	            },
	            _onFocused: function onFocused() {
	                this._minLengthMet() && this.menu.update(this.input.getQuery());
	            },
	            _onBlurred: function onBlurred() {
	                if (this.input.hasQueryChangedSinceLastFocus()) {
	                    this.eventBus.trigger("change", this.input.getQuery());
	                }
	            },
	            _onEnterKeyed: function onEnterKeyed(type, $e) {
	                var $selectable;
	                if ($selectable = this.menu.getActiveSelectable()) {
	                    if (this.select($selectable)) {
	                        $e.preventDefault();
	                        $e.stopPropagation();
	                    }
	                }
	            },
	            _onTabKeyed: function onTabKeyed(type, $e) {
	                var $selectable;
	                if ($selectable = this.menu.getActiveSelectable()) {
	                    this.select($selectable) && $e.preventDefault();
	                } else if ($selectable = this.menu.getTopSelectable()) {
	                    this.autocomplete($selectable) && $e.preventDefault();
	                }
	            },
	            _onEscKeyed: function onEscKeyed() {
	                this.close();
	            },
	            _onUpKeyed: function onUpKeyed() {
	                this.moveCursor(-1);
	            },
	            _onDownKeyed: function onDownKeyed() {
	                this.moveCursor(+1);
	            },
	            _onLeftKeyed: function onLeftKeyed() {
	                if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
	                    this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable());
	                }
	            },
	            _onRightKeyed: function onRightKeyed() {
	                if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
	                    this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable());
	                }
	            },
	            _onQueryChanged: function onQueryChanged(e, query) {
	                this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
	            },
	            _onWhitespaceChanged: function onWhitespaceChanged() {
	                this._updateHint();
	            },
	            _onLangDirChanged: function onLangDirChanged(e, dir) {
	                if (this.dir !== dir) {
	                    this.dir = dir;
	                    this.menu.setLanguageDirection(dir);
	                }
	            },
	            _openIfActive: function openIfActive() {
	                this.isActive() && this.open();
	            },
	            _minLengthMet: function minLengthMet(query) {
	                query = _.isString(query) ? query : this.input.getQuery() || "";
	                return query.length >= this.minLength;
	            },
	            _updateHint: function updateHint() {
	                var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
	                $selectable = this.menu.getTopSelectable();
	                data = this.menu.getSelectableData($selectable);
	                val = this.input.getInputValue();
	                if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
	                    query = Input.normalizeQuery(val);
	                    escapedQuery = _.escapeRegExChars(query);
	                    frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
	                    match = frontMatchRegEx.exec(data.val);
	                    match && this.input.setHint(val + match[1]);
	                } else {
	                    this.input.clearHint();
	                }
	            },
	            isEnabled: function isEnabled() {
	                return this.enabled;
	            },
	            enable: function enable() {
	                this.enabled = true;
	            },
	            disable: function disable() {
	                this.enabled = false;
	            },
	            isActive: function isActive() {
	                return this.active;
	            },
	            activate: function activate() {
	                if (this.isActive()) {
	                    return true;
	                } else if (!this.isEnabled() || this.eventBus.before("active")) {
	                    return false;
	                } else {
	                    this.active = true;
	                    this.eventBus.trigger("active");
	                    return true;
	                }
	            },
	            deactivate: function deactivate() {
	                if (!this.isActive()) {
	                    return true;
	                } else if (this.eventBus.before("idle")) {
	                    return false;
	                } else {
	                    this.active = false;
	                    this.close();
	                    this.eventBus.trigger("idle");
	                    return true;
	                }
	            },
	            isOpen: function isOpen() {
	                return this.menu.isOpen();
	            },
	            open: function open() {
	                if (!this.isOpen() && !this.eventBus.before("open")) {
	                    this.menu.open();
	                    this._updateHint();
	                    this.eventBus.trigger("open");
	                }
	                return this.isOpen();
	            },
	            close: function close() {
	                if (this.isOpen() && !this.eventBus.before("close")) {
	                    this.menu.close();
	                    this.input.clearHint();
	                    this.input.resetInputValue();
	                    this.eventBus.trigger("close");
	                }
	                return !this.isOpen();
	            },
	            setVal: function setVal(val) {
	                this.input.setQuery(_.toStr(val));
	            },
	            getVal: function getVal() {
	                return this.input.getQuery();
	            },
	            select: function select($selectable) {
	                var data = this.menu.getSelectableData($selectable);
	                if (data && !this.eventBus.before("select", data.obj, data.dataset)) {
	                    this.input.setQuery(data.val, true);
	                    this.eventBus.trigger("select", data.obj, data.dataset);
	                    this.close();
	                    return true;
	                }
	                return false;
	            },
	            autocomplete: function autocomplete($selectable) {
	                var query, data, isValid;
	                query = this.input.getQuery();
	                data = this.menu.getSelectableData($selectable);
	                isValid = data && query !== data.val;
	                if (isValid && !this.eventBus.before("autocomplete", data.obj, data.dataset)) {
	                    this.input.setQuery(data.val);
	                    this.eventBus.trigger("autocomplete", data.obj, data.dataset);
	                    return true;
	                }
	                return false;
	            },
	            moveCursor: function moveCursor(delta) {
	                var query, $candidate, data, suggestion, datasetName, cancelMove, id;
	                query = this.input.getQuery();
	                $candidate = this.menu.selectableRelativeToCursor(delta);
	                data = this.menu.getSelectableData($candidate);
	                suggestion = data ? data.obj : null;
	                datasetName = data ? data.dataset : null;
	                id = $candidate ? $candidate.attr("id") : null;
	                this.input.trigger("cursorchange", id);
	                cancelMove = this._minLengthMet() && this.menu.update(query);
	                if (!cancelMove && !this.eventBus.before("cursorchange", suggestion, datasetName)) {
	                    this.menu.setCursor($candidate);
	                    if (data) {
	                        this.input.setInputValue(data.val);
	                    } else {
	                        this.input.resetInputValue();
	                        this._updateHint();
	                    }
	                    this.eventBus.trigger("cursorchange", suggestion, datasetName);
	                    return true;
	                }
	                return false;
	            },
	            destroy: function destroy() {
	                this.input.destroy();
	                this.menu.destroy();
	            }
	        });
	        return Typeahead;
	        function c(ctx) {
	            var methods = [].slice.call(arguments, 1);
	            return function() {
	                var args = [].slice.call(arguments);
	                _.each(methods, function(method) {
	                    return ctx[method].apply(ctx, args);
	                });
	            };
	        }
	    }();
	    (function() {
	        "use strict";
	        var old, keys, methods;
	        old = $.fn.typeahead;
	        keys = {
	            www: "tt-www",
	            attrs: "tt-attrs",
	            typeahead: "tt-typeahead"
	        };
	        methods = {
	            initialize: function initialize(o, datasets) {
	                var www;
	                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
	                o = o || {};
	                www = WWW(o.classNames);
	                return this.each(attach);
	                function attach() {
	                    var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, status, typeahead, MenuConstructor;
	                    _.each(datasets, function(d) {
	                        d.highlight = !!o.highlight;
	                    });
	                    $input = $(this);
	                    $wrapper = $(www.html.wrapper);
	                    $hint = $elOrNull(o.hint);
	                    $menu = $elOrNull(o.menu);
	                    defaultHint = o.hint !== false && !$hint;
	                    defaultMenu = o.menu !== false && !$menu;
	                    defaultHint && ($hint = buildHintFromInput($input, www));
	                    defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
	                    $hint && $hint.val("");
	                    $input = prepInput($input, www);
	                    if (defaultHint || defaultMenu) {
	                        $wrapper.css(www.css.wrapper);
	                        $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
	                        $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
	                    }
	                    MenuConstructor = defaultMenu ? DefaultMenu : Menu;
	                    eventBus = new EventBus({
	                        el: $input
	                    });
	                    input = new Input({
	                        hint: $hint,
	                        input: $input
	                    }, www);
	                    menu = new MenuConstructor({
	                        node: $menu,
	                        datasets: datasets
	                    }, www);
	                    status = new Status({
	                        $input: $input,
	                        menu: menu
	                    });
	                    typeahead = new Typeahead({
	                        input: input,
	                        menu: menu,
	                        eventBus: eventBus,
	                        minLength: o.minLength
	                    }, www);
	                    $input.data(keys.www, www);
	                    $input.data(keys.typeahead, typeahead);
	                }
	            },
	            isEnabled: function isEnabled() {
	                var enabled;
	                ttEach(this.first(), function(t) {
	                    enabled = t.isEnabled();
	                });
	                return enabled;
	            },
	            enable: function enable() {
	                ttEach(this, function(t) {
	                    t.enable();
	                });
	                return this;
	            },
	            disable: function disable() {
	                ttEach(this, function(t) {
	                    t.disable();
	                });
	                return this;
	            },
	            isActive: function isActive() {
	                var active;
	                ttEach(this.first(), function(t) {
	                    active = t.isActive();
	                });
	                return active;
	            },
	            activate: function activate() {
	                ttEach(this, function(t) {
	                    t.activate();
	                });
	                return this;
	            },
	            deactivate: function deactivate() {
	                ttEach(this, function(t) {
	                    t.deactivate();
	                });
	                return this;
	            },
	            isOpen: function isOpen() {
	                var open;
	                ttEach(this.first(), function(t) {
	                    open = t.isOpen();
	                });
	                return open;
	            },
	            open: function open() {
	                ttEach(this, function(t) {
	                    t.open();
	                });
	                return this;
	            },
	            close: function close() {
	                ttEach(this, function(t) {
	                    t.close();
	                });
	                return this;
	            },
	            select: function select(el) {
	                var success = false, $el = $(el);
	                ttEach(this.first(), function(t) {
	                    success = t.select($el);
	                });
	                return success;
	            },
	            autocomplete: function autocomplete(el) {
	                var success = false, $el = $(el);
	                ttEach(this.first(), function(t) {
	                    success = t.autocomplete($el);
	                });
	                return success;
	            },
	            moveCursor: function moveCursoe(delta) {
	                var success = false;
	                ttEach(this.first(), function(t) {
	                    success = t.moveCursor(delta);
	                });
	                return success;
	            },
	            val: function val(newVal) {
	                var query;
	                if (!arguments.length) {
	                    ttEach(this.first(), function(t) {
	                        query = t.getVal();
	                    });
	                    return query;
	                } else {
	                    ttEach(this, function(t) {
	                        t.setVal(_.toStr(newVal));
	                    });
	                    return this;
	                }
	            },
	            destroy: function destroy() {
	                ttEach(this, function(typeahead, $input) {
	                    revert($input);
	                    typeahead.destroy();
	                });
	                return this;
	            }
	        };
	        $.fn.typeahead = function(method) {
	            if (methods[method]) {
	                return methods[method].apply(this, [].slice.call(arguments, 1));
	            } else {
	                return methods.initialize.apply(this, arguments);
	            }
	        };
	        $.fn.typeahead.noConflict = function noConflict() {
	            $.fn.typeahead = old;
	            return this;
	        };
	        function ttEach($els, fn) {
	            $els.each(function() {
	                var $input = $(this), typeahead;
	                (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
	            });
	        }
	        function buildHintFromInput($input, www) {
	            return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
	                spellcheck: "false",
	                tabindex: -1
	            });
	        }
	        function prepInput($input, www) {
	            $input.data(keys.attrs, {
	                dir: $input.attr("dir"),
	                autocomplete: $input.attr("autocomplete"),
	                spellcheck: $input.attr("spellcheck"),
	                style: $input.attr("style")
	            });
	            $input.addClass(www.classes.input).attr({
	                spellcheck: false
	            });
	            try {
	                !$input.attr("dir") && $input.attr("dir", "auto");
	            } catch (e) {}
	            return $input;
	        }
	        function getBackgroundStyles($el) {
	            return {
	                backgroundAttachment: $el.css("background-attachment"),
	                backgroundClip: $el.css("background-clip"),
	                backgroundColor: $el.css("background-color"),
	                backgroundImage: $el.css("background-image"),
	                backgroundOrigin: $el.css("background-origin"),
	                backgroundPosition: $el.css("background-position"),
	                backgroundRepeat: $el.css("background-repeat"),
	                backgroundSize: $el.css("background-size")
	            };
	        }
	        function revert($input) {
	            var www, $wrapper;
	            www = $input.data(keys.www);
	            $wrapper = $input.parent().filter(www.selectors.wrapper);
	            _.each($input.data(keys.attrs), function(val, key) {
	                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
	            });
	            $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
	            if ($wrapper.length) {
	                $input.detach().insertAfter($wrapper);
	                $wrapper.remove();
	            }
	        }
	        function $elOrNull(obj) {
	            var isValid, $el;
	            isValid = _.isJQuery(obj) || _.isElement(obj);
	            $el = isValid ? $(obj).first() : [];
	            return $el.length ? $el : null;
	        }
	    })();
	});
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(212).setImmediate))

/***/ },
/* 212 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(213).nextTick;
	var apply = Function.prototype.apply;
	var slice = Array.prototype.slice;
	var immediateIds = {};
	var nextImmediateId = 0;

	// DOM APIs, for completeness

	exports.setTimeout = function() {
	  return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
	};
	exports.setInterval = function() {
	  return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
	};
	exports.clearTimeout =
	exports.clearInterval = function(timeout) { timeout.close(); };

	function Timeout(id, clearFn) {
	  this._id = id;
	  this._clearFn = clearFn;
	}
	Timeout.prototype.unref = Timeout.prototype.ref = function() {};
	Timeout.prototype.close = function() {
	  this._clearFn.call(window, this._id);
	};

	// Does not start the time, just sets up the members needed.
	exports.enroll = function(item, msecs) {
	  clearTimeout(item._idleTimeoutId);
	  item._idleTimeout = msecs;
	};

	exports.unenroll = function(item) {
	  clearTimeout(item._idleTimeoutId);
	  item._idleTimeout = -1;
	};

	exports._unrefActive = exports.active = function(item) {
	  clearTimeout(item._idleTimeoutId);

	  var msecs = item._idleTimeout;
	  if (msecs >= 0) {
	    item._idleTimeoutId = setTimeout(function onTimeout() {
	      if (item._onTimeout)
	        item._onTimeout();
	    }, msecs);
	  }
	};

	// That's not how node.js implements it but the exposed api is the same.
	exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
	  var id = nextImmediateId++;
	  var args = arguments.length < 2 ? false : slice.call(arguments, 1);

	  immediateIds[id] = true;

	  nextTick(function onNextTick() {
	    if (immediateIds[id]) {
	      // fn.call() is faster so we optimize for the common use-case
	      // @see http://jsperf.com/call-apply-segu
	      if (args) {
	        fn.apply(null, args);
	      } else {
	        fn.call(null);
	      }
	      // Prevent ids from leaking
	      exports.clearImmediate(id);
	    }
	  });

	  return id;
	};

	exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
	  delete immediateIds[id];
	};
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(212).setImmediate, __webpack_require__(212).clearImmediate))

/***/ },
/* 213 */
/***/ function(module, exports) {

	// shim for using process in browser
	var process = module.exports = {};

	// cached from whatever global is present so that test runners that stub it
	// don't break things.  But we need to wrap it in a try catch in case it is
	// wrapped in strict mode code which doesn't define any globals.  It's inside a
	// function because try/catches deoptimize in certain engines.

	var cachedSetTimeout;
	var cachedClearTimeout;

	function defaultSetTimout() {
	    throw new Error('setTimeout has not been defined');
	}
	function defaultClearTimeout () {
	    throw new Error('clearTimeout has not been defined');
	}
	(function () {
	    try {
	        if (typeof setTimeout === 'function') {
	            cachedSetTimeout = setTimeout;
	        } else {
	            cachedSetTimeout = defaultSetTimout;
	        }
	    } catch (e) {
	        cachedSetTimeout = defaultSetTimout;
	    }
	    try {
	        if (typeof clearTimeout === 'function') {
	            cachedClearTimeout = clearTimeout;
	        } else {
	            cachedClearTimeout = defaultClearTimeout;
	        }
	    } catch (e) {
	        cachedClearTimeout = defaultClearTimeout;
	    }
	} ())
	function runTimeout(fun) {
	    if (cachedSetTimeout === setTimeout) {
	        //normal enviroments in sane situations
	        return setTimeout(fun, 0);
	    }
	    // if setTimeout wasn't available but was latter defined
	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
	        cachedSetTimeout = setTimeout;
	        return setTimeout(fun, 0);
	    }
	    try {
	        // when when somebody has screwed with setTimeout but no I.E. maddness
	        return cachedSetTimeout(fun, 0);
	    } catch(e){
	        try {
	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
	            return cachedSetTimeout.call(null, fun, 0);
	        } catch(e){
	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
	            return cachedSetTimeout.call(this, fun, 0);
	        }
	    }


	}
	function runClearTimeout(marker) {
	    if (cachedClearTimeout === clearTimeout) {
	        //normal enviroments in sane situations
	        return clearTimeout(marker);
	    }
	    // if clearTimeout wasn't available but was latter defined
	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
	        cachedClearTimeout = clearTimeout;
	        return clearTimeout(marker);
	    }
	    try {
	        // when when somebody has screwed with setTimeout but no I.E. maddness
	        return cachedClearTimeout(marker);
	    } catch (e){
	        try {
	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
	            return cachedClearTimeout.call(null, marker);
	        } catch (e){
	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
	            return cachedClearTimeout.call(this, marker);
	        }
	    }



	}
	var queue = [];
	var draining = false;
	var currentQueue;
	var queueIndex = -1;

	function cleanUpNextTick() {
	    if (!draining || !currentQueue) {
	        return;
	    }
	    draining = false;
	    if (currentQueue.length) {
	        queue = currentQueue.concat(queue);
	    } else {
	        queueIndex = -1;
	    }
	    if (queue.length) {
	        drainQueue();
	    }
	}

	function drainQueue() {
	    if (draining) {
	        return;
	    }
	    var timeout = runTimeout(cleanUpNextTick);
	    draining = true;

	    var len = queue.length;
	    while(len) {
	        currentQueue = queue;
	        queue = [];
	        while (++queueIndex < len) {
	            if (currentQueue) {
	                currentQueue[queueIndex].run();
	            }
	        }
	        queueIndex = -1;
	        len = queue.length;
	    }
	    currentQueue = null;
	    draining = false;
	    runClearTimeout(timeout);
	}

	process.nextTick = function (fun) {
	    var args = new Array(arguments.length - 1);
	    if (arguments.length > 1) {
	        for (var i = 1; i < arguments.length; i++) {
	            args[i - 1] = arguments[i];
	        }
	    }
	    queue.push(new Item(fun, args));
	    if (queue.length === 1 && !draining) {
	        runTimeout(drainQueue);
	    }
	};

	// v8 likes predictible objects
	function Item(fun, array) {
	    this.fun = fun;
	    this.array = array;
	}
	Item.prototype.run = function () {
	    this.fun.apply(null, this.array);
	};
	process.title = 'browser';
	process.browser = true;
	process.env = {};
	process.argv = [];
	process.version = ''; // empty string to avoid regexp issues
	process.versions = {};

	function noop() {}

	process.on = noop;
	process.addListener = noop;
	process.once = noop;
	process.off = noop;
	process.removeListener = noop;
	process.removeAllListeners = noop;
	process.emit = noop;
	process.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; };


/***/ },
/* 214 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["moment"] = __webpack_require__(215);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 215 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(module) {//! moment.js
	//! version : 2.13.0
	//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
	//! license : MIT
	//! momentjs.com

	;(function (global, factory) {
	     true ? module.exports = factory() :
	    typeof define === 'function' && define.amd ? define(factory) :
	    global.moment = factory()
	}(this, function () { 'use strict';

	    var hookCallback;

	    function utils_hooks__hooks () {
	        return hookCallback.apply(null, arguments);
	    }

	    // This is done to register the method called with moment()
	    // without creating circular dependencies.
	    function setHookCallback (callback) {
	        hookCallback = callback;
	    }

	    function isArray(input) {
	        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
	    }

	    function isDate(input) {
	        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
	    }

	    function map(arr, fn) {
	        var res = [], i;
	        for (i = 0; i < arr.length; ++i) {
	            res.push(fn(arr[i], i));
	        }
	        return res;
	    }

	    function hasOwnProp(a, b) {
	        return Object.prototype.hasOwnProperty.call(a, b);
	    }

	    function extend(a, b) {
	        for (var i in b) {
	            if (hasOwnProp(b, i)) {
	                a[i] = b[i];
	            }
	        }

	        if (hasOwnProp(b, 'toString')) {
	            a.toString = b.toString;
	        }

	        if (hasOwnProp(b, 'valueOf')) {
	            a.valueOf = b.valueOf;
	        }

	        return a;
	    }

	    function create_utc__createUTC (input, format, locale, strict) {
	        return createLocalOrUTC(input, format, locale, strict, true).utc();
	    }

	    function defaultParsingFlags() {
	        // We need to deep clone this object.
	        return {
	            empty           : false,
	            unusedTokens    : [],
	            unusedInput     : [],
	            overflow        : -2,
	            charsLeftOver   : 0,
	            nullInput       : false,
	            invalidMonth    : null,
	            invalidFormat   : false,
	            userInvalidated : false,
	            iso             : false,
	            parsedDateParts : [],
	            meridiem        : null
	        };
	    }

	    function getParsingFlags(m) {
	        if (m._pf == null) {
	            m._pf = defaultParsingFlags();
	        }
	        return m._pf;
	    }

	    var some;
	    if (Array.prototype.some) {
	        some = Array.prototype.some;
	    } else {
	        some = function (fun) {
	            var t = Object(this);
	            var len = t.length >>> 0;

	            for (var i = 0; i < len; i++) {
	                if (i in t && fun.call(this, t[i], i, t)) {
	                    return true;
	                }
	            }

	            return false;
	        };
	    }

	    function valid__isValid(m) {
	        if (m._isValid == null) {
	            var flags = getParsingFlags(m);
	            var parsedParts = some.call(flags.parsedDateParts, function (i) {
	                return i != null;
	            });
	            m._isValid = !isNaN(m._d.getTime()) &&
	                flags.overflow < 0 &&
	                !flags.empty &&
	                !flags.invalidMonth &&
	                !flags.invalidWeekday &&
	                !flags.nullInput &&
	                !flags.invalidFormat &&
	                !flags.userInvalidated &&
	                (!flags.meridiem || (flags.meridiem && parsedParts));

	            if (m._strict) {
	                m._isValid = m._isValid &&
	                    flags.charsLeftOver === 0 &&
	                    flags.unusedTokens.length === 0 &&
	                    flags.bigHour === undefined;
	            }
	        }
	        return m._isValid;
	    }

	    function valid__createInvalid (flags) {
	        var m = create_utc__createUTC(NaN);
	        if (flags != null) {
	            extend(getParsingFlags(m), flags);
	        }
	        else {
	            getParsingFlags(m).userInvalidated = true;
	        }

	        return m;
	    }

	    function isUndefined(input) {
	        return input === void 0;
	    }

	    // Plugins that add properties should also add the key here (null value),
	    // so we can properly clone ourselves.
	    var momentProperties = utils_hooks__hooks.momentProperties = [];

	    function copyConfig(to, from) {
	        var i, prop, val;

	        if (!isUndefined(from._isAMomentObject)) {
	            to._isAMomentObject = from._isAMomentObject;
	        }
	        if (!isUndefined(from._i)) {
	            to._i = from._i;
	        }
	        if (!isUndefined(from._f)) {
	            to._f = from._f;
	        }
	        if (!isUndefined(from._l)) {
	            to._l = from._l;
	        }
	        if (!isUndefined(from._strict)) {
	            to._strict = from._strict;
	        }
	        if (!isUndefined(from._tzm)) {
	            to._tzm = from._tzm;
	        }
	        if (!isUndefined(from._isUTC)) {
	            to._isUTC = from._isUTC;
	        }
	        if (!isUndefined(from._offset)) {
	            to._offset = from._offset;
	        }
	        if (!isUndefined(from._pf)) {
	            to._pf = getParsingFlags(from);
	        }
	        if (!isUndefined(from._locale)) {
	            to._locale = from._locale;
	        }

	        if (momentProperties.length > 0) {
	            for (i in momentProperties) {
	                prop = momentProperties[i];
	                val = from[prop];
	                if (!isUndefined(val)) {
	                    to[prop] = val;
	                }
	            }
	        }

	        return to;
	    }

	    var updateInProgress = false;

	    // Moment prototype object
	    function Moment(config) {
	        copyConfig(this, config);
	        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
	        // Prevent infinite loop in case updateOffset creates new moment
	        // objects.
	        if (updateInProgress === false) {
	            updateInProgress = true;
	            utils_hooks__hooks.updateOffset(this);
	            updateInProgress = false;
	        }
	    }

	    function isMoment (obj) {
	        return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
	    }

	    function absFloor (number) {
	        if (number < 0) {
	            return Math.ceil(number);
	        } else {
	            return Math.floor(number);
	        }
	    }

	    function toInt(argumentForCoercion) {
	        var coercedNumber = +argumentForCoercion,
	            value = 0;

	        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
	            value = absFloor(coercedNumber);
	        }

	        return value;
	    }

	    // compare two arrays, return the number of differences
	    function compareArrays(array1, array2, dontConvert) {
	        var len = Math.min(array1.length, array2.length),
	            lengthDiff = Math.abs(array1.length - array2.length),
	            diffs = 0,
	            i;
	        for (i = 0; i < len; i++) {
	            if ((dontConvert && array1[i] !== array2[i]) ||
	                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
	                diffs++;
	            }
	        }
	        return diffs + lengthDiff;
	    }

	    function warn(msg) {
	        if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
	                (typeof console !==  'undefined') && console.warn) {
	            console.warn('Deprecation warning: ' + msg);
	        }
	    }

	    function deprecate(msg, fn) {
	        var firstTime = true;

	        return extend(function () {
	            if (utils_hooks__hooks.deprecationHandler != null) {
	                utils_hooks__hooks.deprecationHandler(null, msg);
	            }
	            if (firstTime) {
	                warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
	                firstTime = false;
	            }
	            return fn.apply(this, arguments);
	        }, fn);
	    }

	    var deprecations = {};

	    function deprecateSimple(name, msg) {
	        if (utils_hooks__hooks.deprecationHandler != null) {
	            utils_hooks__hooks.deprecationHandler(name, msg);
	        }
	        if (!deprecations[name]) {
	            warn(msg);
	            deprecations[name] = true;
	        }
	    }

	    utils_hooks__hooks.suppressDeprecationWarnings = false;
	    utils_hooks__hooks.deprecationHandler = null;

	    function isFunction(input) {
	        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
	    }

	    function isObject(input) {
	        return Object.prototype.toString.call(input) === '[object Object]';
	    }

	    function locale_set__set (config) {
	        var prop, i;
	        for (i in config) {
	            prop = config[i];
	            if (isFunction(prop)) {
	                this[i] = prop;
	            } else {
	                this['_' + i] = prop;
	            }
	        }
	        this._config = config;
	        // Lenient ordinal parsing accepts just a number in addition to
	        // number + (possibly) stuff coming from _ordinalParseLenient.
	        this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
	    }

	    function mergeConfigs(parentConfig, childConfig) {
	        var res = extend({}, parentConfig), prop;
	        for (prop in childConfig) {
	            if (hasOwnProp(childConfig, prop)) {
	                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
	                    res[prop] = {};
	                    extend(res[prop], parentConfig[prop]);
	                    extend(res[prop], childConfig[prop]);
	                } else if (childConfig[prop] != null) {
	                    res[prop] = childConfig[prop];
	                } else {
	                    delete res[prop];
	                }
	            }
	        }
	        return res;
	    }

	    function Locale(config) {
	        if (config != null) {
	            this.set(config);
	        }
	    }

	    var keys;

	    if (Object.keys) {
	        keys = Object.keys;
	    } else {
	        keys = function (obj) {
	            var i, res = [];
	            for (i in obj) {
	                if (hasOwnProp(obj, i)) {
	                    res.push(i);
	                }
	            }
	            return res;
	        };
	    }

	    // internal storage for locale config files
	    var locales = {};
	    var globalLocale;

	    function normalizeLocale(key) {
	        return key ? key.toLowerCase().replace('_', '-') : key;
	    }

	    // pick the locale from the array
	    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
	    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
	    function chooseLocale(names) {
	        var i = 0, j, next, locale, split;

	        while (i < names.length) {
	            split = normalizeLocale(names[i]).split('-');
	            j = split.length;
	            next = normalizeLocale(names[i + 1]);
	            next = next ? next.split('-') : null;
	            while (j > 0) {
	                locale = loadLocale(split.slice(0, j).join('-'));
	                if (locale) {
	                    return locale;
	                }
	                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
	                    //the next array item is better than a shallower substring of this one
	                    break;
	                }
	                j--;
	            }
	            i++;
	        }
	        return null;
	    }

	    function loadLocale(name) {
	        var oldLocale = null;
	        // TODO: Find a better way to register and load all the locales in Node
	        if (!locales[name] && (typeof module !== 'undefined') &&
	                module && module.exports) {
	            try {
	                oldLocale = globalLocale._abbr;
	                __webpack_require__(216)("./" + name);
	                // because defineLocale currently also sets the global locale, we
	                // want to undo that for lazy loaded locales
	                locale_locales__getSetGlobalLocale(oldLocale);
	            } catch (e) { }
	        }
	        return locales[name];
	    }

	    // This function will load locale and then set the global locale.  If
	    // no arguments are passed in, it will simply return the current global
	    // locale key.
	    function locale_locales__getSetGlobalLocale (key, values) {
	        var data;
	        if (key) {
	            if (isUndefined(values)) {
	                data = locale_locales__getLocale(key);
	            }
	            else {
	                data = defineLocale(key, values);
	            }

	            if (data) {
	                // moment.duration._locale = moment._locale = data;
	                globalLocale = data;
	            }
	        }

	        return globalLocale._abbr;
	    }

	    function defineLocale (name, config) {
	        if (config !== null) {
	            config.abbr = name;
	            if (locales[name] != null) {
	                deprecateSimple('defineLocaleOverride',
	                        'use moment.updateLocale(localeName, config) to change ' +
	                        'an existing locale. moment.defineLocale(localeName, ' +
	                        'config) should only be used for creating a new locale');
	                config = mergeConfigs(locales[name]._config, config);
	            } else if (config.parentLocale != null) {
	                if (locales[config.parentLocale] != null) {
	                    config = mergeConfigs(locales[config.parentLocale]._config, config);
	                } else {
	                    // treat as if there is no base config
	                    deprecateSimple('parentLocaleUndefined',
	                            'specified parentLocale is not defined yet');
	                }
	            }
	            locales[name] = new Locale(config);

	            // backwards compat for now: also set the locale
	            locale_locales__getSetGlobalLocale(name);

	            return locales[name];
	        } else {
	            // useful for testing
	            delete locales[name];
	            return null;
	        }
	    }

	    function updateLocale(name, config) {
	        if (config != null) {
	            var locale;
	            if (locales[name] != null) {
	                config = mergeConfigs(locales[name]._config, config);
	            }
	            locale = new Locale(config);
	            locale.parentLocale = locales[name];
	            locales[name] = locale;

	            // backwards compat for now: also set the locale
	            locale_locales__getSetGlobalLocale(name);
	        } else {
	            // pass null for config to unupdate, useful for tests
	            if (locales[name] != null) {
	                if (locales[name].parentLocale != null) {
	                    locales[name] = locales[name].parentLocale;
	                } else if (locales[name] != null) {
	                    delete locales[name];
	                }
	            }
	        }
	        return locales[name];
	    }

	    // returns locale data
	    function locale_locales__getLocale (key) {
	        var locale;

	        if (key && key._locale && key._locale._abbr) {
	            key = key._locale._abbr;
	        }

	        if (!key) {
	            return globalLocale;
	        }

	        if (!isArray(key)) {
	            //short-circuit everything else
	            locale = loadLocale(key);
	            if (locale) {
	                return locale;
	            }
	            key = [key];
	        }

	        return chooseLocale(key);
	    }

	    function locale_locales__listLocales() {
	        return keys(locales);
	    }

	    var aliases = {};

	    function addUnitAlias (unit, shorthand) {
	        var lowerCase = unit.toLowerCase();
	        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
	    }

	    function normalizeUnits(units) {
	        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
	    }

	    function normalizeObjectUnits(inputObject) {
	        var normalizedInput = {},
	            normalizedProp,
	            prop;

	        for (prop in inputObject) {
	            if (hasOwnProp(inputObject, prop)) {
	                normalizedProp = normalizeUnits(prop);
	                if (normalizedProp) {
	                    normalizedInput[normalizedProp] = inputObject[prop];
	                }
	            }
	        }

	        return normalizedInput;
	    }

	    function makeGetSet (unit, keepTime) {
	        return function (value) {
	            if (value != null) {
	                get_set__set(this, unit, value);
	                utils_hooks__hooks.updateOffset(this, keepTime);
	                return this;
	            } else {
	                return get_set__get(this, unit);
	            }
	        };
	    }

	    function get_set__get (mom, unit) {
	        return mom.isValid() ?
	            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
	    }

	    function get_set__set (mom, unit, value) {
	        if (mom.isValid()) {
	            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
	        }
	    }

	    // MOMENTS

	    function getSet (units, value) {
	        var unit;
	        if (typeof units === 'object') {
	            for (unit in units) {
	                this.set(unit, units[unit]);
	            }
	        } else {
	            units = normalizeUnits(units);
	            if (isFunction(this[units])) {
	                return this[units](value);
	            }
	        }
	        return this;
	    }

	    function zeroFill(number, targetLength, forceSign) {
	        var absNumber = '' + Math.abs(number),
	            zerosToFill = targetLength - absNumber.length,
	            sign = number >= 0;
	        return (sign ? (forceSign ? '+' : '') : '-') +
	            Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
	    }

	    var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;

	    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;

	    var formatFunctions = {};

	    var formatTokenFunctions = {};

	    // token:    'M'
	    // padded:   ['MM', 2]
	    // ordinal:  'Mo'
	    // callback: function () { this.month() + 1 }
	    function addFormatToken (token, padded, ordinal, callback) {
	        var func = callback;
	        if (typeof callback === 'string') {
	            func = function () {
	                return this[callback]();
	            };
	        }
	        if (token) {
	            formatTokenFunctions[token] = func;
	        }
	        if (padded) {
	            formatTokenFunctions[padded[0]] = function () {
	                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
	            };
	        }
	        if (ordinal) {
	            formatTokenFunctions[ordinal] = function () {
	                return this.localeData().ordinal(func.apply(this, arguments), token);
	            };
	        }
	    }

	    function removeFormattingTokens(input) {
	        if (input.match(/\[[\s\S]/)) {
	            return input.replace(/^\[|\]$/g, '');
	        }
	        return input.replace(/\\/g, '');
	    }

	    function makeFormatFunction(format) {
	        var array = format.match(formattingTokens), i, length;

	        for (i = 0, length = array.length; i < length; i++) {
	            if (formatTokenFunctions[array[i]]) {
	                array[i] = formatTokenFunctions[array[i]];
	            } else {
	                array[i] = removeFormattingTokens(array[i]);
	            }
	        }

	        return function (mom) {
	            var output = '', i;
	            for (i = 0; i < length; i++) {
	                output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
	            }
	            return output;
	        };
	    }

	    // format date using native date object
	    function formatMoment(m, format) {
	        if (!m.isValid()) {
	            return m.localeData().invalidDate();
	        }

	        format = expandFormat(format, m.localeData());
	        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);

	        return formatFunctions[format](m);
	    }

	    function expandFormat(format, locale) {
	        var i = 5;

	        function replaceLongDateFormatTokens(input) {
	            return locale.longDateFormat(input) || input;
	        }

	        localFormattingTokens.lastIndex = 0;
	        while (i >= 0 && localFormattingTokens.test(format)) {
	            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
	            localFormattingTokens.lastIndex = 0;
	            i -= 1;
	        }

	        return format;
	    }

	    var match1         = /\d/;            //       0 - 9
	    var match2         = /\d\d/;          //      00 - 99
	    var match3         = /\d{3}/;         //     000 - 999
	    var match4         = /\d{4}/;         //    0000 - 9999
	    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
	    var match1to2      = /\d\d?/;         //       0 - 99
	    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
	    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
	    var match1to3      = /\d{1,3}/;       //       0 - 999
	    var match1to4      = /\d{1,4}/;       //       0 - 9999
	    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999

	    var matchUnsigned  = /\d+/;           //       0 - inf
	    var matchSigned    = /[+-]?\d+/;      //    -inf - inf

	    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
	    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z

	    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123

	    // any word (or two) characters or numbers including two/three word month in arabic.
	    // includes scottish gaelic two word and hyphenated months
	    var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;


	    var regexes = {};

	    function addRegexToken (token, regex, strictRegex) {
	        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
	            return (isStrict && strictRegex) ? strictRegex : regex;
	        };
	    }

	    function getParseRegexForToken (token, config) {
	        if (!hasOwnProp(regexes, token)) {
	            return new RegExp(unescapeFormat(token));
	        }

	        return regexes[token](config._strict, config._locale);
	    }

	    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
	    function unescapeFormat(s) {
	        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
	            return p1 || p2 || p3 || p4;
	        }));
	    }

	    function regexEscape(s) {
	        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
	    }

	    var tokens = {};

	    function addParseToken (token, callback) {
	        var i, func = callback;
	        if (typeof token === 'string') {
	            token = [token];
	        }
	        if (typeof callback === 'number') {
	            func = function (input, array) {
	                array[callback] = toInt(input);
	            };
	        }
	        for (i = 0; i < token.length; i++) {
	            tokens[token[i]] = func;
	        }
	    }

	    function addWeekParseToken (token, callback) {
	        addParseToken(token, function (input, array, config, token) {
	            config._w = config._w || {};
	            callback(input, config._w, config, token);
	        });
	    }

	    function addTimeToArrayFromToken(token, input, config) {
	        if (input != null && hasOwnProp(tokens, token)) {
	            tokens[token](input, config._a, config, token);
	        }
	    }

	    var YEAR = 0;
	    var MONTH = 1;
	    var DATE = 2;
	    var HOUR = 3;
	    var MINUTE = 4;
	    var SECOND = 5;
	    var MILLISECOND = 6;
	    var WEEK = 7;
	    var WEEKDAY = 8;

	    var indexOf;

	    if (Array.prototype.indexOf) {
	        indexOf = Array.prototype.indexOf;
	    } else {
	        indexOf = function (o) {
	            // I know
	            var i;
	            for (i = 0; i < this.length; ++i) {
	                if (this[i] === o) {
	                    return i;
	                }
	            }
	            return -1;
	        };
	    }

	    function daysInMonth(year, month) {
	        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
	    }

	    // FORMATTING

	    addFormatToken('M', ['MM', 2], 'Mo', function () {
	        return this.month() + 1;
	    });

	    addFormatToken('MMM', 0, 0, function (format) {
	        return this.localeData().monthsShort(this, format);
	    });

	    addFormatToken('MMMM', 0, 0, function (format) {
	        return this.localeData().months(this, format);
	    });

	    // ALIASES

	    addUnitAlias('month', 'M');

	    // PARSING

	    addRegexToken('M',    match1to2);
	    addRegexToken('MM',   match1to2, match2);
	    addRegexToken('MMM',  function (isStrict, locale) {
	        return locale.monthsShortRegex(isStrict);
	    });
	    addRegexToken('MMMM', function (isStrict, locale) {
	        return locale.monthsRegex(isStrict);
	    });

	    addParseToken(['M', 'MM'], function (input, array) {
	        array[MONTH] = toInt(input) - 1;
	    });

	    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
	        var month = config._locale.monthsParse(input, token, config._strict);
	        // if we didn't find a month name, mark the date as invalid.
	        if (month != null) {
	            array[MONTH] = month;
	        } else {
	            getParsingFlags(config).invalidMonth = input;
	        }
	    });

	    // LOCALES

	    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
	    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
	    function localeMonths (m, format) {
	        return isArray(this._months) ? this._months[m.month()] :
	            this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
	    }

	    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
	    function localeMonthsShort (m, format) {
	        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
	            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
	    }

	    function units_month__handleStrictParse(monthName, format, strict) {
	        var i, ii, mom, llc = monthName.toLocaleLowerCase();
	        if (!this._monthsParse) {
	            // this is not used
	            this._monthsParse = [];
	            this._longMonthsParse = [];
	            this._shortMonthsParse = [];
	            for (i = 0; i < 12; ++i) {
	                mom = create_utc__createUTC([2000, i]);
	                this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
	                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
	            }
	        }

	        if (strict) {
	            if (format === 'MMM') {
	                ii = indexOf.call(this._shortMonthsParse, llc);
	                return ii !== -1 ? ii : null;
	            } else {
	                ii = indexOf.call(this._longMonthsParse, llc);
	                return ii !== -1 ? ii : null;
	            }
	        } else {
	            if (format === 'MMM') {
	                ii = indexOf.call(this._shortMonthsParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._longMonthsParse, llc);
	                return ii !== -1 ? ii : null;
	            } else {
	                ii = indexOf.call(this._longMonthsParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._shortMonthsParse, llc);
	                return ii !== -1 ? ii : null;
	            }
	        }
	    }

	    function localeMonthsParse (monthName, format, strict) {
	        var i, mom, regex;

	        if (this._monthsParseExact) {
	            return units_month__handleStrictParse.call(this, monthName, format, strict);
	        }

	        if (!this._monthsParse) {
	            this._monthsParse = [];
	            this._longMonthsParse = [];
	            this._shortMonthsParse = [];
	        }

	        // TODO: add sorting
	        // Sorting makes sure if one month (or abbr) is a prefix of another
	        // see sorting in computeMonthsParse
	        for (i = 0; i < 12; i++) {
	            // make the regex if we don't have it already
	            mom = create_utc__createUTC([2000, i]);
	            if (strict && !this._longMonthsParse[i]) {
	                this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
	                this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
	            }
	            if (!strict && !this._monthsParse[i]) {
	                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
	                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
	            }
	            // test the regex
	            if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
	                return i;
	            } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
	                return i;
	            } else if (!strict && this._monthsParse[i].test(monthName)) {
	                return i;
	            }
	        }
	    }

	    // MOMENTS

	    function setMonth (mom, value) {
	        var dayOfMonth;

	        if (!mom.isValid()) {
	            // No op
	            return mom;
	        }

	        if (typeof value === 'string') {
	            if (/^\d+$/.test(value)) {
	                value = toInt(value);
	            } else {
	                value = mom.localeData().monthsParse(value);
	                // TODO: Another silent failure?
	                if (typeof value !== 'number') {
	                    return mom;
	                }
	            }
	        }

	        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
	        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
	        return mom;
	    }

	    function getSetMonth (value) {
	        if (value != null) {
	            setMonth(this, value);
	            utils_hooks__hooks.updateOffset(this, true);
	            return this;
	        } else {
	            return get_set__get(this, 'Month');
	        }
	    }

	    function getDaysInMonth () {
	        return daysInMonth(this.year(), this.month());
	    }

	    var defaultMonthsShortRegex = matchWord;
	    function monthsShortRegex (isStrict) {
	        if (this._monthsParseExact) {
	            if (!hasOwnProp(this, '_monthsRegex')) {
	                computeMonthsParse.call(this);
	            }
	            if (isStrict) {
	                return this._monthsShortStrictRegex;
	            } else {
	                return this._monthsShortRegex;
	            }
	        } else {
	            return this._monthsShortStrictRegex && isStrict ?
	                this._monthsShortStrictRegex : this._monthsShortRegex;
	        }
	    }

	    var defaultMonthsRegex = matchWord;
	    function monthsRegex (isStrict) {
	        if (this._monthsParseExact) {
	            if (!hasOwnProp(this, '_monthsRegex')) {
	                computeMonthsParse.call(this);
	            }
	            if (isStrict) {
	                return this._monthsStrictRegex;
	            } else {
	                return this._monthsRegex;
	            }
	        } else {
	            return this._monthsStrictRegex && isStrict ?
	                this._monthsStrictRegex : this._monthsRegex;
	        }
	    }

	    function computeMonthsParse () {
	        function cmpLenRev(a, b) {
	            return b.length - a.length;
	        }

	        var shortPieces = [], longPieces = [], mixedPieces = [],
	            i, mom;
	        for (i = 0; i < 12; i++) {
	            // make the regex if we don't have it already
	            mom = create_utc__createUTC([2000, i]);
	            shortPieces.push(this.monthsShort(mom, ''));
	            longPieces.push(this.months(mom, ''));
	            mixedPieces.push(this.months(mom, ''));
	            mixedPieces.push(this.monthsShort(mom, ''));
	        }
	        // Sorting makes sure if one month (or abbr) is a prefix of another it
	        // will match the longer piece.
	        shortPieces.sort(cmpLenRev);
	        longPieces.sort(cmpLenRev);
	        mixedPieces.sort(cmpLenRev);
	        for (i = 0; i < 12; i++) {
	            shortPieces[i] = regexEscape(shortPieces[i]);
	            longPieces[i] = regexEscape(longPieces[i]);
	            mixedPieces[i] = regexEscape(mixedPieces[i]);
	        }

	        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
	        this._monthsShortRegex = this._monthsRegex;
	        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
	        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
	    }

	    function checkOverflow (m) {
	        var overflow;
	        var a = m._a;

	        if (a && getParsingFlags(m).overflow === -2) {
	            overflow =
	                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
	                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
	                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
	                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
	                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
	                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
	                -1;

	            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
	                overflow = DATE;
	            }
	            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
	                overflow = WEEK;
	            }
	            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
	                overflow = WEEKDAY;
	            }

	            getParsingFlags(m).overflow = overflow;
	        }

	        return m;
	    }

	    // iso 8601 regex
	    // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
	    var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
	    var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;

	    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;

	    var isoDates = [
	        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
	        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
	        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
	        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
	        ['YYYY-DDD', /\d{4}-\d{3}/],
	        ['YYYY-MM', /\d{4}-\d\d/, false],
	        ['YYYYYYMMDD', /[+-]\d{10}/],
	        ['YYYYMMDD', /\d{8}/],
	        // YYYYMM is NOT allowed by the standard
	        ['GGGG[W]WWE', /\d{4}W\d{3}/],
	        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
	        ['YYYYDDD', /\d{7}/]
	    ];

	    // iso time formats and regexes
	    var isoTimes = [
	        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
	        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
	        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
	        ['HH:mm', /\d\d:\d\d/],
	        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
	        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
	        ['HHmmss', /\d\d\d\d\d\d/],
	        ['HHmm', /\d\d\d\d/],
	        ['HH', /\d\d/]
	    ];

	    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;

	    // date from iso format
	    function configFromISO(config) {
	        var i, l,
	            string = config._i,
	            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
	            allowTime, dateFormat, timeFormat, tzFormat;

	        if (match) {
	            getParsingFlags(config).iso = true;

	            for (i = 0, l = isoDates.length; i < l; i++) {
	                if (isoDates[i][1].exec(match[1])) {
	                    dateFormat = isoDates[i][0];
	                    allowTime = isoDates[i][2] !== false;
	                    break;
	                }
	            }
	            if (dateFormat == null) {
	                config._isValid = false;
	                return;
	            }
	            if (match[3]) {
	                for (i = 0, l = isoTimes.length; i < l; i++) {
	                    if (isoTimes[i][1].exec(match[3])) {
	                        // match[2] should be 'T' or space
	                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
	                        break;
	                    }
	                }
	                if (timeFormat == null) {
	                    config._isValid = false;
	                    return;
	                }
	            }
	            if (!allowTime && timeFormat != null) {
	                config._isValid = false;
	                return;
	            }
	            if (match[4]) {
	                if (tzRegex.exec(match[4])) {
	                    tzFormat = 'Z';
	                } else {
	                    config._isValid = false;
	                    return;
	                }
	            }
	            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
	            configFromStringAndFormat(config);
	        } else {
	            config._isValid = false;
	        }
	    }

	    // date from iso format or fallback
	    function configFromString(config) {
	        var matched = aspNetJsonRegex.exec(config._i);

	        if (matched !== null) {
	            config._d = new Date(+matched[1]);
	            return;
	        }

	        configFromISO(config);
	        if (config._isValid === false) {
	            delete config._isValid;
	            utils_hooks__hooks.createFromInputFallback(config);
	        }
	    }

	    utils_hooks__hooks.createFromInputFallback = deprecate(
	        'moment construction falls back to js Date. This is ' +
	        'discouraged and will be removed in upcoming major ' +
	        'release. Please refer to ' +
	        'https://github.com/moment/moment/issues/1407 for more info.',
	        function (config) {
	            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
	        }
	    );

	    function createDate (y, m, d, h, M, s, ms) {
	        //can't just apply() to create a date:
	        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
	        var date = new Date(y, m, d, h, M, s, ms);

	        //the date constructor remaps years 0-99 to 1900-1999
	        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
	            date.setFullYear(y);
	        }
	        return date;
	    }

	    function createUTCDate (y) {
	        var date = new Date(Date.UTC.apply(null, arguments));

	        //the Date.UTC function remaps years 0-99 to 1900-1999
	        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
	            date.setUTCFullYear(y);
	        }
	        return date;
	    }

	    // FORMATTING

	    addFormatToken('Y', 0, 0, function () {
	        var y = this.year();
	        return y <= 9999 ? '' + y : '+' + y;
	    });

	    addFormatToken(0, ['YY', 2], 0, function () {
	        return this.year() % 100;
	    });

	    addFormatToken(0, ['YYYY',   4],       0, 'year');
	    addFormatToken(0, ['YYYYY',  5],       0, 'year');
	    addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');

	    // ALIASES

	    addUnitAlias('year', 'y');

	    // PARSING

	    addRegexToken('Y',      matchSigned);
	    addRegexToken('YY',     match1to2, match2);
	    addRegexToken('YYYY',   match1to4, match4);
	    addRegexToken('YYYYY',  match1to6, match6);
	    addRegexToken('YYYYYY', match1to6, match6);

	    addParseToken(['YYYYY', 'YYYYYY'], YEAR);
	    addParseToken('YYYY', function (input, array) {
	        array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
	    });
	    addParseToken('YY', function (input, array) {
	        array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
	    });
	    addParseToken('Y', function (input, array) {
	        array[YEAR] = parseInt(input, 10);
	    });

	    // HELPERS

	    function daysInYear(year) {
	        return isLeapYear(year) ? 366 : 365;
	    }

	    function isLeapYear(year) {
	        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
	    }

	    // HOOKS

	    utils_hooks__hooks.parseTwoDigitYear = function (input) {
	        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
	    };

	    // MOMENTS

	    var getSetYear = makeGetSet('FullYear', true);

	    function getIsLeapYear () {
	        return isLeapYear(this.year());
	    }

	    // start-of-first-week - start-of-year
	    function firstWeekOffset(year, dow, doy) {
	        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
	            fwd = 7 + dow - doy,
	            // first-week day local weekday -- which local weekday is fwd
	            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;

	        return -fwdlw + fwd - 1;
	    }

	    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
	    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
	        var localWeekday = (7 + weekday - dow) % 7,
	            weekOffset = firstWeekOffset(year, dow, doy),
	            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
	            resYear, resDayOfYear;

	        if (dayOfYear <= 0) {
	            resYear = year - 1;
	            resDayOfYear = daysInYear(resYear) + dayOfYear;
	        } else if (dayOfYear > daysInYear(year)) {
	            resYear = year + 1;
	            resDayOfYear = dayOfYear - daysInYear(year);
	        } else {
	            resYear = year;
	            resDayOfYear = dayOfYear;
	        }

	        return {
	            year: resYear,
	            dayOfYear: resDayOfYear
	        };
	    }

	    function weekOfYear(mom, dow, doy) {
	        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
	            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
	            resWeek, resYear;

	        if (week < 1) {
	            resYear = mom.year() - 1;
	            resWeek = week + weeksInYear(resYear, dow, doy);
	        } else if (week > weeksInYear(mom.year(), dow, doy)) {
	            resWeek = week - weeksInYear(mom.year(), dow, doy);
	            resYear = mom.year() + 1;
	        } else {
	            resYear = mom.year();
	            resWeek = week;
	        }

	        return {
	            week: resWeek,
	            year: resYear
	        };
	    }

	    function weeksInYear(year, dow, doy) {
	        var weekOffset = firstWeekOffset(year, dow, doy),
	            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
	        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
	    }

	    // Pick the first defined of two or three arguments.
	    function defaults(a, b, c) {
	        if (a != null) {
	            return a;
	        }
	        if (b != null) {
	            return b;
	        }
	        return c;
	    }

	    function currentDateArray(config) {
	        // hooks is actually the exported moment object
	        var nowValue = new Date(utils_hooks__hooks.now());
	        if (config._useUTC) {
	            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
	        }
	        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
	    }

	    // convert an array to a date.
	    // the array should mirror the parameters below
	    // note: all values past the year are optional and will default to the lowest possible value.
	    // [year, month, day , hour, minute, second, millisecond]
	    function configFromArray (config) {
	        var i, date, input = [], currentDate, yearToUse;

	        if (config._d) {
	            return;
	        }

	        currentDate = currentDateArray(config);

	        //compute day of the year from weeks and weekdays
	        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
	            dayOfYearFromWeekInfo(config);
	        }

	        //if the day of the year is set, figure out what it is
	        if (config._dayOfYear) {
	            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);

	            if (config._dayOfYear > daysInYear(yearToUse)) {
	                getParsingFlags(config)._overflowDayOfYear = true;
	            }

	            date = createUTCDate(yearToUse, 0, config._dayOfYear);
	            config._a[MONTH] = date.getUTCMonth();
	            config._a[DATE] = date.getUTCDate();
	        }

	        // Default to current date.
	        // * if no year, month, day of month are given, default to today
	        // * if day of month is given, default month and year
	        // * if month is given, default only year
	        // * if year is given, don't default anything
	        for (i = 0; i < 3 && config._a[i] == null; ++i) {
	            config._a[i] = input[i] = currentDate[i];
	        }

	        // Zero out whatever was not defaulted, including time
	        for (; i < 7; i++) {
	            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
	        }

	        // Check for 24:00:00.000
	        if (config._a[HOUR] === 24 &&
	                config._a[MINUTE] === 0 &&
	                config._a[SECOND] === 0 &&
	                config._a[MILLISECOND] === 0) {
	            config._nextDay = true;
	            config._a[HOUR] = 0;
	        }

	        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
	        // Apply timezone offset from input. The actual utcOffset can be changed
	        // with parseZone.
	        if (config._tzm != null) {
	            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
	        }

	        if (config._nextDay) {
	            config._a[HOUR] = 24;
	        }
	    }

	    function dayOfYearFromWeekInfo(config) {
	        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;

	        w = config._w;
	        if (w.GG != null || w.W != null || w.E != null) {
	            dow = 1;
	            doy = 4;

	            // TODO: We need to take the current isoWeekYear, but that depends on
	            // how we interpret now (local, utc, fixed offset). So create
	            // a now version of current config (take local/utc/offset flags, and
	            // create now).
	            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
	            week = defaults(w.W, 1);
	            weekday = defaults(w.E, 1);
	            if (weekday < 1 || weekday > 7) {
	                weekdayOverflow = true;
	            }
	        } else {
	            dow = config._locale._week.dow;
	            doy = config._locale._week.doy;

	            weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
	            week = defaults(w.w, 1);

	            if (w.d != null) {
	                // weekday -- low day numbers are considered next week
	                weekday = w.d;
	                if (weekday < 0 || weekday > 6) {
	                    weekdayOverflow = true;
	                }
	            } else if (w.e != null) {
	                // local weekday -- counting starts from begining of week
	                weekday = w.e + dow;
	                if (w.e < 0 || w.e > 6) {
	                    weekdayOverflow = true;
	                }
	            } else {
	                // default to begining of week
	                weekday = dow;
	            }
	        }
	        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
	            getParsingFlags(config)._overflowWeeks = true;
	        } else if (weekdayOverflow != null) {
	            getParsingFlags(config)._overflowWeekday = true;
	        } else {
	            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
	            config._a[YEAR] = temp.year;
	            config._dayOfYear = temp.dayOfYear;
	        }
	    }

	    // constant that refers to the ISO standard
	    utils_hooks__hooks.ISO_8601 = function () {};

	    // date from string and format string
	    function configFromStringAndFormat(config) {
	        // TODO: Move this to another part of the creation flow to prevent circular deps
	        if (config._f === utils_hooks__hooks.ISO_8601) {
	            configFromISO(config);
	            return;
	        }

	        config._a = [];
	        getParsingFlags(config).empty = true;

	        // This array is used to make a Date, either with `new Date` or `Date.UTC`
	        var string = '' + config._i,
	            i, parsedInput, tokens, token, skipped,
	            stringLength = string.length,
	            totalParsedInputLength = 0;

	        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];

	        for (i = 0; i < tokens.length; i++) {
	            token = tokens[i];
	            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
	            // console.log('token', token, 'parsedInput', parsedInput,
	            //         'regex', getParseRegexForToken(token, config));
	            if (parsedInput) {
	                skipped = string.substr(0, string.indexOf(parsedInput));
	                if (skipped.length > 0) {
	                    getParsingFlags(config).unusedInput.push(skipped);
	                }
	                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
	                totalParsedInputLength += parsedInput.length;
	            }
	            // don't parse if it's not a known token
	            if (formatTokenFunctions[token]) {
	                if (parsedInput) {
	                    getParsingFlags(config).empty = false;
	                }
	                else {
	                    getParsingFlags(config).unusedTokens.push(token);
	                }
	                addTimeToArrayFromToken(token, parsedInput, config);
	            }
	            else if (config._strict && !parsedInput) {
	                getParsingFlags(config).unusedTokens.push(token);
	            }
	        }

	        // add remaining unparsed input length to the string
	        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
	        if (string.length > 0) {
	            getParsingFlags(config).unusedInput.push(string);
	        }

	        // clear _12h flag if hour is <= 12
	        if (getParsingFlags(config).bigHour === true &&
	                config._a[HOUR] <= 12 &&
	                config._a[HOUR] > 0) {
	            getParsingFlags(config).bigHour = undefined;
	        }

	        getParsingFlags(config).parsedDateParts = config._a.slice(0);
	        getParsingFlags(config).meridiem = config._meridiem;
	        // handle meridiem
	        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);

	        configFromArray(config);
	        checkOverflow(config);
	    }


	    function meridiemFixWrap (locale, hour, meridiem) {
	        var isPm;

	        if (meridiem == null) {
	            // nothing to do
	            return hour;
	        }
	        if (locale.meridiemHour != null) {
	            return locale.meridiemHour(hour, meridiem);
	        } else if (locale.isPM != null) {
	            // Fallback
	            isPm = locale.isPM(meridiem);
	            if (isPm && hour < 12) {
	                hour += 12;
	            }
	            if (!isPm && hour === 12) {
	                hour = 0;
	            }
	            return hour;
	        } else {
	            // this is not supposed to happen
	            return hour;
	        }
	    }

	    // date from string and array of format strings
	    function configFromStringAndArray(config) {
	        var tempConfig,
	            bestMoment,

	            scoreToBeat,
	            i,
	            currentScore;

	        if (config._f.length === 0) {
	            getParsingFlags(config).invalidFormat = true;
	            config._d = new Date(NaN);
	            return;
	        }

	        for (i = 0; i < config._f.length; i++) {
	            currentScore = 0;
	            tempConfig = copyConfig({}, config);
	            if (config._useUTC != null) {
	                tempConfig._useUTC = config._useUTC;
	            }
	            tempConfig._f = config._f[i];
	            configFromStringAndFormat(tempConfig);

	            if (!valid__isValid(tempConfig)) {
	                continue;
	            }

	            // if there is any input that was not parsed add a penalty for that format
	            currentScore += getParsingFlags(tempConfig).charsLeftOver;

	            //or tokens
	            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;

	            getParsingFlags(tempConfig).score = currentScore;

	            if (scoreToBeat == null || currentScore < scoreToBeat) {
	                scoreToBeat = currentScore;
	                bestMoment = tempConfig;
	            }
	        }

	        extend(config, bestMoment || tempConfig);
	    }

	    function configFromObject(config) {
	        if (config._d) {
	            return;
	        }

	        var i = normalizeObjectUnits(config._i);
	        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
	            return obj && parseInt(obj, 10);
	        });

	        configFromArray(config);
	    }

	    function createFromConfig (config) {
	        var res = new Moment(checkOverflow(prepareConfig(config)));
	        if (res._nextDay) {
	            // Adding is smart enough around DST
	            res.add(1, 'd');
	            res._nextDay = undefined;
	        }

	        return res;
	    }

	    function prepareConfig (config) {
	        var input = config._i,
	            format = config._f;

	        config._locale = config._locale || locale_locales__getLocale(config._l);

	        if (input === null || (format === undefined && input === '')) {
	            return valid__createInvalid({nullInput: true});
	        }

	        if (typeof input === 'string') {
	            config._i = input = config._locale.preparse(input);
	        }

	        if (isMoment(input)) {
	            return new Moment(checkOverflow(input));
	        } else if (isArray(format)) {
	            configFromStringAndArray(config);
	        } else if (format) {
	            configFromStringAndFormat(config);
	        } else if (isDate(input)) {
	            config._d = input;
	        } else {
	            configFromInput(config);
	        }

	        if (!valid__isValid(config)) {
	            config._d = null;
	        }

	        return config;
	    }

	    function configFromInput(config) {
	        var input = config._i;
	        if (input === undefined) {
	            config._d = new Date(utils_hooks__hooks.now());
	        } else if (isDate(input)) {
	            config._d = new Date(input.valueOf());
	        } else if (typeof input === 'string') {
	            configFromString(config);
	        } else if (isArray(input)) {
	            config._a = map(input.slice(0), function (obj) {
	                return parseInt(obj, 10);
	            });
	            configFromArray(config);
	        } else if (typeof(input) === 'object') {
	            configFromObject(config);
	        } else if (typeof(input) === 'number') {
	            // from milliseconds
	            config._d = new Date(input);
	        } else {
	            utils_hooks__hooks.createFromInputFallback(config);
	        }
	    }

	    function createLocalOrUTC (input, format, locale, strict, isUTC) {
	        var c = {};

	        if (typeof(locale) === 'boolean') {
	            strict = locale;
	            locale = undefined;
	        }
	        // object construction must be done this way.
	        // https://github.com/moment/moment/issues/1423
	        c._isAMomentObject = true;
	        c._useUTC = c._isUTC = isUTC;
	        c._l = locale;
	        c._i = input;
	        c._f = format;
	        c._strict = strict;

	        return createFromConfig(c);
	    }

	    function local__createLocal (input, format, locale, strict) {
	        return createLocalOrUTC(input, format, locale, strict, false);
	    }

	    var prototypeMin = deprecate(
	         'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
	         function () {
	             var other = local__createLocal.apply(null, arguments);
	             if (this.isValid() && other.isValid()) {
	                 return other < this ? this : other;
	             } else {
	                 return valid__createInvalid();
	             }
	         }
	     );

	    var prototypeMax = deprecate(
	        'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
	        function () {
	            var other = local__createLocal.apply(null, arguments);
	            if (this.isValid() && other.isValid()) {
	                return other > this ? this : other;
	            } else {
	                return valid__createInvalid();
	            }
	        }
	    );

	    // Pick a moment m from moments so that m[fn](other) is true for all
	    // other. This relies on the function fn to be transitive.
	    //
	    // moments should either be an array of moment objects or an array, whose
	    // first element is an array of moment objects.
	    function pickBy(fn, moments) {
	        var res, i;
	        if (moments.length === 1 && isArray(moments[0])) {
	            moments = moments[0];
	        }
	        if (!moments.length) {
	            return local__createLocal();
	        }
	        res = moments[0];
	        for (i = 1; i < moments.length; ++i) {
	            if (!moments[i].isValid() || moments[i][fn](res)) {
	                res = moments[i];
	            }
	        }
	        return res;
	    }

	    // TODO: Use [].sort instead?
	    function min () {
	        var args = [].slice.call(arguments, 0);

	        return pickBy('isBefore', args);
	    }

	    function max () {
	        var args = [].slice.call(arguments, 0);

	        return pickBy('isAfter', args);
	    }

	    var now = function () {
	        return Date.now ? Date.now() : +(new Date());
	    };

	    function Duration (duration) {
	        var normalizedInput = normalizeObjectUnits(duration),
	            years = normalizedInput.year || 0,
	            quarters = normalizedInput.quarter || 0,
	            months = normalizedInput.month || 0,
	            weeks = normalizedInput.week || 0,
	            days = normalizedInput.day || 0,
	            hours = normalizedInput.hour || 0,
	            minutes = normalizedInput.minute || 0,
	            seconds = normalizedInput.second || 0,
	            milliseconds = normalizedInput.millisecond || 0;

	        // representation for dateAddRemove
	        this._milliseconds = +milliseconds +
	            seconds * 1e3 + // 1000
	            minutes * 6e4 + // 1000 * 60
	            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
	        // Because of dateAddRemove treats 24 hours as different from a
	        // day when working around DST, we need to store them separately
	        this._days = +days +
	            weeks * 7;
	        // It is impossible translate months into days without knowing
	        // which months you are are talking about, so we have to store
	        // it separately.
	        this._months = +months +
	            quarters * 3 +
	            years * 12;

	        this._data = {};

	        this._locale = locale_locales__getLocale();

	        this._bubble();
	    }

	    function isDuration (obj) {
	        return obj instanceof Duration;
	    }

	    // FORMATTING

	    function offset (token, separator) {
	        addFormatToken(token, 0, 0, function () {
	            var offset = this.utcOffset();
	            var sign = '+';
	            if (offset < 0) {
	                offset = -offset;
	                sign = '-';
	            }
	            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
	        });
	    }

	    offset('Z', ':');
	    offset('ZZ', '');

	    // PARSING

	    addRegexToken('Z',  matchShortOffset);
	    addRegexToken('ZZ', matchShortOffset);
	    addParseToken(['Z', 'ZZ'], function (input, array, config) {
	        config._useUTC = true;
	        config._tzm = offsetFromString(matchShortOffset, input);
	    });

	    // HELPERS

	    // timezone chunker
	    // '+10:00' > ['10',  '00']
	    // '-1530'  > ['-15', '30']
	    var chunkOffset = /([\+\-]|\d\d)/gi;

	    function offsetFromString(matcher, string) {
	        var matches = ((string || '').match(matcher) || []);
	        var chunk   = matches[matches.length - 1] || [];
	        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
	        var minutes = +(parts[1] * 60) + toInt(parts[2]);

	        return parts[0] === '+' ? minutes : -minutes;
	    }

	    // Return a moment from input, that is local/utc/zone equivalent to model.
	    function cloneWithOffset(input, model) {
	        var res, diff;
	        if (model._isUTC) {
	            res = model.clone();
	            diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
	            // Use low-level api, because this fn is low-level api.
	            res._d.setTime(res._d.valueOf() + diff);
	            utils_hooks__hooks.updateOffset(res, false);
	            return res;
	        } else {
	            return local__createLocal(input).local();
	        }
	    }

	    function getDateOffset (m) {
	        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
	        // https://github.com/moment/moment/pull/1871
	        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
	    }

	    // HOOKS

	    // This function will be called whenever a moment is mutated.
	    // It is intended to keep the offset in sync with the timezone.
	    utils_hooks__hooks.updateOffset = function () {};

	    // MOMENTS

	    // keepLocalTime = true means only change the timezone, without
	    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
	    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
	    // +0200, so we adjust the time as needed, to be valid.
	    //
	    // Keeping the time actually adds/subtracts (one hour)
	    // from the actual represented time. That is why we call updateOffset
	    // a second time. In case it wants us to change the offset again
	    // _changeInProgress == true case, then we have to adjust, because
	    // there is no such time in the given timezone.
	    function getSetOffset (input, keepLocalTime) {
	        var offset = this._offset || 0,
	            localAdjust;
	        if (!this.isValid()) {
	            return input != null ? this : NaN;
	        }
	        if (input != null) {
	            if (typeof input === 'string') {
	                input = offsetFromString(matchShortOffset, input);
	            } else if (Math.abs(input) < 16) {
	                input = input * 60;
	            }
	            if (!this._isUTC && keepLocalTime) {
	                localAdjust = getDateOffset(this);
	            }
	            this._offset = input;
	            this._isUTC = true;
	            if (localAdjust != null) {
	                this.add(localAdjust, 'm');
	            }
	            if (offset !== input) {
	                if (!keepLocalTime || this._changeInProgress) {
	                    add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
	                } else if (!this._changeInProgress) {
	                    this._changeInProgress = true;
	                    utils_hooks__hooks.updateOffset(this, true);
	                    this._changeInProgress = null;
	                }
	            }
	            return this;
	        } else {
	            return this._isUTC ? offset : getDateOffset(this);
	        }
	    }

	    function getSetZone (input, keepLocalTime) {
	        if (input != null) {
	            if (typeof input !== 'string') {
	                input = -input;
	            }

	            this.utcOffset(input, keepLocalTime);

	            return this;
	        } else {
	            return -this.utcOffset();
	        }
	    }

	    function setOffsetToUTC (keepLocalTime) {
	        return this.utcOffset(0, keepLocalTime);
	    }

	    function setOffsetToLocal (keepLocalTime) {
	        if (this._isUTC) {
	            this.utcOffset(0, keepLocalTime);
	            this._isUTC = false;

	            if (keepLocalTime) {
	                this.subtract(getDateOffset(this), 'm');
	            }
	        }
	        return this;
	    }

	    function setOffsetToParsedOffset () {
	        if (this._tzm) {
	            this.utcOffset(this._tzm);
	        } else if (typeof this._i === 'string') {
	            this.utcOffset(offsetFromString(matchOffset, this._i));
	        }
	        return this;
	    }

	    function hasAlignedHourOffset (input) {
	        if (!this.isValid()) {
	            return false;
	        }
	        input = input ? local__createLocal(input).utcOffset() : 0;

	        return (this.utcOffset() - input) % 60 === 0;
	    }

	    function isDaylightSavingTime () {
	        return (
	            this.utcOffset() > this.clone().month(0).utcOffset() ||
	            this.utcOffset() > this.clone().month(5).utcOffset()
	        );
	    }

	    function isDaylightSavingTimeShifted () {
	        if (!isUndefined(this._isDSTShifted)) {
	            return this._isDSTShifted;
	        }

	        var c = {};

	        copyConfig(c, this);
	        c = prepareConfig(c);

	        if (c._a) {
	            var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
	            this._isDSTShifted = this.isValid() &&
	                compareArrays(c._a, other.toArray()) > 0;
	        } else {
	            this._isDSTShifted = false;
	        }

	        return this._isDSTShifted;
	    }

	    function isLocal () {
	        return this.isValid() ? !this._isUTC : false;
	    }

	    function isUtcOffset () {
	        return this.isValid() ? this._isUTC : false;
	    }

	    function isUtc () {
	        return this.isValid() ? this._isUTC && this._offset === 0 : false;
	    }

	    // ASP.NET json date format regex
	    var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;

	    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
	    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
	    // and further modified to allow for strings containing both week and day
	    var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;

	    function create__createDuration (input, key) {
	        var duration = input,
	            // matching against regexp is expensive, do it on demand
	            match = null,
	            sign,
	            ret,
	            diffRes;

	        if (isDuration(input)) {
	            duration = {
	                ms : input._milliseconds,
	                d  : input._days,
	                M  : input._months
	            };
	        } else if (typeof input === 'number') {
	            duration = {};
	            if (key) {
	                duration[key] = input;
	            } else {
	                duration.milliseconds = input;
	            }
	        } else if (!!(match = aspNetRegex.exec(input))) {
	            sign = (match[1] === '-') ? -1 : 1;
	            duration = {
	                y  : 0,
	                d  : toInt(match[DATE])        * sign,
	                h  : toInt(match[HOUR])        * sign,
	                m  : toInt(match[MINUTE])      * sign,
	                s  : toInt(match[SECOND])      * sign,
	                ms : toInt(match[MILLISECOND]) * sign
	            };
	        } else if (!!(match = isoRegex.exec(input))) {
	            sign = (match[1] === '-') ? -1 : 1;
	            duration = {
	                y : parseIso(match[2], sign),
	                M : parseIso(match[3], sign),
	                w : parseIso(match[4], sign),
	                d : parseIso(match[5], sign),
	                h : parseIso(match[6], sign),
	                m : parseIso(match[7], sign),
	                s : parseIso(match[8], sign)
	            };
	        } else if (duration == null) {// checks for null or undefined
	            duration = {};
	        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
	            diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));

	            duration = {};
	            duration.ms = diffRes.milliseconds;
	            duration.M = diffRes.months;
	        }

	        ret = new Duration(duration);

	        if (isDuration(input) && hasOwnProp(input, '_locale')) {
	            ret._locale = input._locale;
	        }

	        return ret;
	    }

	    create__createDuration.fn = Duration.prototype;

	    function parseIso (inp, sign) {
	        // We'd normally use ~~inp for this, but unfortunately it also
	        // converts floats to ints.
	        // inp may be undefined, so careful calling replace on it.
	        var res = inp && parseFloat(inp.replace(',', '.'));
	        // apply sign while we're at it
	        return (isNaN(res) ? 0 : res) * sign;
	    }

	    function positiveMomentsDifference(base, other) {
	        var res = {milliseconds: 0, months: 0};

	        res.months = other.month() - base.month() +
	            (other.year() - base.year()) * 12;
	        if (base.clone().add(res.months, 'M').isAfter(other)) {
	            --res.months;
	        }

	        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));

	        return res;
	    }

	    function momentsDifference(base, other) {
	        var res;
	        if (!(base.isValid() && other.isValid())) {
	            return {milliseconds: 0, months: 0};
	        }

	        other = cloneWithOffset(other, base);
	        if (base.isBefore(other)) {
	            res = positiveMomentsDifference(base, other);
	        } else {
	            res = positiveMomentsDifference(other, base);
	            res.milliseconds = -res.milliseconds;
	            res.months = -res.months;
	        }

	        return res;
	    }

	    function absRound (number) {
	        if (number < 0) {
	            return Math.round(-1 * number) * -1;
	        } else {
	            return Math.round(number);
	        }
	    }

	    // TODO: remove 'name' arg after deprecation is removed
	    function createAdder(direction, name) {
	        return function (val, period) {
	            var dur, tmp;
	            //invert the arguments, but complain about it
	            if (period !== null && !isNaN(+period)) {
	                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
	                tmp = val; val = period; period = tmp;
	            }

	            val = typeof val === 'string' ? +val : val;
	            dur = create__createDuration(val, period);
	            add_subtract__addSubtract(this, dur, direction);
	            return this;
	        };
	    }

	    function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
	        var milliseconds = duration._milliseconds,
	            days = absRound(duration._days),
	            months = absRound(duration._months);

	        if (!mom.isValid()) {
	            // No op
	            return;
	        }

	        updateOffset = updateOffset == null ? true : updateOffset;

	        if (milliseconds) {
	            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
	        }
	        if (days) {
	            get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
	        }
	        if (months) {
	            setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
	        }
	        if (updateOffset) {
	            utils_hooks__hooks.updateOffset(mom, days || months);
	        }
	    }

	    var add_subtract__add      = createAdder(1, 'add');
	    var add_subtract__subtract = createAdder(-1, 'subtract');

	    function moment_calendar__calendar (time, formats) {
	        // We want to compare the start of today, vs this.
	        // Getting start-of-today depends on whether we're local/utc/offset or not.
	        var now = time || local__createLocal(),
	            sod = cloneWithOffset(now, this).startOf('day'),
	            diff = this.diff(sod, 'days', true),
	            format = diff < -6 ? 'sameElse' :
	                diff < -1 ? 'lastWeek' :
	                diff < 0 ? 'lastDay' :
	                diff < 1 ? 'sameDay' :
	                diff < 2 ? 'nextDay' :
	                diff < 7 ? 'nextWeek' : 'sameElse';

	        var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);

	        return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
	    }

	    function clone () {
	        return new Moment(this);
	    }

	    function isAfter (input, units) {
	        var localInput = isMoment(input) ? input : local__createLocal(input);
	        if (!(this.isValid() && localInput.isValid())) {
	            return false;
	        }
	        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
	        if (units === 'millisecond') {
	            return this.valueOf() > localInput.valueOf();
	        } else {
	            return localInput.valueOf() < this.clone().startOf(units).valueOf();
	        }
	    }

	    function isBefore (input, units) {
	        var localInput = isMoment(input) ? input : local__createLocal(input);
	        if (!(this.isValid() && localInput.isValid())) {
	            return false;
	        }
	        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
	        if (units === 'millisecond') {
	            return this.valueOf() < localInput.valueOf();
	        } else {
	            return this.clone().endOf(units).valueOf() < localInput.valueOf();
	        }
	    }

	    function isBetween (from, to, units, inclusivity) {
	        inclusivity = inclusivity || '()';
	        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
	            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
	    }

	    function isSame (input, units) {
	        var localInput = isMoment(input) ? input : local__createLocal(input),
	            inputMs;
	        if (!(this.isValid() && localInput.isValid())) {
	            return false;
	        }
	        units = normalizeUnits(units || 'millisecond');
	        if (units === 'millisecond') {
	            return this.valueOf() === localInput.valueOf();
	        } else {
	            inputMs = localInput.valueOf();
	            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
	        }
	    }

	    function isSameOrAfter (input, units) {
	        return this.isSame(input, units) || this.isAfter(input,units);
	    }

	    function isSameOrBefore (input, units) {
	        return this.isSame(input, units) || this.isBefore(input,units);
	    }

	    function diff (input, units, asFloat) {
	        var that,
	            zoneDelta,
	            delta, output;

	        if (!this.isValid()) {
	            return NaN;
	        }

	        that = cloneWithOffset(input, this);

	        if (!that.isValid()) {
	            return NaN;
	        }

	        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;

	        units = normalizeUnits(units);

	        if (units === 'year' || units === 'month' || units === 'quarter') {
	            output = monthDiff(this, that);
	            if (units === 'quarter') {
	                output = output / 3;
	            } else if (units === 'year') {
	                output = output / 12;
	            }
	        } else {
	            delta = this - that;
	            output = units === 'second' ? delta / 1e3 : // 1000
	                units === 'minute' ? delta / 6e4 : // 1000 * 60
	                units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
	                units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
	                units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
	                delta;
	        }
	        return asFloat ? output : absFloor(output);
	    }

	    function monthDiff (a, b) {
	        // difference in months
	        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
	            // b is in (anchor - 1 month, anchor + 1 month)
	            anchor = a.clone().add(wholeMonthDiff, 'months'),
	            anchor2, adjust;

	        if (b - anchor < 0) {
	            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
	            // linear across the month
	            adjust = (b - anchor) / (anchor - anchor2);
	        } else {
	            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
	            // linear across the month
	            adjust = (b - anchor) / (anchor2 - anchor);
	        }

	        //check for negative zero, return zero if negative zero
	        return -(wholeMonthDiff + adjust) || 0;
	    }

	    utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
	    utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';

	    function toString () {
	        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
	    }

	    function moment_format__toISOString () {
	        var m = this.clone().utc();
	        if (0 < m.year() && m.year() <= 9999) {
	            if (isFunction(Date.prototype.toISOString)) {
	                // native implementation is ~50x faster, use it when we can
	                return this.toDate().toISOString();
	            } else {
	                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
	            }
	        } else {
	            return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
	        }
	    }

	    function format (inputString) {
	        if (!inputString) {
	            inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
	        }
	        var output = formatMoment(this, inputString);
	        return this.localeData().postformat(output);
	    }

	    function from (time, withoutSuffix) {
	        if (this.isValid() &&
	                ((isMoment(time) && time.isValid()) ||
	                 local__createLocal(time).isValid())) {
	            return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
	        } else {
	            return this.localeData().invalidDate();
	        }
	    }

	    function fromNow (withoutSuffix) {
	        return this.from(local__createLocal(), withoutSuffix);
	    }

	    function to (time, withoutSuffix) {
	        if (this.isValid() &&
	                ((isMoment(time) && time.isValid()) ||
	                 local__createLocal(time).isValid())) {
	            return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
	        } else {
	            return this.localeData().invalidDate();
	        }
	    }

	    function toNow (withoutSuffix) {
	        return this.to(local__createLocal(), withoutSuffix);
	    }

	    // If passed a locale key, it will set the locale for this
	    // instance.  Otherwise, it will return the locale configuration
	    // variables for this instance.
	    function locale (key) {
	        var newLocaleData;

	        if (key === undefined) {
	            return this._locale._abbr;
	        } else {
	            newLocaleData = locale_locales__getLocale(key);
	            if (newLocaleData != null) {
	                this._locale = newLocaleData;
	            }
	            return this;
	        }
	    }

	    var lang = deprecate(
	        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
	        function (key) {
	            if (key === undefined) {
	                return this.localeData();
	            } else {
	                return this.locale(key);
	            }
	        }
	    );

	    function localeData () {
	        return this._locale;
	    }

	    function startOf (units) {
	        units = normalizeUnits(units);
	        // the following switch intentionally omits break keywords
	        // to utilize falling through the cases.
	        switch (units) {
	        case 'year':
	            this.month(0);
	            /* falls through */
	        case 'quarter':
	        case 'month':
	            this.date(1);
	            /* falls through */
	        case 'week':
	        case 'isoWeek':
	        case 'day':
	        case 'date':
	            this.hours(0);
	            /* falls through */
	        case 'hour':
	            this.minutes(0);
	            /* falls through */
	        case 'minute':
	            this.seconds(0);
	            /* falls through */
	        case 'second':
	            this.milliseconds(0);
	        }

	        // weeks are a special case
	        if (units === 'week') {
	            this.weekday(0);
	        }
	        if (units === 'isoWeek') {
	            this.isoWeekday(1);
	        }

	        // quarters are also special
	        if (units === 'quarter') {
	            this.month(Math.floor(this.month() / 3) * 3);
	        }

	        return this;
	    }

	    function endOf (units) {
	        units = normalizeUnits(units);
	        if (units === undefined || units === 'millisecond') {
	            return this;
	        }

	        // 'date' is an alias for 'day', so it should be considered as such.
	        if (units === 'date') {
	            units = 'day';
	        }

	        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
	    }

	    function to_type__valueOf () {
	        return this._d.valueOf() - ((this._offset || 0) * 60000);
	    }

	    function unix () {
	        return Math.floor(this.valueOf() / 1000);
	    }

	    function toDate () {
	        return this._offset ? new Date(this.valueOf()) : this._d;
	    }

	    function toArray () {
	        var m = this;
	        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
	    }

	    function toObject () {
	        var m = this;
	        return {
	            years: m.year(),
	            months: m.month(),
	            date: m.date(),
	            hours: m.hours(),
	            minutes: m.minutes(),
	            seconds: m.seconds(),
	            milliseconds: m.milliseconds()
	        };
	    }

	    function toJSON () {
	        // new Date(NaN).toJSON() === null
	        return this.isValid() ? this.toISOString() : null;
	    }

	    function moment_valid__isValid () {
	        return valid__isValid(this);
	    }

	    function parsingFlags () {
	        return extend({}, getParsingFlags(this));
	    }

	    function invalidAt () {
	        return getParsingFlags(this).overflow;
	    }

	    function creationData() {
	        return {
	            input: this._i,
	            format: this._f,
	            locale: this._locale,
	            isUTC: this._isUTC,
	            strict: this._strict
	        };
	    }

	    // FORMATTING

	    addFormatToken(0, ['gg', 2], 0, function () {
	        return this.weekYear() % 100;
	    });

	    addFormatToken(0, ['GG', 2], 0, function () {
	        return this.isoWeekYear() % 100;
	    });

	    function addWeekYearFormatToken (token, getter) {
	        addFormatToken(0, [token, token.length], 0, getter);
	    }

	    addWeekYearFormatToken('gggg',     'weekYear');
	    addWeekYearFormatToken('ggggg',    'weekYear');
	    addWeekYearFormatToken('GGGG',  'isoWeekYear');
	    addWeekYearFormatToken('GGGGG', 'isoWeekYear');

	    // ALIASES

	    addUnitAlias('weekYear', 'gg');
	    addUnitAlias('isoWeekYear', 'GG');

	    // PARSING

	    addRegexToken('G',      matchSigned);
	    addRegexToken('g',      matchSigned);
	    addRegexToken('GG',     match1to2, match2);
	    addRegexToken('gg',     match1to2, match2);
	    addRegexToken('GGGG',   match1to4, match4);
	    addRegexToken('gggg',   match1to4, match4);
	    addRegexToken('GGGGG',  match1to6, match6);
	    addRegexToken('ggggg',  match1to6, match6);

	    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
	        week[token.substr(0, 2)] = toInt(input);
	    });

	    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
	        week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
	    });

	    // MOMENTS

	    function getSetWeekYear (input) {
	        return getSetWeekYearHelper.call(this,
	                input,
	                this.week(),
	                this.weekday(),
	                this.localeData()._week.dow,
	                this.localeData()._week.doy);
	    }

	    function getSetISOWeekYear (input) {
	        return getSetWeekYearHelper.call(this,
	                input, this.isoWeek(), this.isoWeekday(), 1, 4);
	    }

	    function getISOWeeksInYear () {
	        return weeksInYear(this.year(), 1, 4);
	    }

	    function getWeeksInYear () {
	        var weekInfo = this.localeData()._week;
	        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
	    }

	    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
	        var weeksTarget;
	        if (input == null) {
	            return weekOfYear(this, dow, doy).year;
	        } else {
	            weeksTarget = weeksInYear(input, dow, doy);
	            if (week > weeksTarget) {
	                week = weeksTarget;
	            }
	            return setWeekAll.call(this, input, week, weekday, dow, doy);
	        }
	    }

	    function setWeekAll(weekYear, week, weekday, dow, doy) {
	        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
	            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);

	        this.year(date.getUTCFullYear());
	        this.month(date.getUTCMonth());
	        this.date(date.getUTCDate());
	        return this;
	    }

	    // FORMATTING

	    addFormatToken('Q', 0, 'Qo', 'quarter');

	    // ALIASES

	    addUnitAlias('quarter', 'Q');

	    // PARSING

	    addRegexToken('Q', match1);
	    addParseToken('Q', function (input, array) {
	        array[MONTH] = (toInt(input) - 1) * 3;
	    });

	    // MOMENTS

	    function getSetQuarter (input) {
	        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
	    }

	    // FORMATTING

	    addFormatToken('w', ['ww', 2], 'wo', 'week');
	    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');

	    // ALIASES

	    addUnitAlias('week', 'w');
	    addUnitAlias('isoWeek', 'W');

	    // PARSING

	    addRegexToken('w',  match1to2);
	    addRegexToken('ww', match1to2, match2);
	    addRegexToken('W',  match1to2);
	    addRegexToken('WW', match1to2, match2);

	    addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
	        week[token.substr(0, 1)] = toInt(input);
	    });

	    // HELPERS

	    // LOCALES

	    function localeWeek (mom) {
	        return weekOfYear(mom, this._week.dow, this._week.doy).week;
	    }

	    var defaultLocaleWeek = {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    };

	    function localeFirstDayOfWeek () {
	        return this._week.dow;
	    }

	    function localeFirstDayOfYear () {
	        return this._week.doy;
	    }

	    // MOMENTS

	    function getSetWeek (input) {
	        var week = this.localeData().week(this);
	        return input == null ? week : this.add((input - week) * 7, 'd');
	    }

	    function getSetISOWeek (input) {
	        var week = weekOfYear(this, 1, 4).week;
	        return input == null ? week : this.add((input - week) * 7, 'd');
	    }

	    // FORMATTING

	    addFormatToken('D', ['DD', 2], 'Do', 'date');

	    // ALIASES

	    addUnitAlias('date', 'D');

	    // PARSING

	    addRegexToken('D',  match1to2);
	    addRegexToken('DD', match1to2, match2);
	    addRegexToken('Do', function (isStrict, locale) {
	        return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
	    });

	    addParseToken(['D', 'DD'], DATE);
	    addParseToken('Do', function (input, array) {
	        array[DATE] = toInt(input.match(match1to2)[0], 10);
	    });

	    // MOMENTS

	    var getSetDayOfMonth = makeGetSet('Date', true);

	    // FORMATTING

	    addFormatToken('d', 0, 'do', 'day');

	    addFormatToken('dd', 0, 0, function (format) {
	        return this.localeData().weekdaysMin(this, format);
	    });

	    addFormatToken('ddd', 0, 0, function (format) {
	        return this.localeData().weekdaysShort(this, format);
	    });

	    addFormatToken('dddd', 0, 0, function (format) {
	        return this.localeData().weekdays(this, format);
	    });

	    addFormatToken('e', 0, 0, 'weekday');
	    addFormatToken('E', 0, 0, 'isoWeekday');

	    // ALIASES

	    addUnitAlias('day', 'd');
	    addUnitAlias('weekday', 'e');
	    addUnitAlias('isoWeekday', 'E');

	    // PARSING

	    addRegexToken('d',    match1to2);
	    addRegexToken('e',    match1to2);
	    addRegexToken('E',    match1to2);
	    addRegexToken('dd',   function (isStrict, locale) {
	        return locale.weekdaysMinRegex(isStrict);
	    });
	    addRegexToken('ddd',   function (isStrict, locale) {
	        return locale.weekdaysShortRegex(isStrict);
	    });
	    addRegexToken('dddd',   function (isStrict, locale) {
	        return locale.weekdaysRegex(isStrict);
	    });

	    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
	        var weekday = config._locale.weekdaysParse(input, token, config._strict);
	        // if we didn't get a weekday name, mark the date as invalid
	        if (weekday != null) {
	            week.d = weekday;
	        } else {
	            getParsingFlags(config).invalidWeekday = input;
	        }
	    });

	    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
	        week[token] = toInt(input);
	    });

	    // HELPERS

	    function parseWeekday(input, locale) {
	        if (typeof input !== 'string') {
	            return input;
	        }

	        if (!isNaN(input)) {
	            return parseInt(input, 10);
	        }

	        input = locale.weekdaysParse(input);
	        if (typeof input === 'number') {
	            return input;
	        }

	        return null;
	    }

	    // LOCALES

	    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
	    function localeWeekdays (m, format) {
	        return isArray(this._weekdays) ? this._weekdays[m.day()] :
	            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
	    }

	    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
	    function localeWeekdaysShort (m) {
	        return this._weekdaysShort[m.day()];
	    }

	    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
	    function localeWeekdaysMin (m) {
	        return this._weekdaysMin[m.day()];
	    }

	    function day_of_week__handleStrictParse(weekdayName, format, strict) {
	        var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
	        if (!this._weekdaysParse) {
	            this._weekdaysParse = [];
	            this._shortWeekdaysParse = [];
	            this._minWeekdaysParse = [];

	            for (i = 0; i < 7; ++i) {
	                mom = create_utc__createUTC([2000, 1]).day(i);
	                this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
	                this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
	                this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
	            }
	        }

	        if (strict) {
	            if (format === 'dddd') {
	                ii = indexOf.call(this._weekdaysParse, llc);
	                return ii !== -1 ? ii : null;
	            } else if (format === 'ddd') {
	                ii = indexOf.call(this._shortWeekdaysParse, llc);
	                return ii !== -1 ? ii : null;
	            } else {
	                ii = indexOf.call(this._minWeekdaysParse, llc);
	                return ii !== -1 ? ii : null;
	            }
	        } else {
	            if (format === 'dddd') {
	                ii = indexOf.call(this._weekdaysParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._shortWeekdaysParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._minWeekdaysParse, llc);
	                return ii !== -1 ? ii : null;
	            } else if (format === 'ddd') {
	                ii = indexOf.call(this._shortWeekdaysParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._weekdaysParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._minWeekdaysParse, llc);
	                return ii !== -1 ? ii : null;
	            } else {
	                ii = indexOf.call(this._minWeekdaysParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._weekdaysParse, llc);
	                if (ii !== -1) {
	                    return ii;
	                }
	                ii = indexOf.call(this._shortWeekdaysParse, llc);
	                return ii !== -1 ? ii : null;
	            }
	        }
	    }

	    function localeWeekdaysParse (weekdayName, format, strict) {
	        var i, mom, regex;

	        if (this._weekdaysParseExact) {
	            return day_of_week__handleStrictParse.call(this, weekdayName, format, strict);
	        }

	        if (!this._weekdaysParse) {
	            this._weekdaysParse = [];
	            this._minWeekdaysParse = [];
	            this._shortWeekdaysParse = [];
	            this._fullWeekdaysParse = [];
	        }

	        for (i = 0; i < 7; i++) {
	            // make the regex if we don't have it already

	            mom = create_utc__createUTC([2000, 1]).day(i);
	            if (strict && !this._fullWeekdaysParse[i]) {
	                this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
	                this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
	                this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
	            }
	            if (!this._weekdaysParse[i]) {
	                regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
	                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
	            }
	            // test the regex
	            if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
	                return i;
	            } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
	                return i;
	            } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
	                return i;
	            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
	                return i;
	            }
	        }
	    }

	    // MOMENTS

	    function getSetDayOfWeek (input) {
	        if (!this.isValid()) {
	            return input != null ? this : NaN;
	        }
	        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
	        if (input != null) {
	            input = parseWeekday(input, this.localeData());
	            return this.add(input - day, 'd');
	        } else {
	            return day;
	        }
	    }

	    function getSetLocaleDayOfWeek (input) {
	        if (!this.isValid()) {
	            return input != null ? this : NaN;
	        }
	        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
	        return input == null ? weekday : this.add(input - weekday, 'd');
	    }

	    function getSetISODayOfWeek (input) {
	        if (!this.isValid()) {
	            return input != null ? this : NaN;
	        }
	        // behaves the same as moment#day except
	        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
	        // as a setter, sunday should belong to the previous week.
	        return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
	    }

	    var defaultWeekdaysRegex = matchWord;
	    function weekdaysRegex (isStrict) {
	        if (this._weekdaysParseExact) {
	            if (!hasOwnProp(this, '_weekdaysRegex')) {
	                computeWeekdaysParse.call(this);
	            }
	            if (isStrict) {
	                return this._weekdaysStrictRegex;
	            } else {
	                return this._weekdaysRegex;
	            }
	        } else {
	            return this._weekdaysStrictRegex && isStrict ?
	                this._weekdaysStrictRegex : this._weekdaysRegex;
	        }
	    }

	    var defaultWeekdaysShortRegex = matchWord;
	    function weekdaysShortRegex (isStrict) {
	        if (this._weekdaysParseExact) {
	            if (!hasOwnProp(this, '_weekdaysRegex')) {
	                computeWeekdaysParse.call(this);
	            }
	            if (isStrict) {
	                return this._weekdaysShortStrictRegex;
	            } else {
	                return this._weekdaysShortRegex;
	            }
	        } else {
	            return this._weekdaysShortStrictRegex && isStrict ?
	                this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
	        }
	    }

	    var defaultWeekdaysMinRegex = matchWord;
	    function weekdaysMinRegex (isStrict) {
	        if (this._weekdaysParseExact) {
	            if (!hasOwnProp(this, '_weekdaysRegex')) {
	                computeWeekdaysParse.call(this);
	            }
	            if (isStrict) {
	                return this._weekdaysMinStrictRegex;
	            } else {
	                return this._weekdaysMinRegex;
	            }
	        } else {
	            return this._weekdaysMinStrictRegex && isStrict ?
	                this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
	        }
	    }


	    function computeWeekdaysParse () {
	        function cmpLenRev(a, b) {
	            return b.length - a.length;
	        }

	        var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
	            i, mom, minp, shortp, longp;
	        for (i = 0; i < 7; i++) {
	            // make the regex if we don't have it already
	            mom = create_utc__createUTC([2000, 1]).day(i);
	            minp = this.weekdaysMin(mom, '');
	            shortp = this.weekdaysShort(mom, '');
	            longp = this.weekdays(mom, '');
	            minPieces.push(minp);
	            shortPieces.push(shortp);
	            longPieces.push(longp);
	            mixedPieces.push(minp);
	            mixedPieces.push(shortp);
	            mixedPieces.push(longp);
	        }
	        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
	        // will match the longer piece.
	        minPieces.sort(cmpLenRev);
	        shortPieces.sort(cmpLenRev);
	        longPieces.sort(cmpLenRev);
	        mixedPieces.sort(cmpLenRev);
	        for (i = 0; i < 7; i++) {
	            shortPieces[i] = regexEscape(shortPieces[i]);
	            longPieces[i] = regexEscape(longPieces[i]);
	            mixedPieces[i] = regexEscape(mixedPieces[i]);
	        }

	        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
	        this._weekdaysShortRegex = this._weekdaysRegex;
	        this._weekdaysMinRegex = this._weekdaysRegex;

	        this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
	        this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
	        this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
	    }

	    // FORMATTING

	    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');

	    // ALIASES

	    addUnitAlias('dayOfYear', 'DDD');

	    // PARSING

	    addRegexToken('DDD',  match1to3);
	    addRegexToken('DDDD', match3);
	    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
	        config._dayOfYear = toInt(input);
	    });

	    // HELPERS

	    // MOMENTS

	    function getSetDayOfYear (input) {
	        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
	        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
	    }

	    // FORMATTING

	    function hFormat() {
	        return this.hours() % 12 || 12;
	    }

	    function kFormat() {
	        return this.hours() || 24;
	    }

	    addFormatToken('H', ['HH', 2], 0, 'hour');
	    addFormatToken('h', ['hh', 2], 0, hFormat);
	    addFormatToken('k', ['kk', 2], 0, kFormat);

	    addFormatToken('hmm', 0, 0, function () {
	        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
	    });

	    addFormatToken('hmmss', 0, 0, function () {
	        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
	            zeroFill(this.seconds(), 2);
	    });

	    addFormatToken('Hmm', 0, 0, function () {
	        return '' + this.hours() + zeroFill(this.minutes(), 2);
	    });

	    addFormatToken('Hmmss', 0, 0, function () {
	        return '' + this.hours() + zeroFill(this.minutes(), 2) +
	            zeroFill(this.seconds(), 2);
	    });

	    function meridiem (token, lowercase) {
	        addFormatToken(token, 0, 0, function () {
	            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
	        });
	    }

	    meridiem('a', true);
	    meridiem('A', false);

	    // ALIASES

	    addUnitAlias('hour', 'h');

	    // PARSING

	    function matchMeridiem (isStrict, locale) {
	        return locale._meridiemParse;
	    }

	    addRegexToken('a',  matchMeridiem);
	    addRegexToken('A',  matchMeridiem);
	    addRegexToken('H',  match1to2);
	    addRegexToken('h',  match1to2);
	    addRegexToken('HH', match1to2, match2);
	    addRegexToken('hh', match1to2, match2);

	    addRegexToken('hmm', match3to4);
	    addRegexToken('hmmss', match5to6);
	    addRegexToken('Hmm', match3to4);
	    addRegexToken('Hmmss', match5to6);

	    addParseToken(['H', 'HH'], HOUR);
	    addParseToken(['a', 'A'], function (input, array, config) {
	        config._isPm = config._locale.isPM(input);
	        config._meridiem = input;
	    });
	    addParseToken(['h', 'hh'], function (input, array, config) {
	        array[HOUR] = toInt(input);
	        getParsingFlags(config).bigHour = true;
	    });
	    addParseToken('hmm', function (input, array, config) {
	        var pos = input.length - 2;
	        array[HOUR] = toInt(input.substr(0, pos));
	        array[MINUTE] = toInt(input.substr(pos));
	        getParsingFlags(config).bigHour = true;
	    });
	    addParseToken('hmmss', function (input, array, config) {
	        var pos1 = input.length - 4;
	        var pos2 = input.length - 2;
	        array[HOUR] = toInt(input.substr(0, pos1));
	        array[MINUTE] = toInt(input.substr(pos1, 2));
	        array[SECOND] = toInt(input.substr(pos2));
	        getParsingFlags(config).bigHour = true;
	    });
	    addParseToken('Hmm', function (input, array, config) {
	        var pos = input.length - 2;
	        array[HOUR] = toInt(input.substr(0, pos));
	        array[MINUTE] = toInt(input.substr(pos));
	    });
	    addParseToken('Hmmss', function (input, array, config) {
	        var pos1 = input.length - 4;
	        var pos2 = input.length - 2;
	        array[HOUR] = toInt(input.substr(0, pos1));
	        array[MINUTE] = toInt(input.substr(pos1, 2));
	        array[SECOND] = toInt(input.substr(pos2));
	    });

	    // LOCALES

	    function localeIsPM (input) {
	        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
	        // Using charAt should be more compatible.
	        return ((input + '').toLowerCase().charAt(0) === 'p');
	    }

	    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
	    function localeMeridiem (hours, minutes, isLower) {
	        if (hours > 11) {
	            return isLower ? 'pm' : 'PM';
	        } else {
	            return isLower ? 'am' : 'AM';
	        }
	    }


	    // MOMENTS

	    // Setting the hour should keep the time, because the user explicitly
	    // specified which hour he wants. So trying to maintain the same hour (in
	    // a new timezone) makes sense. Adding/subtracting hours does not follow
	    // this rule.
	    var getSetHour = makeGetSet('Hours', true);

	    // FORMATTING

	    addFormatToken('m', ['mm', 2], 0, 'minute');

	    // ALIASES

	    addUnitAlias('minute', 'm');

	    // PARSING

	    addRegexToken('m',  match1to2);
	    addRegexToken('mm', match1to2, match2);
	    addParseToken(['m', 'mm'], MINUTE);

	    // MOMENTS

	    var getSetMinute = makeGetSet('Minutes', false);

	    // FORMATTING

	    addFormatToken('s', ['ss', 2], 0, 'second');

	    // ALIASES

	    addUnitAlias('second', 's');

	    // PARSING

	    addRegexToken('s',  match1to2);
	    addRegexToken('ss', match1to2, match2);
	    addParseToken(['s', 'ss'], SECOND);

	    // MOMENTS

	    var getSetSecond = makeGetSet('Seconds', false);

	    // FORMATTING

	    addFormatToken('S', 0, 0, function () {
	        return ~~(this.millisecond() / 100);
	    });

	    addFormatToken(0, ['SS', 2], 0, function () {
	        return ~~(this.millisecond() / 10);
	    });

	    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
	    addFormatToken(0, ['SSSS', 4], 0, function () {
	        return this.millisecond() * 10;
	    });
	    addFormatToken(0, ['SSSSS', 5], 0, function () {
	        return this.millisecond() * 100;
	    });
	    addFormatToken(0, ['SSSSSS', 6], 0, function () {
	        return this.millisecond() * 1000;
	    });
	    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
	        return this.millisecond() * 10000;
	    });
	    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
	        return this.millisecond() * 100000;
	    });
	    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
	        return this.millisecond() * 1000000;
	    });


	    // ALIASES

	    addUnitAlias('millisecond', 'ms');

	    // PARSING

	    addRegexToken('S',    match1to3, match1);
	    addRegexToken('SS',   match1to3, match2);
	    addRegexToken('SSS',  match1to3, match3);

	    var token;
	    for (token = 'SSSS'; token.length <= 9; token += 'S') {
	        addRegexToken(token, matchUnsigned);
	    }

	    function parseMs(input, array) {
	        array[MILLISECOND] = toInt(('0.' + input) * 1000);
	    }

	    for (token = 'S'; token.length <= 9; token += 'S') {
	        addParseToken(token, parseMs);
	    }
	    // MOMENTS

	    var getSetMillisecond = makeGetSet('Milliseconds', false);

	    // FORMATTING

	    addFormatToken('z',  0, 0, 'zoneAbbr');
	    addFormatToken('zz', 0, 0, 'zoneName');

	    // MOMENTS

	    function getZoneAbbr () {
	        return this._isUTC ? 'UTC' : '';
	    }

	    function getZoneName () {
	        return this._isUTC ? 'Coordinated Universal Time' : '';
	    }

	    var momentPrototype__proto = Moment.prototype;

	    momentPrototype__proto.add               = add_subtract__add;
	    momentPrototype__proto.calendar          = moment_calendar__calendar;
	    momentPrototype__proto.clone             = clone;
	    momentPrototype__proto.diff              = diff;
	    momentPrototype__proto.endOf             = endOf;
	    momentPrototype__proto.format            = format;
	    momentPrototype__proto.from              = from;
	    momentPrototype__proto.fromNow           = fromNow;
	    momentPrototype__proto.to                = to;
	    momentPrototype__proto.toNow             = toNow;
	    momentPrototype__proto.get               = getSet;
	    momentPrototype__proto.invalidAt         = invalidAt;
	    momentPrototype__proto.isAfter           = isAfter;
	    momentPrototype__proto.isBefore          = isBefore;
	    momentPrototype__proto.isBetween         = isBetween;
	    momentPrototype__proto.isSame            = isSame;
	    momentPrototype__proto.isSameOrAfter     = isSameOrAfter;
	    momentPrototype__proto.isSameOrBefore    = isSameOrBefore;
	    momentPrototype__proto.isValid           = moment_valid__isValid;
	    momentPrototype__proto.lang              = lang;
	    momentPrototype__proto.locale            = locale;
	    momentPrototype__proto.localeData        = localeData;
	    momentPrototype__proto.max               = prototypeMax;
	    momentPrototype__proto.min               = prototypeMin;
	    momentPrototype__proto.parsingFlags      = parsingFlags;
	    momentPrototype__proto.set               = getSet;
	    momentPrototype__proto.startOf           = startOf;
	    momentPrototype__proto.subtract          = add_subtract__subtract;
	    momentPrototype__proto.toArray           = toArray;
	    momentPrototype__proto.toObject          = toObject;
	    momentPrototype__proto.toDate            = toDate;
	    momentPrototype__proto.toISOString       = moment_format__toISOString;
	    momentPrototype__proto.toJSON            = toJSON;
	    momentPrototype__proto.toString          = toString;
	    momentPrototype__proto.unix              = unix;
	    momentPrototype__proto.valueOf           = to_type__valueOf;
	    momentPrototype__proto.creationData      = creationData;

	    // Year
	    momentPrototype__proto.year       = getSetYear;
	    momentPrototype__proto.isLeapYear = getIsLeapYear;

	    // Week Year
	    momentPrototype__proto.weekYear    = getSetWeekYear;
	    momentPrototype__proto.isoWeekYear = getSetISOWeekYear;

	    // Quarter
	    momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;

	    // Month
	    momentPrototype__proto.month       = getSetMonth;
	    momentPrototype__proto.daysInMonth = getDaysInMonth;

	    // Week
	    momentPrototype__proto.week           = momentPrototype__proto.weeks        = getSetWeek;
	    momentPrototype__proto.isoWeek        = momentPrototype__proto.isoWeeks     = getSetISOWeek;
	    momentPrototype__proto.weeksInYear    = getWeeksInYear;
	    momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;

	    // Day
	    momentPrototype__proto.date       = getSetDayOfMonth;
	    momentPrototype__proto.day        = momentPrototype__proto.days             = getSetDayOfWeek;
	    momentPrototype__proto.weekday    = getSetLocaleDayOfWeek;
	    momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
	    momentPrototype__proto.dayOfYear  = getSetDayOfYear;

	    // Hour
	    momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;

	    // Minute
	    momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;

	    // Second
	    momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;

	    // Millisecond
	    momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;

	    // Offset
	    momentPrototype__proto.utcOffset            = getSetOffset;
	    momentPrototype__proto.utc                  = setOffsetToUTC;
	    momentPrototype__proto.local                = setOffsetToLocal;
	    momentPrototype__proto.parseZone            = setOffsetToParsedOffset;
	    momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
	    momentPrototype__proto.isDST                = isDaylightSavingTime;
	    momentPrototype__proto.isDSTShifted         = isDaylightSavingTimeShifted;
	    momentPrototype__proto.isLocal              = isLocal;
	    momentPrototype__proto.isUtcOffset          = isUtcOffset;
	    momentPrototype__proto.isUtc                = isUtc;
	    momentPrototype__proto.isUTC                = isUtc;

	    // Timezone
	    momentPrototype__proto.zoneAbbr = getZoneAbbr;
	    momentPrototype__proto.zoneName = getZoneName;

	    // Deprecations
	    momentPrototype__proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
	    momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
	    momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
	    momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);

	    var momentPrototype = momentPrototype__proto;

	    function moment__createUnix (input) {
	        return local__createLocal(input * 1000);
	    }

	    function moment__createInZone () {
	        return local__createLocal.apply(null, arguments).parseZone();
	    }

	    var defaultCalendar = {
	        sameDay : '[Today at] LT',
	        nextDay : '[Tomorrow at] LT',
	        nextWeek : 'dddd [at] LT',
	        lastDay : '[Yesterday at] LT',
	        lastWeek : '[Last] dddd [at] LT',
	        sameElse : 'L'
	    };

	    function locale_calendar__calendar (key, mom, now) {
	        var output = this._calendar[key];
	        return isFunction(output) ? output.call(mom, now) : output;
	    }

	    var defaultLongDateFormat = {
	        LTS  : 'h:mm:ss A',
	        LT   : 'h:mm A',
	        L    : 'MM/DD/YYYY',
	        LL   : 'MMMM D, YYYY',
	        LLL  : 'MMMM D, YYYY h:mm A',
	        LLLL : 'dddd, MMMM D, YYYY h:mm A'
	    };

	    function longDateFormat (key) {
	        var format = this._longDateFormat[key],
	            formatUpper = this._longDateFormat[key.toUpperCase()];

	        if (format || !formatUpper) {
	            return format;
	        }

	        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
	            return val.slice(1);
	        });

	        return this._longDateFormat[key];
	    }

	    var defaultInvalidDate = 'Invalid date';

	    function invalidDate () {
	        return this._invalidDate;
	    }

	    var defaultOrdinal = '%d';
	    var defaultOrdinalParse = /\d{1,2}/;

	    function ordinal (number) {
	        return this._ordinal.replace('%d', number);
	    }

	    function preParsePostFormat (string) {
	        return string;
	    }

	    var defaultRelativeTime = {
	        future : 'in %s',
	        past   : '%s ago',
	        s  : 'a few seconds',
	        m  : 'a minute',
	        mm : '%d minutes',
	        h  : 'an hour',
	        hh : '%d hours',
	        d  : 'a day',
	        dd : '%d days',
	        M  : 'a month',
	        MM : '%d months',
	        y  : 'a year',
	        yy : '%d years'
	    };

	    function relative__relativeTime (number, withoutSuffix, string, isFuture) {
	        var output = this._relativeTime[string];
	        return (isFunction(output)) ?
	            output(number, withoutSuffix, string, isFuture) :
	            output.replace(/%d/i, number);
	    }

	    function pastFuture (diff, output) {
	        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
	        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
	    }

	    var prototype__proto = Locale.prototype;

	    prototype__proto._calendar       = defaultCalendar;
	    prototype__proto.calendar        = locale_calendar__calendar;
	    prototype__proto._longDateFormat = defaultLongDateFormat;
	    prototype__proto.longDateFormat  = longDateFormat;
	    prototype__proto._invalidDate    = defaultInvalidDate;
	    prototype__proto.invalidDate     = invalidDate;
	    prototype__proto._ordinal        = defaultOrdinal;
	    prototype__proto.ordinal         = ordinal;
	    prototype__proto._ordinalParse   = defaultOrdinalParse;
	    prototype__proto.preparse        = preParsePostFormat;
	    prototype__proto.postformat      = preParsePostFormat;
	    prototype__proto._relativeTime   = defaultRelativeTime;
	    prototype__proto.relativeTime    = relative__relativeTime;
	    prototype__proto.pastFuture      = pastFuture;
	    prototype__proto.set             = locale_set__set;

	    // Month
	    prototype__proto.months            =        localeMonths;
	    prototype__proto._months           = defaultLocaleMonths;
	    prototype__proto.monthsShort       =        localeMonthsShort;
	    prototype__proto._monthsShort      = defaultLocaleMonthsShort;
	    prototype__proto.monthsParse       =        localeMonthsParse;
	    prototype__proto._monthsRegex      = defaultMonthsRegex;
	    prototype__proto.monthsRegex       = monthsRegex;
	    prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
	    prototype__proto.monthsShortRegex  = monthsShortRegex;

	    // Week
	    prototype__proto.week = localeWeek;
	    prototype__proto._week = defaultLocaleWeek;
	    prototype__proto.firstDayOfYear = localeFirstDayOfYear;
	    prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;

	    // Day of Week
	    prototype__proto.weekdays       =        localeWeekdays;
	    prototype__proto._weekdays      = defaultLocaleWeekdays;
	    prototype__proto.weekdaysMin    =        localeWeekdaysMin;
	    prototype__proto._weekdaysMin   = defaultLocaleWeekdaysMin;
	    prototype__proto.weekdaysShort  =        localeWeekdaysShort;
	    prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
	    prototype__proto.weekdaysParse  =        localeWeekdaysParse;

	    prototype__proto._weekdaysRegex      = defaultWeekdaysRegex;
	    prototype__proto.weekdaysRegex       =        weekdaysRegex;
	    prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex;
	    prototype__proto.weekdaysShortRegex  =        weekdaysShortRegex;
	    prototype__proto._weekdaysMinRegex   = defaultWeekdaysMinRegex;
	    prototype__proto.weekdaysMinRegex    =        weekdaysMinRegex;

	    // Hours
	    prototype__proto.isPM = localeIsPM;
	    prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
	    prototype__proto.meridiem = localeMeridiem;

	    function lists__get (format, index, field, setter) {
	        var locale = locale_locales__getLocale();
	        var utc = create_utc__createUTC().set(setter, index);
	        return locale[field](utc, format);
	    }

	    function listMonthsImpl (format, index, field) {
	        if (typeof format === 'number') {
	            index = format;
	            format = undefined;
	        }

	        format = format || '';

	        if (index != null) {
	            return lists__get(format, index, field, 'month');
	        }

	        var i;
	        var out = [];
	        for (i = 0; i < 12; i++) {
	            out[i] = lists__get(format, i, field, 'month');
	        }
	        return out;
	    }

	    // ()
	    // (5)
	    // (fmt, 5)
	    // (fmt)
	    // (true)
	    // (true, 5)
	    // (true, fmt, 5)
	    // (true, fmt)
	    function listWeekdaysImpl (localeSorted, format, index, field) {
	        if (typeof localeSorted === 'boolean') {
	            if (typeof format === 'number') {
	                index = format;
	                format = undefined;
	            }

	            format = format || '';
	        } else {
	            format = localeSorted;
	            index = format;
	            localeSorted = false;

	            if (typeof format === 'number') {
	                index = format;
	                format = undefined;
	            }

	            format = format || '';
	        }

	        var locale = locale_locales__getLocale(),
	            shift = localeSorted ? locale._week.dow : 0;

	        if (index != null) {
	            return lists__get(format, (index + shift) % 7, field, 'day');
	        }

	        var i;
	        var out = [];
	        for (i = 0; i < 7; i++) {
	            out[i] = lists__get(format, (i + shift) % 7, field, 'day');
	        }
	        return out;
	    }

	    function lists__listMonths (format, index) {
	        return listMonthsImpl(format, index, 'months');
	    }

	    function lists__listMonthsShort (format, index) {
	        return listMonthsImpl(format, index, 'monthsShort');
	    }

	    function lists__listWeekdays (localeSorted, format, index) {
	        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
	    }

	    function lists__listWeekdaysShort (localeSorted, format, index) {
	        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
	    }

	    function lists__listWeekdaysMin (localeSorted, format, index) {
	        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
	    }

	    locale_locales__getSetGlobalLocale('en', {
	        ordinalParse: /\d{1,2}(th|st|nd|rd)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (toInt(number % 100 / 10) === 1) ? 'th' :
	                (b === 1) ? 'st' :
	                (b === 2) ? 'nd' :
	                (b === 3) ? 'rd' : 'th';
	            return number + output;
	        }
	    });

	    // Side effect imports
	    utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
	    utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);

	    var mathAbs = Math.abs;

	    function duration_abs__abs () {
	        var data           = this._data;

	        this._milliseconds = mathAbs(this._milliseconds);
	        this._days         = mathAbs(this._days);
	        this._months       = mathAbs(this._months);

	        data.milliseconds  = mathAbs(data.milliseconds);
	        data.seconds       = mathAbs(data.seconds);
	        data.minutes       = mathAbs(data.minutes);
	        data.hours         = mathAbs(data.hours);
	        data.months        = mathAbs(data.months);
	        data.years         = mathAbs(data.years);

	        return this;
	    }

	    function duration_add_subtract__addSubtract (duration, input, value, direction) {
	        var other = create__createDuration(input, value);

	        duration._milliseconds += direction * other._milliseconds;
	        duration._days         += direction * other._days;
	        duration._months       += direction * other._months;

	        return duration._bubble();
	    }

	    // supports only 2.0-style add(1, 's') or add(duration)
	    function duration_add_subtract__add (input, value) {
	        return duration_add_subtract__addSubtract(this, input, value, 1);
	    }

	    // supports only 2.0-style subtract(1, 's') or subtract(duration)
	    function duration_add_subtract__subtract (input, value) {
	        return duration_add_subtract__addSubtract(this, input, value, -1);
	    }

	    function absCeil (number) {
	        if (number < 0) {
	            return Math.floor(number);
	        } else {
	            return Math.ceil(number);
	        }
	    }

	    function bubble () {
	        var milliseconds = this._milliseconds;
	        var days         = this._days;
	        var months       = this._months;
	        var data         = this._data;
	        var seconds, minutes, hours, years, monthsFromDays;

	        // if we have a mix of positive and negative values, bubble down first
	        // check: https://github.com/moment/moment/issues/2166
	        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
	                (milliseconds <= 0 && days <= 0 && months <= 0))) {
	            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
	            days = 0;
	            months = 0;
	        }

	        // The following code bubbles up values, see the tests for
	        // examples of what that means.
	        data.milliseconds = milliseconds % 1000;

	        seconds           = absFloor(milliseconds / 1000);
	        data.seconds      = seconds % 60;

	        minutes           = absFloor(seconds / 60);
	        data.minutes      = minutes % 60;

	        hours             = absFloor(minutes / 60);
	        data.hours        = hours % 24;

	        days += absFloor(hours / 24);

	        // convert days to months
	        monthsFromDays = absFloor(daysToMonths(days));
	        months += monthsFromDays;
	        days -= absCeil(monthsToDays(monthsFromDays));

	        // 12 months -> 1 year
	        years = absFloor(months / 12);
	        months %= 12;

	        data.days   = days;
	        data.months = months;
	        data.years  = years;

	        return this;
	    }

	    function daysToMonths (days) {
	        // 400 years have 146097 days (taking into account leap year rules)
	        // 400 years have 12 months === 4800
	        return days * 4800 / 146097;
	    }

	    function monthsToDays (months) {
	        // the reverse of daysToMonths
	        return months * 146097 / 4800;
	    }

	    function as (units) {
	        var days;
	        var months;
	        var milliseconds = this._milliseconds;

	        units = normalizeUnits(units);

	        if (units === 'month' || units === 'year') {
	            days   = this._days   + milliseconds / 864e5;
	            months = this._months + daysToMonths(days);
	            return units === 'month' ? months : months / 12;
	        } else {
	            // handle milliseconds separately because of floating point math errors (issue #1867)
	            days = this._days + Math.round(monthsToDays(this._months));
	            switch (units) {
	                case 'week'   : return days / 7     + milliseconds / 6048e5;
	                case 'day'    : return days         + milliseconds / 864e5;
	                case 'hour'   : return days * 24    + milliseconds / 36e5;
	                case 'minute' : return days * 1440  + milliseconds / 6e4;
	                case 'second' : return days * 86400 + milliseconds / 1000;
	                // Math.floor prevents floating point math errors here
	                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
	                default: throw new Error('Unknown unit ' + units);
	            }
	        }
	    }

	    // TODO: Use this.as('ms')?
	    function duration_as__valueOf () {
	        return (
	            this._milliseconds +
	            this._days * 864e5 +
	            (this._months % 12) * 2592e6 +
	            toInt(this._months / 12) * 31536e6
	        );
	    }

	    function makeAs (alias) {
	        return function () {
	            return this.as(alias);
	        };
	    }

	    var asMilliseconds = makeAs('ms');
	    var asSeconds      = makeAs('s');
	    var asMinutes      = makeAs('m');
	    var asHours        = makeAs('h');
	    var asDays         = makeAs('d');
	    var asWeeks        = makeAs('w');
	    var asMonths       = makeAs('M');
	    var asYears        = makeAs('y');

	    function duration_get__get (units) {
	        units = normalizeUnits(units);
	        return this[units + 's']();
	    }

	    function makeGetter(name) {
	        return function () {
	            return this._data[name];
	        };
	    }

	    var milliseconds = makeGetter('milliseconds');
	    var seconds      = makeGetter('seconds');
	    var minutes      = makeGetter('minutes');
	    var hours        = makeGetter('hours');
	    var days         = makeGetter('days');
	    var months       = makeGetter('months');
	    var years        = makeGetter('years');

	    function weeks () {
	        return absFloor(this.days() / 7);
	    }

	    var round = Math.round;
	    var thresholds = {
	        s: 45,  // seconds to minute
	        m: 45,  // minutes to hour
	        h: 22,  // hours to day
	        d: 26,  // days to month
	        M: 11   // months to year
	    };

	    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
	    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
	        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
	    }

	    function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
	        var duration = create__createDuration(posNegDuration).abs();
	        var seconds  = round(duration.as('s'));
	        var minutes  = round(duration.as('m'));
	        var hours    = round(duration.as('h'));
	        var days     = round(duration.as('d'));
	        var months   = round(duration.as('M'));
	        var years    = round(duration.as('y'));

	        var a = seconds < thresholds.s && ['s', seconds]  ||
	                minutes <= 1           && ['m']           ||
	                minutes < thresholds.m && ['mm', minutes] ||
	                hours   <= 1           && ['h']           ||
	                hours   < thresholds.h && ['hh', hours]   ||
	                days    <= 1           && ['d']           ||
	                days    < thresholds.d && ['dd', days]    ||
	                months  <= 1           && ['M']           ||
	                months  < thresholds.M && ['MM', months]  ||
	                years   <= 1           && ['y']           || ['yy', years];

	        a[2] = withoutSuffix;
	        a[3] = +posNegDuration > 0;
	        a[4] = locale;
	        return substituteTimeAgo.apply(null, a);
	    }

	    // This function allows you to set a threshold for relative time strings
	    function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
	        if (thresholds[threshold] === undefined) {
	            return false;
	        }
	        if (limit === undefined) {
	            return thresholds[threshold];
	        }
	        thresholds[threshold] = limit;
	        return true;
	    }

	    function humanize (withSuffix) {
	        var locale = this.localeData();
	        var output = duration_humanize__relativeTime(this, !withSuffix, locale);

	        if (withSuffix) {
	            output = locale.pastFuture(+this, output);
	        }

	        return locale.postformat(output);
	    }

	    var iso_string__abs = Math.abs;

	    function iso_string__toISOString() {
	        // for ISO strings we do not use the normal bubbling rules:
	        //  * milliseconds bubble up until they become hours
	        //  * days do not bubble at all
	        //  * months bubble up until they become years
	        // This is because there is no context-free conversion between hours and days
	        // (think of clock changes)
	        // and also not between days and months (28-31 days per month)
	        var seconds = iso_string__abs(this._milliseconds) / 1000;
	        var days         = iso_string__abs(this._days);
	        var months       = iso_string__abs(this._months);
	        var minutes, hours, years;

	        // 3600 seconds -> 60 minutes -> 1 hour
	        minutes           = absFloor(seconds / 60);
	        hours             = absFloor(minutes / 60);
	        seconds %= 60;
	        minutes %= 60;

	        // 12 months -> 1 year
	        years  = absFloor(months / 12);
	        months %= 12;


	        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
	        var Y = years;
	        var M = months;
	        var D = days;
	        var h = hours;
	        var m = minutes;
	        var s = seconds;
	        var total = this.asSeconds();

	        if (!total) {
	            // this is the same as C#'s (Noda) and python (isodate)...
	            // but not other JS (goog.date)
	            return 'P0D';
	        }

	        return (total < 0 ? '-' : '') +
	            'P' +
	            (Y ? Y + 'Y' : '') +
	            (M ? M + 'M' : '') +
	            (D ? D + 'D' : '') +
	            ((h || m || s) ? 'T' : '') +
	            (h ? h + 'H' : '') +
	            (m ? m + 'M' : '') +
	            (s ? s + 'S' : '');
	    }

	    var duration_prototype__proto = Duration.prototype;

	    duration_prototype__proto.abs            = duration_abs__abs;
	    duration_prototype__proto.add            = duration_add_subtract__add;
	    duration_prototype__proto.subtract       = duration_add_subtract__subtract;
	    duration_prototype__proto.as             = as;
	    duration_prototype__proto.asMilliseconds = asMilliseconds;
	    duration_prototype__proto.asSeconds      = asSeconds;
	    duration_prototype__proto.asMinutes      = asMinutes;
	    duration_prototype__proto.asHours        = asHours;
	    duration_prototype__proto.asDays         = asDays;
	    duration_prototype__proto.asWeeks        = asWeeks;
	    duration_prototype__proto.asMonths       = asMonths;
	    duration_prototype__proto.asYears        = asYears;
	    duration_prototype__proto.valueOf        = duration_as__valueOf;
	    duration_prototype__proto._bubble        = bubble;
	    duration_prototype__proto.get            = duration_get__get;
	    duration_prototype__proto.milliseconds   = milliseconds;
	    duration_prototype__proto.seconds        = seconds;
	    duration_prototype__proto.minutes        = minutes;
	    duration_prototype__proto.hours          = hours;
	    duration_prototype__proto.days           = days;
	    duration_prototype__proto.weeks          = weeks;
	    duration_prototype__proto.months         = months;
	    duration_prototype__proto.years          = years;
	    duration_prototype__proto.humanize       = humanize;
	    duration_prototype__proto.toISOString    = iso_string__toISOString;
	    duration_prototype__proto.toString       = iso_string__toISOString;
	    duration_prototype__proto.toJSON         = iso_string__toISOString;
	    duration_prototype__proto.locale         = locale;
	    duration_prototype__proto.localeData     = localeData;

	    // Deprecations
	    duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
	    duration_prototype__proto.lang = lang;

	    // Side effect imports

	    // FORMATTING

	    addFormatToken('X', 0, 0, 'unix');
	    addFormatToken('x', 0, 0, 'valueOf');

	    // PARSING

	    addRegexToken('x', matchSigned);
	    addRegexToken('X', matchTimestamp);
	    addParseToken('X', function (input, array, config) {
	        config._d = new Date(parseFloat(input, 10) * 1000);
	    });
	    addParseToken('x', function (input, array, config) {
	        config._d = new Date(toInt(input));
	    });

	    // Side effect imports


	    utils_hooks__hooks.version = '2.13.0';

	    setHookCallback(local__createLocal);

	    utils_hooks__hooks.fn                    = momentPrototype;
	    utils_hooks__hooks.min                   = min;
	    utils_hooks__hooks.max                   = max;
	    utils_hooks__hooks.now                   = now;
	    utils_hooks__hooks.utc                   = create_utc__createUTC;
	    utils_hooks__hooks.unix                  = moment__createUnix;
	    utils_hooks__hooks.months                = lists__listMonths;
	    utils_hooks__hooks.isDate                = isDate;
	    utils_hooks__hooks.locale                = locale_locales__getSetGlobalLocale;
	    utils_hooks__hooks.invalid               = valid__createInvalid;
	    utils_hooks__hooks.duration              = create__createDuration;
	    utils_hooks__hooks.isMoment              = isMoment;
	    utils_hooks__hooks.weekdays              = lists__listWeekdays;
	    utils_hooks__hooks.parseZone             = moment__createInZone;
	    utils_hooks__hooks.localeData            = locale_locales__getLocale;
	    utils_hooks__hooks.isDuration            = isDuration;
	    utils_hooks__hooks.monthsShort           = lists__listMonthsShort;
	    utils_hooks__hooks.weekdaysMin           = lists__listWeekdaysMin;
	    utils_hooks__hooks.defineLocale          = defineLocale;
	    utils_hooks__hooks.updateLocale          = updateLocale;
	    utils_hooks__hooks.locales               = locale_locales__listLocales;
	    utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
	    utils_hooks__hooks.normalizeUnits        = normalizeUnits;
	    utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
	    utils_hooks__hooks.prototype             = momentPrototype;

	    var _moment = utils_hooks__hooks;

	    return _moment;

	}));
	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8)(module)))

/***/ },
/* 216 */
/***/ function(module, exports, __webpack_require__) {

	var map = {
		"./af": 217,
		"./af.js": 217,
		"./ar": 218,
		"./ar-ma": 219,
		"./ar-ma.js": 219,
		"./ar-sa": 220,
		"./ar-sa.js": 220,
		"./ar-tn": 221,
		"./ar-tn.js": 221,
		"./ar.js": 218,
		"./az": 222,
		"./az.js": 222,
		"./be": 223,
		"./be.js": 223,
		"./bg": 224,
		"./bg.js": 224,
		"./bn": 225,
		"./bn.js": 225,
		"./bo": 226,
		"./bo.js": 226,
		"./br": 227,
		"./br.js": 227,
		"./bs": 228,
		"./bs.js": 228,
		"./ca": 229,
		"./ca.js": 229,
		"./cs": 230,
		"./cs.js": 230,
		"./cv": 231,
		"./cv.js": 231,
		"./cy": 232,
		"./cy.js": 232,
		"./da": 233,
		"./da.js": 233,
		"./de": 234,
		"./de-at": 235,
		"./de-at.js": 235,
		"./de.js": 234,
		"./dv": 236,
		"./dv.js": 236,
		"./el": 237,
		"./el.js": 237,
		"./en-au": 238,
		"./en-au.js": 238,
		"./en-ca": 239,
		"./en-ca.js": 239,
		"./en-gb": 240,
		"./en-gb.js": 240,
		"./en-ie": 241,
		"./en-ie.js": 241,
		"./en-nz": 242,
		"./en-nz.js": 242,
		"./eo": 243,
		"./eo.js": 243,
		"./es": 244,
		"./es.js": 244,
		"./et": 245,
		"./et.js": 245,
		"./eu": 246,
		"./eu.js": 246,
		"./fa": 247,
		"./fa.js": 247,
		"./fi": 248,
		"./fi.js": 248,
		"./fo": 249,
		"./fo.js": 249,
		"./fr": 250,
		"./fr-ca": 251,
		"./fr-ca.js": 251,
		"./fr-ch": 252,
		"./fr-ch.js": 252,
		"./fr.js": 250,
		"./fy": 253,
		"./fy.js": 253,
		"./gd": 254,
		"./gd.js": 254,
		"./gl": 255,
		"./gl.js": 255,
		"./he": 256,
		"./he.js": 256,
		"./hi": 257,
		"./hi.js": 257,
		"./hr": 258,
		"./hr.js": 258,
		"./hu": 259,
		"./hu.js": 259,
		"./hy-am": 260,
		"./hy-am.js": 260,
		"./id": 261,
		"./id.js": 261,
		"./is": 262,
		"./is.js": 262,
		"./it": 263,
		"./it.js": 263,
		"./ja": 264,
		"./ja.js": 264,
		"./jv": 265,
		"./jv.js": 265,
		"./ka": 266,
		"./ka.js": 266,
		"./kk": 267,
		"./kk.js": 267,
		"./km": 268,
		"./km.js": 268,
		"./ko": 269,
		"./ko.js": 269,
		"./ky": 270,
		"./ky.js": 270,
		"./lb": 271,
		"./lb.js": 271,
		"./lo": 272,
		"./lo.js": 272,
		"./lt": 273,
		"./lt.js": 273,
		"./lv": 274,
		"./lv.js": 274,
		"./me": 275,
		"./me.js": 275,
		"./mk": 276,
		"./mk.js": 276,
		"./ml": 277,
		"./ml.js": 277,
		"./mr": 278,
		"./mr.js": 278,
		"./ms": 279,
		"./ms-my": 280,
		"./ms-my.js": 280,
		"./ms.js": 279,
		"./my": 281,
		"./my.js": 281,
		"./nb": 282,
		"./nb.js": 282,
		"./ne": 283,
		"./ne.js": 283,
		"./nl": 284,
		"./nl.js": 284,
		"./nn": 285,
		"./nn.js": 285,
		"./pa-in": 286,
		"./pa-in.js": 286,
		"./pl": 287,
		"./pl.js": 287,
		"./pt": 288,
		"./pt-br": 289,
		"./pt-br.js": 289,
		"./pt.js": 288,
		"./ro": 290,
		"./ro.js": 290,
		"./ru": 291,
		"./ru.js": 291,
		"./se": 292,
		"./se.js": 292,
		"./si": 293,
		"./si.js": 293,
		"./sk": 294,
		"./sk.js": 294,
		"./sl": 295,
		"./sl.js": 295,
		"./sq": 296,
		"./sq.js": 296,
		"./sr": 297,
		"./sr-cyrl": 298,
		"./sr-cyrl.js": 298,
		"./sr.js": 297,
		"./ss": 299,
		"./ss.js": 299,
		"./sv": 300,
		"./sv.js": 300,
		"./sw": 301,
		"./sw.js": 301,
		"./ta": 302,
		"./ta.js": 302,
		"./te": 303,
		"./te.js": 303,
		"./th": 304,
		"./th.js": 304,
		"./tl-ph": 305,
		"./tl-ph.js": 305,
		"./tlh": 306,
		"./tlh.js": 306,
		"./tr": 307,
		"./tr.js": 307,
		"./tzl": 308,
		"./tzl.js": 308,
		"./tzm": 309,
		"./tzm-latn": 310,
		"./tzm-latn.js": 310,
		"./tzm.js": 309,
		"./uk": 311,
		"./uk.js": 311,
		"./uz": 312,
		"./uz.js": 312,
		"./vi": 313,
		"./vi.js": 313,
		"./x-pseudo": 314,
		"./x-pseudo.js": 314,
		"./zh-cn": 315,
		"./zh-cn.js": 315,
		"./zh-tw": 316,
		"./zh-tw.js": 316
	};
	function webpackContext(req) {
		return __webpack_require__(webpackContextResolve(req));
	};
	function webpackContextResolve(req) {
		return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }());
	};
	webpackContext.keys = function webpackContextKeys() {
		return Object.keys(map);
	};
	webpackContext.resolve = webpackContextResolve;
	module.exports = webpackContext;
	webpackContext.id = 216;


/***/ },
/* 217 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : afrikaans (af)
	//! author : Werner Mollentze : https://github.com/wernerm

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var af = moment.defineLocale('af', {
	        months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
	        weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
	        weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
	        weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
	        meridiemParse: /vm|nm/i,
	        isPM : function (input) {
	            return /^nm$/i.test(input);
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 12) {
	                return isLower ? 'vm' : 'VM';
	            } else {
	                return isLower ? 'nm' : 'NM';
	            }
	        },
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[Vandag om] LT',
	            nextDay : '[Môre om] LT',
	            nextWeek : 'dddd [om] LT',
	            lastDay : '[Gister om] LT',
	            lastWeek : '[Laas] dddd [om] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'oor %s',
	            past : '%s gelede',
	            s : '\'n paar sekondes',
	            m : '\'n minuut',
	            mm : '%d minute',
	            h : '\'n uur',
	            hh : '%d ure',
	            d : '\'n dag',
	            dd : '%d dae',
	            M : '\'n maand',
	            MM : '%d maande',
	            y : '\'n jaar',
	            yy : '%d jaar'
	        },
	        ordinalParse: /\d{1,2}(ste|de)/,
	        ordinal : function (number) {
	            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
	        },
	        week : {
	            dow : 1, // Maandag is die eerste dag van die week.
	            doy : 4  // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
	        }
	    });

	    return af;

	}));

/***/ },
/* 218 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! Locale: Arabic (ar)
	//! Author: Abdel Said: https://github.com/abdelsaid
	//! Changes in months, weekdays: Ahmed Elkhatib
	//! Native plural forms: forabi https://github.com/forabi

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '١',
	        '2': '٢',
	        '3': '٣',
	        '4': '٤',
	        '5': '٥',
	        '6': '٦',
	        '7': '٧',
	        '8': '٨',
	        '9': '٩',
	        '0': '٠'
	    }, numberMap = {
	        '١': '1',
	        '٢': '2',
	        '٣': '3',
	        '٤': '4',
	        '٥': '5',
	        '٦': '6',
	        '٧': '7',
	        '٨': '8',
	        '٩': '9',
	        '٠': '0'
	    }, pluralForm = function (n) {
	        return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
	    }, plurals = {
	        s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
	        m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
	        h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
	        d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
	        M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
	        y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
	    }, pluralize = function (u) {
	        return function (number, withoutSuffix, string, isFuture) {
	            var f = pluralForm(number),
	                str = plurals[u][pluralForm(number)];
	            if (f === 2) {
	                str = str[withoutSuffix ? 0 : 1];
	            }
	            return str.replace(/%d/i, number);
	        };
	    }, months = [
	        'كانون الثاني يناير',
	        'شباط فبراير',
	        'آذار مارس',
	        'نيسان أبريل',
	        'أيار مايو',
	        'حزيران يونيو',
	        'تموز يوليو',
	        'آب أغسطس',
	        'أيلول سبتمبر',
	        'تشرين الأول أكتوبر',
	        'تشرين الثاني نوفمبر',
	        'كانون الأول ديسمبر'
	    ];

	    var ar = moment.defineLocale('ar', {
	        months : months,
	        monthsShort : months,
	        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
	        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'D/\u200FM/\u200FYYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        meridiemParse: /ص|م/,
	        isPM : function (input) {
	            return 'م' === input;
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 12) {
	                return 'ص';
	            } else {
	                return 'م';
	            }
	        },
	        calendar : {
	            sameDay: '[اليوم عند الساعة] LT',
	            nextDay: '[غدًا عند الساعة] LT',
	            nextWeek: 'dddd [عند الساعة] LT',
	            lastDay: '[أمس عند الساعة] LT',
	            lastWeek: 'dddd [عند الساعة] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'بعد %s',
	            past : 'منذ %s',
	            s : pluralize('s'),
	            m : pluralize('m'),
	            mm : pluralize('m'),
	            h : pluralize('h'),
	            hh : pluralize('h'),
	            d : pluralize('d'),
	            dd : pluralize('d'),
	            M : pluralize('M'),
	            MM : pluralize('M'),
	            y : pluralize('y'),
	            yy : pluralize('y')
	        },
	        preparse: function (string) {
	            return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
	                return numberMap[match];
	            }).replace(/،/g, ',');
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            }).replace(/,/g, '،');
	        },
	        week : {
	            dow : 6, // Saturday is the first day of the week.
	            doy : 12  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ar;

	}));

/***/ },
/* 219 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Moroccan Arabic (ar-ma)
	//! author : ElFadili Yassine : https://github.com/ElFadiliY
	//! author : Abdel Said : https://github.com/abdelsaid

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ar_ma = moment.defineLocale('ar-ma', {
	        months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
	        monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
	        weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	        weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
	        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[اليوم على الساعة] LT',
	            nextDay: '[غدا على الساعة] LT',
	            nextWeek: 'dddd [على الساعة] LT',
	            lastDay: '[أمس على الساعة] LT',
	            lastWeek: 'dddd [على الساعة] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'في %s',
	            past : 'منذ %s',
	            s : 'ثوان',
	            m : 'دقيقة',
	            mm : '%d دقائق',
	            h : 'ساعة',
	            hh : '%d ساعات',
	            d : 'يوم',
	            dd : '%d أيام',
	            M : 'شهر',
	            MM : '%d أشهر',
	            y : 'سنة',
	            yy : '%d سنوات'
	        },
	        week : {
	            dow : 6, // Saturday is the first day of the week.
	            doy : 12  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ar_ma;

	}));

/***/ },
/* 220 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Arabic Saudi Arabia (ar-sa)
	//! author : Suhail Alkowaileet : https://github.com/xsoh

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '١',
	        '2': '٢',
	        '3': '٣',
	        '4': '٤',
	        '5': '٥',
	        '6': '٦',
	        '7': '٧',
	        '8': '٨',
	        '9': '٩',
	        '0': '٠'
	    }, numberMap = {
	        '١': '1',
	        '٢': '2',
	        '٣': '3',
	        '٤': '4',
	        '٥': '5',
	        '٦': '6',
	        '٧': '7',
	        '٨': '8',
	        '٩': '9',
	        '٠': '0'
	    };

	    var ar_sa = moment.defineLocale('ar-sa', {
	        months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	        monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
	        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        meridiemParse: /ص|م/,
	        isPM : function (input) {
	            return 'م' === input;
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 12) {
	                return 'ص';
	            } else {
	                return 'م';
	            }
	        },
	        calendar : {
	            sameDay: '[اليوم على الساعة] LT',
	            nextDay: '[غدا على الساعة] LT',
	            nextWeek: 'dddd [على الساعة] LT',
	            lastDay: '[أمس على الساعة] LT',
	            lastWeek: 'dddd [على الساعة] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'في %s',
	            past : 'منذ %s',
	            s : 'ثوان',
	            m : 'دقيقة',
	            mm : '%d دقائق',
	            h : 'ساعة',
	            hh : '%d ساعات',
	            d : 'يوم',
	            dd : '%d أيام',
	            M : 'شهر',
	            MM : '%d أشهر',
	            y : 'سنة',
	            yy : '%d سنوات'
	        },
	        preparse: function (string) {
	            return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
	                return numberMap[match];
	            }).replace(/،/g, ',');
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            }).replace(/,/g, '،');
	        },
	        week : {
	            dow : 6, // Saturday is the first day of the week.
	            doy : 12  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ar_sa;

	}));

/***/ },
/* 221 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale  : Tunisian Arabic (ar-tn)

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ar_tn = moment.defineLocale('ar-tn', {
	        months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	        monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	        weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	        weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
	        weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat: {
	            LT: 'HH:mm',
	            LTS: 'HH:mm:ss',
	            L: 'DD/MM/YYYY',
	            LL: 'D MMMM YYYY',
	            LLL: 'D MMMM YYYY HH:mm',
	            LLLL: 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar: {
	            sameDay: '[اليوم على الساعة] LT',
	            nextDay: '[غدا على الساعة] LT',
	            nextWeek: 'dddd [على الساعة] LT',
	            lastDay: '[أمس على الساعة] LT',
	            lastWeek: 'dddd [على الساعة] LT',
	            sameElse: 'L'
	        },
	        relativeTime: {
	            future: 'في %s',
	            past: 'منذ %s',
	            s: 'ثوان',
	            m: 'دقيقة',
	            mm: '%d دقائق',
	            h: 'ساعة',
	            hh: '%d ساعات',
	            d: 'يوم',
	            dd: '%d أيام',
	            M: 'شهر',
	            MM: '%d أشهر',
	            y: 'سنة',
	            yy: '%d سنوات'
	        },
	        week: {
	            dow: 1, // Monday is the first day of the week.
	            doy: 4 // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return ar_tn;

	}));

/***/ },
/* 222 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : azerbaijani (az)
	//! author : topchiyev : https://github.com/topchiyev

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var suffixes = {
	        1: '-inci',
	        5: '-inci',
	        8: '-inci',
	        70: '-inci',
	        80: '-inci',
	        2: '-nci',
	        7: '-nci',
	        20: '-nci',
	        50: '-nci',
	        3: '-üncü',
	        4: '-üncü',
	        100: '-üncü',
	        6: '-ncı',
	        9: '-uncu',
	        10: '-uncu',
	        30: '-uncu',
	        60: '-ıncı',
	        90: '-ıncı'
	    };

	    var az = moment.defineLocale('az', {
	        months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
	        monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
	        weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
	        weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
	        weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[bugün saat] LT',
	            nextDay : '[sabah saat] LT',
	            nextWeek : '[gələn həftə] dddd [saat] LT',
	            lastDay : '[dünən] LT',
	            lastWeek : '[keçən həftə] dddd [saat] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s sonra',
	            past : '%s əvvəl',
	            s : 'birneçə saniyyə',
	            m : 'bir dəqiqə',
	            mm : '%d dəqiqə',
	            h : 'bir saat',
	            hh : '%d saat',
	            d : 'bir gün',
	            dd : '%d gün',
	            M : 'bir ay',
	            MM : '%d ay',
	            y : 'bir il',
	            yy : '%d il'
	        },
	        meridiemParse: /gecə|səhər|gündüz|axşam/,
	        isPM : function (input) {
	            return /^(gündüz|axşam)$/.test(input);
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'gecə';
	            } else if (hour < 12) {
	                return 'səhər';
	            } else if (hour < 17) {
	                return 'gündüz';
	            } else {
	                return 'axşam';
	            }
	        },
	        ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
	        ordinal : function (number) {
	            if (number === 0) {  // special case for zero
	                return number + '-ıncı';
	            }
	            var a = number % 10,
	                b = number % 100 - a,
	                c = number >= 100 ? 100 : null;
	            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return az;

	}));

/***/ },
/* 223 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : belarusian (be)
	//! author : Dmitry Demidov : https://github.com/demidov91
	//! author: Praleska: http://praleska.pro/
	//! Author : Menelion Elensúle : https://github.com/Oire

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function plural(word, num) {
	        var forms = word.split('_');
	        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
	    }
	    function relativeTimeWithPlural(number, withoutSuffix, key) {
	        var format = {
	            'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
	            'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
	            'dd': 'дзень_дні_дзён',
	            'MM': 'месяц_месяцы_месяцаў',
	            'yy': 'год_гады_гадоў'
	        };
	        if (key === 'm') {
	            return withoutSuffix ? 'хвіліна' : 'хвіліну';
	        }
	        else if (key === 'h') {
	            return withoutSuffix ? 'гадзіна' : 'гадзіну';
	        }
	        else {
	            return number + ' ' + plural(format[key], +number);
	        }
	    }

	    var be = moment.defineLocale('be', {
	        months : {
	            format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
	            standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
	        },
	        monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
	        weekdays : {
	            format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
	            standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
	            isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
	        },
	        weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
	        weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY г.',
	            LLL : 'D MMMM YYYY г., HH:mm',
	            LLLL : 'dddd, D MMMM YYYY г., HH:mm'
	        },
	        calendar : {
	            sameDay: '[Сёння ў] LT',
	            nextDay: '[Заўтра ў] LT',
	            lastDay: '[Учора ў] LT',
	            nextWeek: function () {
	                return '[У] dddd [ў] LT';
	            },
	            lastWeek: function () {
	                switch (this.day()) {
	                case 0:
	                case 3:
	                case 5:
	                case 6:
	                    return '[У мінулую] dddd [ў] LT';
	                case 1:
	                case 2:
	                case 4:
	                    return '[У мінулы] dddd [ў] LT';
	                }
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'праз %s',
	            past : '%s таму',
	            s : 'некалькі секунд',
	            m : relativeTimeWithPlural,
	            mm : relativeTimeWithPlural,
	            h : relativeTimeWithPlural,
	            hh : relativeTimeWithPlural,
	            d : 'дзень',
	            dd : relativeTimeWithPlural,
	            M : 'месяц',
	            MM : relativeTimeWithPlural,
	            y : 'год',
	            yy : relativeTimeWithPlural
	        },
	        meridiemParse: /ночы|раніцы|дня|вечара/,
	        isPM : function (input) {
	            return /^(дня|вечара)$/.test(input);
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'ночы';
	            } else if (hour < 12) {
	                return 'раніцы';
	            } else if (hour < 17) {
	                return 'дня';
	            } else {
	                return 'вечара';
	            }
	        },
	        ordinalParse: /\d{1,2}-(і|ы|га)/,
	        ordinal: function (number, period) {
	            switch (period) {
	            case 'M':
	            case 'd':
	            case 'DDD':
	            case 'w':
	            case 'W':
	                return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
	            case 'D':
	                return number + '-га';
	            default:
	                return number;
	            }
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return be;

	}));

/***/ },
/* 224 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : bulgarian (bg)
	//! author : Krasen Borisov : https://github.com/kraz

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var bg = moment.defineLocale('bg', {
	        months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
	        monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
	        weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
	        weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
	        weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'D.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY H:mm',
	            LLLL : 'dddd, D MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay : '[Днес в] LT',
	            nextDay : '[Утре в] LT',
	            nextWeek : 'dddd [в] LT',
	            lastDay : '[Вчера в] LT',
	            lastWeek : function () {
	                switch (this.day()) {
	                case 0:
	                case 3:
	                case 6:
	                    return '[В изминалата] dddd [в] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[В изминалия] dddd [в] LT';
	                }
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'след %s',
	            past : 'преди %s',
	            s : 'няколко секунди',
	            m : 'минута',
	            mm : '%d минути',
	            h : 'час',
	            hh : '%d часа',
	            d : 'ден',
	            dd : '%d дни',
	            M : 'месец',
	            MM : '%d месеца',
	            y : 'година',
	            yy : '%d години'
	        },
	        ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
	        ordinal : function (number) {
	            var lastDigit = number % 10,
	                last2Digits = number % 100;
	            if (number === 0) {
	                return number + '-ев';
	            } else if (last2Digits === 0) {
	                return number + '-ен';
	            } else if (last2Digits > 10 && last2Digits < 20) {
	                return number + '-ти';
	            } else if (lastDigit === 1) {
	                return number + '-ви';
	            } else if (lastDigit === 2) {
	                return number + '-ри';
	            } else if (lastDigit === 7 || lastDigit === 8) {
	                return number + '-ми';
	            } else {
	                return number + '-ти';
	            }
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return bg;

	}));

/***/ },
/* 225 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Bengali (bn)
	//! author : Kaushik Gandhi : https://github.com/kaushikgandhi

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '১',
	        '2': '২',
	        '3': '৩',
	        '4': '৪',
	        '5': '৫',
	        '6': '৬',
	        '7': '৭',
	        '8': '৮',
	        '9': '৯',
	        '0': '০'
	    },
	    numberMap = {
	        '১': '1',
	        '২': '2',
	        '৩': '3',
	        '৪': '4',
	        '৫': '5',
	        '৬': '6',
	        '৭': '7',
	        '৮': '8',
	        '৯': '9',
	        '০': '0'
	    };

	    var bn = moment.defineLocale('bn', {
	        months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
	        monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'),
	        weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার'.split('_'),
	        weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি'.split('_'),
	        weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'),
	        longDateFormat : {
	            LT : 'A h:mm সময়',
	            LTS : 'A h:mm:ss সময়',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, A h:mm সময়',
	            LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
	        },
	        calendar : {
	            sameDay : '[আজ] LT',
	            nextDay : '[আগামীকাল] LT',
	            nextWeek : 'dddd, LT',
	            lastDay : '[গতকাল] LT',
	            lastWeek : '[গত] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s পরে',
	            past : '%s আগে',
	            s : 'কয়েক সেকেন্ড',
	            m : 'এক মিনিট',
	            mm : '%d মিনিট',
	            h : 'এক ঘন্টা',
	            hh : '%d ঘন্টা',
	            d : 'এক দিন',
	            dd : '%d দিন',
	            M : 'এক মাস',
	            MM : '%d মাস',
	            y : 'এক বছর',
	            yy : '%d বছর'
	        },
	        preparse: function (string) {
	            return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if ((meridiem === 'রাত' && hour >= 4) ||
	                    (meridiem === 'দুপুর' && hour < 5) ||
	                    meridiem === 'বিকাল') {
	                return hour + 12;
	            } else {
	                return hour;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'রাত';
	            } else if (hour < 10) {
	                return 'সকাল';
	            } else if (hour < 17) {
	                return 'দুপুর';
	            } else if (hour < 20) {
	                return 'বিকাল';
	            } else {
	                return 'রাত';
	            }
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return bn;

	}));

/***/ },
/* 226 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : tibetan (bo)
	//! author : Thupten N. Chakrishar : https://github.com/vajradog

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '༡',
	        '2': '༢',
	        '3': '༣',
	        '4': '༤',
	        '5': '༥',
	        '6': '༦',
	        '7': '༧',
	        '8': '༨',
	        '9': '༩',
	        '0': '༠'
	    },
	    numberMap = {
	        '༡': '1',
	        '༢': '2',
	        '༣': '3',
	        '༤': '4',
	        '༥': '5',
	        '༦': '6',
	        '༧': '7',
	        '༨': '8',
	        '༩': '9',
	        '༠': '0'
	    };

	    var bo = moment.defineLocale('bo', {
	        months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
	        monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
	        weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
	        weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
	        weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
	        longDateFormat : {
	            LT : 'A h:mm',
	            LTS : 'A h:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, A h:mm',
	            LLLL : 'dddd, D MMMM YYYY, A h:mm'
	        },
	        calendar : {
	            sameDay : '[དི་རིང] LT',
	            nextDay : '[སང་ཉིན] LT',
	            nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
	            lastDay : '[ཁ་སང] LT',
	            lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s ལ་',
	            past : '%s སྔན་ལ',
	            s : 'ལམ་སང',
	            m : 'སྐར་མ་གཅིག',
	            mm : '%d སྐར་མ',
	            h : 'ཆུ་ཚོད་གཅིག',
	            hh : '%d ཆུ་ཚོད',
	            d : 'ཉིན་གཅིག',
	            dd : '%d ཉིན་',
	            M : 'ཟླ་བ་གཅིག',
	            MM : '%d ཟླ་བ',
	            y : 'ལོ་གཅིག',
	            yy : '%d ལོ'
	        },
	        preparse: function (string) {
	            return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
	                    (meridiem === 'ཉིན་གུང' && hour < 5) ||
	                    meridiem === 'དགོང་དག') {
	                return hour + 12;
	            } else {
	                return hour;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'མཚན་མོ';
	            } else if (hour < 10) {
	                return 'ཞོགས་ཀས';
	            } else if (hour < 17) {
	                return 'ཉིན་གུང';
	            } else if (hour < 20) {
	                return 'དགོང་དག';
	            } else {
	                return 'མཚན་མོ';
	            }
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return bo;

	}));

/***/ },
/* 227 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : breton (br)
	//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function relativeTimeWithMutation(number, withoutSuffix, key) {
	        var format = {
	            'mm': 'munutenn',
	            'MM': 'miz',
	            'dd': 'devezh'
	        };
	        return number + ' ' + mutation(format[key], number);
	    }
	    function specialMutationForYears(number) {
	        switch (lastNumber(number)) {
	        case 1:
	        case 3:
	        case 4:
	        case 5:
	        case 9:
	            return number + ' bloaz';
	        default:
	            return number + ' vloaz';
	        }
	    }
	    function lastNumber(number) {
	        if (number > 9) {
	            return lastNumber(number % 10);
	        }
	        return number;
	    }
	    function mutation(text, number) {
	        if (number === 2) {
	            return softMutation(text);
	        }
	        return text;
	    }
	    function softMutation(text) {
	        var mutationTable = {
	            'm': 'v',
	            'b': 'v',
	            'd': 'z'
	        };
	        if (mutationTable[text.charAt(0)] === undefined) {
	            return text;
	        }
	        return mutationTable[text.charAt(0)] + text.substring(1);
	    }

	    var br = moment.defineLocale('br', {
	        months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
	        monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
	        weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
	        weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
	        weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'h[e]mm A',
	            LTS : 'h[e]mm:ss A',
	            L : 'DD/MM/YYYY',
	            LL : 'D [a viz] MMMM YYYY',
	            LLL : 'D [a viz] MMMM YYYY h[e]mm A',
	            LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
	        },
	        calendar : {
	            sameDay : '[Hiziv da] LT',
	            nextDay : '[Warc\'hoazh da] LT',
	            nextWeek : 'dddd [da] LT',
	            lastDay : '[Dec\'h da] LT',
	            lastWeek : 'dddd [paset da] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'a-benn %s',
	            past : '%s \'zo',
	            s : 'un nebeud segondennoù',
	            m : 'ur vunutenn',
	            mm : relativeTimeWithMutation,
	            h : 'un eur',
	            hh : '%d eur',
	            d : 'un devezh',
	            dd : relativeTimeWithMutation,
	            M : 'ur miz',
	            MM : relativeTimeWithMutation,
	            y : 'ur bloaz',
	            yy : specialMutationForYears
	        },
	        ordinalParse: /\d{1,2}(añ|vet)/,
	        ordinal : function (number) {
	            var output = (number === 1) ? 'añ' : 'vet';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return br;

	}));

/***/ },
/* 228 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : bosnian (bs)
	//! author : Nedim Cholich : https://github.com/frontyard
	//! based on (hr) translation by Bojan Marković

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function translate(number, withoutSuffix, key) {
	        var result = number + ' ';
	        switch (key) {
	        case 'm':
	            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
	        case 'mm':
	            if (number === 1) {
	                result += 'minuta';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'minute';
	            } else {
	                result += 'minuta';
	            }
	            return result;
	        case 'h':
	            return withoutSuffix ? 'jedan sat' : 'jednog sata';
	        case 'hh':
	            if (number === 1) {
	                result += 'sat';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'sata';
	            } else {
	                result += 'sati';
	            }
	            return result;
	        case 'dd':
	            if (number === 1) {
	                result += 'dan';
	            } else {
	                result += 'dana';
	            }
	            return result;
	        case 'MM':
	            if (number === 1) {
	                result += 'mjesec';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'mjeseca';
	            } else {
	                result += 'mjeseci';
	            }
	            return result;
	        case 'yy':
	            if (number === 1) {
	                result += 'godina';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'godine';
	            } else {
	                result += 'godina';
	            }
	            return result;
	        }
	    }

	    var bs = moment.defineLocale('bs', {
	        months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
	        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
	        monthsParseExact: true,
	        weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
	        weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
	        weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD. MM. YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY H:mm',
	            LLLL : 'dddd, D. MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay  : '[danas u] LT',
	            nextDay  : '[sutra u] LT',
	            nextWeek : function () {
	                switch (this.day()) {
	                case 0:
	                    return '[u] [nedjelju] [u] LT';
	                case 3:
	                    return '[u] [srijedu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	                }
	            },
	            lastDay  : '[jučer u] LT',
	            lastWeek : function () {
	                switch (this.day()) {
	                case 0:
	                case 3:
	                    return '[prošlu] dddd [u] LT';
	                case 6:
	                    return '[prošle] [subote] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[prošli] dddd [u] LT';
	                }
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'za %s',
	            past   : 'prije %s',
	            s      : 'par sekundi',
	            m      : translate,
	            mm     : translate,
	            h      : translate,
	            hh     : translate,
	            d      : 'dan',
	            dd     : translate,
	            M      : 'mjesec',
	            MM     : translate,
	            y      : 'godinu',
	            yy     : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return bs;

	}));

/***/ },
/* 229 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : catalan (ca)
	//! author : Juan G. Hurtado : https://github.com/juanghurtado

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ca = moment.defineLocale('ca', {
	        months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
	        monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
	        weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
	        weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY H:mm',
	            LLLL : 'dddd D MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay : function () {
	                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	            },
	            nextDay : function () {
	                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	            },
	            nextWeek : function () {
	                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	            },
	            lastDay : function () {
	                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	            },
	            lastWeek : function () {
	                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'en %s',
	            past : 'fa %s',
	            s : 'uns segons',
	            m : 'un minut',
	            mm : '%d minuts',
	            h : 'una hora',
	            hh : '%d hores',
	            d : 'un dia',
	            dd : '%d dies',
	            M : 'un mes',
	            MM : '%d mesos',
	            y : 'un any',
	            yy : '%d anys'
	        },
	        ordinalParse: /\d{1,2}(r|n|t|è|a)/,
	        ordinal : function (number, period) {
	            var output = (number === 1) ? 'r' :
	                (number === 2) ? 'n' :
	                (number === 3) ? 'r' :
	                (number === 4) ? 't' : 'è';
	            if (period === 'w' || period === 'W') {
	                output = 'a';
	            }
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return ca;

	}));

/***/ },
/* 230 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : czech (cs)
	//! author : petrbela : https://github.com/petrbela

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'),
	        monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
	    function plural(n) {
	        return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
	    }
	    function translate(number, withoutSuffix, key, isFuture) {
	        var result = number + ' ';
	        switch (key) {
	        case 's':  // a few seconds / in a few seconds / a few seconds ago
	            return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
	        case 'm':  // a minute / in a minute / a minute ago
	            return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
	        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'minuty' : 'minut');
	            } else {
	                return result + 'minutami';
	            }
	            break;
	        case 'h':  // an hour / in an hour / an hour ago
	            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
	        case 'hh': // 9 hours / in 9 hours / 9 hours ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'hodiny' : 'hodin');
	            } else {
	                return result + 'hodinami';
	            }
	            break;
	        case 'd':  // a day / in a day / a day ago
	            return (withoutSuffix || isFuture) ? 'den' : 'dnem';
	        case 'dd': // 9 days / in 9 days / 9 days ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'dny' : 'dní');
	            } else {
	                return result + 'dny';
	            }
	            break;
	        case 'M':  // a month / in a month / a month ago
	            return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
	        case 'MM': // 9 months / in 9 months / 9 months ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'měsíce' : 'měsíců');
	            } else {
	                return result + 'měsíci';
	            }
	            break;
	        case 'y':  // a year / in a year / a year ago
	            return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
	        case 'yy': // 9 years / in 9 years / 9 years ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'roky' : 'let');
	            } else {
	                return result + 'lety';
	            }
	            break;
	        }
	    }

	    var cs = moment.defineLocale('cs', {
	        months : months,
	        monthsShort : monthsShort,
	        monthsParse : (function (months, monthsShort) {
	            var i, _monthsParse = [];
	            for (i = 0; i < 12; i++) {
	                // use custom parser to solve problem with July (červenec)
	                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
	            }
	            return _monthsParse;
	        }(months, monthsShort)),
	        shortMonthsParse : (function (monthsShort) {
	            var i, _shortMonthsParse = [];
	            for (i = 0; i < 12; i++) {
	                _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i');
	            }
	            return _shortMonthsParse;
	        }(monthsShort)),
	        longMonthsParse : (function (months) {
	            var i, _longMonthsParse = [];
	            for (i = 0; i < 12; i++) {
	                _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i');
	            }
	            return _longMonthsParse;
	        }(months)),
	        weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
	        weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'),
	        weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
	        longDateFormat : {
	            LT: 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY H:mm',
	            LLLL : 'dddd D. MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay: '[dnes v] LT',
	            nextDay: '[zítra v] LT',
	            nextWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[v neděli v] LT';
	                case 1:
	                case 2:
	                    return '[v] dddd [v] LT';
	                case 3:
	                    return '[ve středu v] LT';
	                case 4:
	                    return '[ve čtvrtek v] LT';
	                case 5:
	                    return '[v pátek v] LT';
	                case 6:
	                    return '[v sobotu v] LT';
	                }
	            },
	            lastDay: '[včera v] LT',
	            lastWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[minulou neděli v] LT';
	                case 1:
	                case 2:
	                    return '[minulé] dddd [v] LT';
	                case 3:
	                    return '[minulou středu v] LT';
	                case 4:
	                case 5:
	                    return '[minulý] dddd [v] LT';
	                case 6:
	                    return '[minulou sobotu v] LT';
	                }
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'za %s',
	            past : 'před %s',
	            s : translate,
	            m : translate,
	            mm : translate,
	            h : translate,
	            hh : translate,
	            d : translate,
	            dd : translate,
	            M : translate,
	            MM : translate,
	            y : translate,
	            yy : translate
	        },
	        ordinalParse : /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return cs;

	}));

/***/ },
/* 231 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : chuvash (cv)
	//! author : Anatoly Mironov : https://github.com/mirontoli

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var cv = moment.defineLocale('cv', {
	        months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'),
	        monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'),
	        weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'),
	        weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'),
	        weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD-MM-YYYY',
	            LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
	            LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
	            LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm'
	        },
	        calendar : {
	            sameDay: '[Паян] LT [сехетре]',
	            nextDay: '[Ыран] LT [сехетре]',
	            lastDay: '[Ӗнер] LT [сехетре]',
	            nextWeek: '[Ҫитес] dddd LT [сехетре]',
	            lastWeek: '[Иртнӗ] dddd LT [сехетре]',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : function (output) {
	                var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран';
	                return output + affix;
	            },
	            past : '%s каялла',
	            s : 'пӗр-ик ҫеккунт',
	            m : 'пӗр минут',
	            mm : '%d минут',
	            h : 'пӗр сехет',
	            hh : '%d сехет',
	            d : 'пӗр кун',
	            dd : '%d кун',
	            M : 'пӗр уйӑх',
	            MM : '%d уйӑх',
	            y : 'пӗр ҫул',
	            yy : '%d ҫул'
	        },
	        ordinalParse: /\d{1,2}-мӗш/,
	        ordinal : '%d-мӗш',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return cv;

	}));

/***/ },
/* 232 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Welsh (cy)
	//! author : Robert Allen

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var cy = moment.defineLocale('cy', {
	        months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'),
	        monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'),
	        weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'),
	        weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
	        weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
	        weekdaysParseExact : true,
	        // time formats are the same as en-gb
	        longDateFormat: {
	            LT: 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L: 'DD/MM/YYYY',
	            LL: 'D MMMM YYYY',
	            LLL: 'D MMMM YYYY HH:mm',
	            LLLL: 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar: {
	            sameDay: '[Heddiw am] LT',
	            nextDay: '[Yfory am] LT',
	            nextWeek: 'dddd [am] LT',
	            lastDay: '[Ddoe am] LT',
	            lastWeek: 'dddd [diwethaf am] LT',
	            sameElse: 'L'
	        },
	        relativeTime: {
	            future: 'mewn %s',
	            past: '%s yn ôl',
	            s: 'ychydig eiliadau',
	            m: 'munud',
	            mm: '%d munud',
	            h: 'awr',
	            hh: '%d awr',
	            d: 'diwrnod',
	            dd: '%d diwrnod',
	            M: 'mis',
	            MM: '%d mis',
	            y: 'blwyddyn',
	            yy: '%d flynedd'
	        },
	        ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
	        // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
	        ordinal: function (number) {
	            var b = number,
	                output = '',
	                lookup = [
	                    '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
	                    'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
	                ];
	            if (b > 20) {
	                if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
	                    output = 'fed'; // not 30ain, 70ain or 90ain
	                } else {
	                    output = 'ain';
	                }
	            } else if (b > 0) {
	                output = lookup[b];
	            }
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return cy;

	}));

/***/ },
/* 233 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : danish (da)
	//! author : Ulrik Nielsen : https://github.com/mrbase

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var da = moment.defineLocale('da', {
	        months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'),
	        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
	        weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
	        weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'),
	        weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY HH:mm',
	            LLLL : 'dddd [d.] D. MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[I dag kl.] LT',
	            nextDay : '[I morgen kl.] LT',
	            nextWeek : 'dddd [kl.] LT',
	            lastDay : '[I går kl.] LT',
	            lastWeek : '[sidste] dddd [kl] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'om %s',
	            past : '%s siden',
	            s : 'få sekunder',
	            m : 'et minut',
	            mm : '%d minutter',
	            h : 'en time',
	            hh : '%d timer',
	            d : 'en dag',
	            dd : '%d dage',
	            M : 'en måned',
	            MM : '%d måneder',
	            y : 'et år',
	            yy : '%d år'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return da;

	}));

/***/ },
/* 234 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : german (de)
	//! author : lluchs : https://github.com/lluchs
	//! author: Menelion Elensúle: https://github.com/Oire
	//! author : Mikolaj Dadela : https://github.com/mik01aj

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function processRelativeTime(number, withoutSuffix, key, isFuture) {
	        var format = {
	            'm': ['eine Minute', 'einer Minute'],
	            'h': ['eine Stunde', 'einer Stunde'],
	            'd': ['ein Tag', 'einem Tag'],
	            'dd': [number + ' Tage', number + ' Tagen'],
	            'M': ['ein Monat', 'einem Monat'],
	            'MM': [number + ' Monate', number + ' Monaten'],
	            'y': ['ein Jahr', 'einem Jahr'],
	            'yy': [number + ' Jahre', number + ' Jahren']
	        };
	        return withoutSuffix ? format[key][0] : format[key][1];
	    }

	    var de = moment.defineLocale('de', {
	        months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
	        monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
	        weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
	        weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT: 'HH:mm',
	            LTS: 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY HH:mm',
	            LLLL : 'dddd, D. MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[heute um] LT [Uhr]',
	            sameElse: 'L',
	            nextDay: '[morgen um] LT [Uhr]',
	            nextWeek: 'dddd [um] LT [Uhr]',
	            lastDay: '[gestern um] LT [Uhr]',
	            lastWeek: '[letzten] dddd [um] LT [Uhr]'
	        },
	        relativeTime : {
	            future : 'in %s',
	            past : 'vor %s',
	            s : 'ein paar Sekunden',
	            m : processRelativeTime,
	            mm : '%d Minuten',
	            h : processRelativeTime,
	            hh : '%d Stunden',
	            d : processRelativeTime,
	            dd : processRelativeTime,
	            M : processRelativeTime,
	            MM : processRelativeTime,
	            y : processRelativeTime,
	            yy : processRelativeTime
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return de;

	}));

/***/ },
/* 235 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : austrian german (de-at)
	//! author : lluchs : https://github.com/lluchs
	//! author: Menelion Elensúle: https://github.com/Oire
	//! author : Martin Groller : https://github.com/MadMG
	//! author : Mikolaj Dadela : https://github.com/mik01aj

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function processRelativeTime(number, withoutSuffix, key, isFuture) {
	        var format = {
	            'm': ['eine Minute', 'einer Minute'],
	            'h': ['eine Stunde', 'einer Stunde'],
	            'd': ['ein Tag', 'einem Tag'],
	            'dd': [number + ' Tage', number + ' Tagen'],
	            'M': ['ein Monat', 'einem Monat'],
	            'MM': [number + ' Monate', number + ' Monaten'],
	            'y': ['ein Jahr', 'einem Jahr'],
	            'yy': [number + ' Jahre', number + ' Jahren']
	        };
	        return withoutSuffix ? format[key][0] : format[key][1];
	    }

	    var de_at = moment.defineLocale('de-at', {
	        months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
	        monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
	        weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
	        weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT: 'HH:mm',
	            LTS: 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY HH:mm',
	            LLLL : 'dddd, D. MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[heute um] LT [Uhr]',
	            sameElse: 'L',
	            nextDay: '[morgen um] LT [Uhr]',
	            nextWeek: 'dddd [um] LT [Uhr]',
	            lastDay: '[gestern um] LT [Uhr]',
	            lastWeek: '[letzten] dddd [um] LT [Uhr]'
	        },
	        relativeTime : {
	            future : 'in %s',
	            past : 'vor %s',
	            s : 'ein paar Sekunden',
	            m : processRelativeTime,
	            mm : '%d Minuten',
	            h : processRelativeTime,
	            hh : '%d Stunden',
	            d : processRelativeTime,
	            dd : processRelativeTime,
	            M : processRelativeTime,
	            MM : processRelativeTime,
	            y : processRelativeTime,
	            yy : processRelativeTime
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return de_at;

	}));

/***/ },
/* 236 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : dhivehi (dv)
	//! author : Jawish Hameed : https://github.com/jawish

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var months = [
	        'ޖެނުއަރީ',
	        'ފެބްރުއަރީ',
	        'މާރިޗު',
	        'އޭޕްރީލު',
	        'މޭ',
	        'ޖޫން',
	        'ޖުލައި',
	        'އޯގަސްޓު',
	        'ސެޕްޓެމްބަރު',
	        'އޮކްޓޯބަރު',
	        'ނޮވެމްބަރު',
	        'ޑިސެމްބަރު'
	    ], weekdays = [
	        'އާދިއްތަ',
	        'ހޯމަ',
	        'އަންގާރަ',
	        'ބުދަ',
	        'ބުރާސްފަތި',
	        'ހުކުރު',
	        'ހޮނިހިރު'
	    ];

	    var dv = moment.defineLocale('dv', {
	        months : months,
	        monthsShort : months,
	        weekdays : weekdays,
	        weekdaysShort : weekdays,
	        weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'),
	        longDateFormat : {

	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'D/M/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        meridiemParse: /މކ|މފ/,
	        isPM : function (input) {
	            return 'މފ' === input;
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 12) {
	                return 'މކ';
	            } else {
	                return 'މފ';
	            }
	        },
	        calendar : {
	            sameDay : '[މިއަދު] LT',
	            nextDay : '[މާދަމާ] LT',
	            nextWeek : 'dddd LT',
	            lastDay : '[އިއްޔެ] LT',
	            lastWeek : '[ފާއިތުވި] dddd LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'ތެރޭގައި %s',
	            past : 'ކުރިން %s',
	            s : 'ސިކުންތުކޮޅެއް',
	            m : 'މިނިޓެއް',
	            mm : 'މިނިޓު %d',
	            h : 'ގަޑިއިރެއް',
	            hh : 'ގަޑިއިރު %d',
	            d : 'ދުވަހެއް',
	            dd : 'ދުވަސް %d',
	            M : 'މަހެއް',
	            MM : 'މަސް %d',
	            y : 'އަހަރެއް',
	            yy : 'އަހަރު %d'
	        },
	        preparse: function (string) {
	            return string.replace(/،/g, ',');
	        },
	        postformat: function (string) {
	            return string.replace(/,/g, '،');
	        },
	        week : {
	            dow : 7,  // Sunday is the first day of the week.
	            doy : 12  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return dv;

	}));

/***/ },
/* 237 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : modern greek (el)
	//! author : Aggelos Karalias : https://github.com/mehiel

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';

	    function isFunction(input) {
	        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
	    }


	    var el = moment.defineLocale('el', {
	        monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'),
	        monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'),
	        months : function (momentToFormat, format) {
	            if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM'
	                return this._monthsGenitiveEl[momentToFormat.month()];
	            } else {
	                return this._monthsNominativeEl[momentToFormat.month()];
	            }
	        },
	        monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'),
	        weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'),
	        weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'),
	        weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'),
	        meridiem : function (hours, minutes, isLower) {
	            if (hours > 11) {
	                return isLower ? 'μμ' : 'ΜΜ';
	            } else {
	                return isLower ? 'πμ' : 'ΠΜ';
	            }
	        },
	        isPM : function (input) {
	            return ((input + '').toLowerCase()[0] === 'μ');
	        },
	        meridiemParse : /[ΠΜ]\.?Μ?\.?/i,
	        longDateFormat : {
	            LT : 'h:mm A',
	            LTS : 'h:mm:ss A',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY h:mm A',
	            LLLL : 'dddd, D MMMM YYYY h:mm A'
	        },
	        calendarEl : {
	            sameDay : '[Σήμερα {}] LT',
	            nextDay : '[Αύριο {}] LT',
	            nextWeek : 'dddd [{}] LT',
	            lastDay : '[Χθες {}] LT',
	            lastWeek : function () {
	                switch (this.day()) {
	                    case 6:
	                        return '[το προηγούμενο] dddd [{}] LT';
	                    default:
	                        return '[την προηγούμενη] dddd [{}] LT';
	                }
	            },
	            sameElse : 'L'
	        },
	        calendar : function (key, mom) {
	            var output = this._calendarEl[key],
	                hours = mom && mom.hours();
	            if (isFunction(output)) {
	                output = output.apply(mom);
	            }
	            return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις'));
	        },
	        relativeTime : {
	            future : 'σε %s',
	            past : '%s πριν',
	            s : 'λίγα δευτερόλεπτα',
	            m : 'ένα λεπτό',
	            mm : '%d λεπτά',
	            h : 'μία ώρα',
	            hh : '%d ώρες',
	            d : 'μία μέρα',
	            dd : '%d μέρες',
	            M : 'ένας μήνας',
	            MM : '%d μήνες',
	            y : 'ένας χρόνος',
	            yy : '%d χρόνια'
	        },
	        ordinalParse: /\d{1,2}η/,
	        ordinal: '%dη',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4st is the first week of the year.
	        }
	    });

	    return el;

	}));

/***/ },
/* 238 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : australian english (en-au)

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var en_au = moment.defineLocale('en-au', {
	        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	        longDateFormat : {
	            LT : 'h:mm A',
	            LTS : 'h:mm:ss A',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY h:mm A',
	            LLLL : 'dddd, D MMMM YYYY h:mm A'
	        },
	        calendar : {
	            sameDay : '[Today at] LT',
	            nextDay : '[Tomorrow at] LT',
	            nextWeek : 'dddd [at] LT',
	            lastDay : '[Yesterday at] LT',
	            lastWeek : '[Last] dddd [at] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'in %s',
	            past : '%s ago',
	            s : 'a few seconds',
	            m : 'a minute',
	            mm : '%d minutes',
	            h : 'an hour',
	            hh : '%d hours',
	            d : 'a day',
	            dd : '%d days',
	            M : 'a month',
	            MM : '%d months',
	            y : 'a year',
	            yy : '%d years'
	        },
	        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (~~(number % 100 / 10) === 1) ? 'th' :
	                (b === 1) ? 'st' :
	                (b === 2) ? 'nd' :
	                (b === 3) ? 'rd' : 'th';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return en_au;

	}));

/***/ },
/* 239 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : canadian english (en-ca)
	//! author : Jonathan Abourbih : https://github.com/jonbca

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var en_ca = moment.defineLocale('en-ca', {
	        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	        longDateFormat : {
	            LT : 'h:mm A',
	            LTS : 'h:mm:ss A',
	            L : 'YYYY-MM-DD',
	            LL : 'MMMM D, YYYY',
	            LLL : 'MMMM D, YYYY h:mm A',
	            LLLL : 'dddd, MMMM D, YYYY h:mm A'
	        },
	        calendar : {
	            sameDay : '[Today at] LT',
	            nextDay : '[Tomorrow at] LT',
	            nextWeek : 'dddd [at] LT',
	            lastDay : '[Yesterday at] LT',
	            lastWeek : '[Last] dddd [at] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'in %s',
	            past : '%s ago',
	            s : 'a few seconds',
	            m : 'a minute',
	            mm : '%d minutes',
	            h : 'an hour',
	            hh : '%d hours',
	            d : 'a day',
	            dd : '%d days',
	            M : 'a month',
	            MM : '%d months',
	            y : 'a year',
	            yy : '%d years'
	        },
	        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (~~(number % 100 / 10) === 1) ? 'th' :
	                (b === 1) ? 'st' :
	                (b === 2) ? 'nd' :
	                (b === 3) ? 'rd' : 'th';
	            return number + output;
	        }
	    });

	    return en_ca;

	}));

/***/ },
/* 240 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : great britain english (en-gb)
	//! author : Chris Gedrim : https://github.com/chrisgedrim

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var en_gb = moment.defineLocale('en-gb', {
	        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[Today at] LT',
	            nextDay : '[Tomorrow at] LT',
	            nextWeek : 'dddd [at] LT',
	            lastDay : '[Yesterday at] LT',
	            lastWeek : '[Last] dddd [at] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'in %s',
	            past : '%s ago',
	            s : 'a few seconds',
	            m : 'a minute',
	            mm : '%d minutes',
	            h : 'an hour',
	            hh : '%d hours',
	            d : 'a day',
	            dd : '%d days',
	            M : 'a month',
	            MM : '%d months',
	            y : 'a year',
	            yy : '%d years'
	        },
	        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (~~(number % 100 / 10) === 1) ? 'th' :
	                (b === 1) ? 'st' :
	                (b === 2) ? 'nd' :
	                (b === 3) ? 'rd' : 'th';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return en_gb;

	}));

/***/ },
/* 241 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Irish english (en-ie)
	//! author : Chris Cartlidge : https://github.com/chriscartlidge

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var en_ie = moment.defineLocale('en-ie', {
	        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD-MM-YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[Today at] LT',
	            nextDay : '[Tomorrow at] LT',
	            nextWeek : 'dddd [at] LT',
	            lastDay : '[Yesterday at] LT',
	            lastWeek : '[Last] dddd [at] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'in %s',
	            past : '%s ago',
	            s : 'a few seconds',
	            m : 'a minute',
	            mm : '%d minutes',
	            h : 'an hour',
	            hh : '%d hours',
	            d : 'a day',
	            dd : '%d days',
	            M : 'a month',
	            MM : '%d months',
	            y : 'a year',
	            yy : '%d years'
	        },
	        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (~~(number % 100 / 10) === 1) ? 'th' :
	                (b === 1) ? 'st' :
	                (b === 2) ? 'nd' :
	                (b === 3) ? 'rd' : 'th';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return en_ie;

	}));

/***/ },
/* 242 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : New Zealand english (en-nz)

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var en_nz = moment.defineLocale('en-nz', {
	        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	        longDateFormat : {
	            LT : 'h:mm A',
	            LTS : 'h:mm:ss A',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY h:mm A',
	            LLLL : 'dddd, D MMMM YYYY h:mm A'
	        },
	        calendar : {
	            sameDay : '[Today at] LT',
	            nextDay : '[Tomorrow at] LT',
	            nextWeek : 'dddd [at] LT',
	            lastDay : '[Yesterday at] LT',
	            lastWeek : '[Last] dddd [at] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'in %s',
	            past : '%s ago',
	            s : 'a few seconds',
	            m : 'a minute',
	            mm : '%d minutes',
	            h : 'an hour',
	            hh : '%d hours',
	            d : 'a day',
	            dd : '%d days',
	            M : 'a month',
	            MM : '%d months',
	            y : 'a year',
	            yy : '%d years'
	        },
	        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (~~(number % 100 / 10) === 1) ? 'th' :
	                (b === 1) ? 'st' :
	                (b === 2) ? 'nd' :
	                (b === 3) ? 'rd' : 'th';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return en_nz;

	}));

/***/ },
/* 243 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : esperanto (eo)
	//! author : Colin Dean : https://github.com/colindean
	//! komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko.
	//!          Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni!

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var eo = moment.defineLocale('eo', {
	        months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'),
	        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'),
	        weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'),
	        weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'),
	        weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'YYYY-MM-DD',
	            LL : 'D[-an de] MMMM, YYYY',
	            LLL : 'D[-an de] MMMM, YYYY HH:mm',
	            LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm'
	        },
	        meridiemParse: /[ap]\.t\.m/i,
	        isPM: function (input) {
	            return input.charAt(0).toLowerCase() === 'p';
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours > 11) {
	                return isLower ? 'p.t.m.' : 'P.T.M.';
	            } else {
	                return isLower ? 'a.t.m.' : 'A.T.M.';
	            }
	        },
	        calendar : {
	            sameDay : '[Hodiaŭ je] LT',
	            nextDay : '[Morgaŭ je] LT',
	            nextWeek : 'dddd [je] LT',
	            lastDay : '[Hieraŭ je] LT',
	            lastWeek : '[pasinta] dddd [je] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'je %s',
	            past : 'antaŭ %s',
	            s : 'sekundoj',
	            m : 'minuto',
	            mm : '%d minutoj',
	            h : 'horo',
	            hh : '%d horoj',
	            d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo
	            dd : '%d tagoj',
	            M : 'monato',
	            MM : '%d monatoj',
	            y : 'jaro',
	            yy : '%d jaroj'
	        },
	        ordinalParse: /\d{1,2}a/,
	        ordinal : '%da',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return eo;

	}));

/***/ },
/* 244 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : spanish (es)
	//! author : Julio Napurí : https://github.com/julionc

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'),
	        monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');

	    var es = moment.defineLocale('es', {
	        months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
	        monthsShort : function (m, format) {
	            if (/-MMM-/.test(format)) {
	                return monthsShort[m.month()];
	            } else {
	                return monthsShortDot[m.month()];
	            }
	        },
	        monthsParseExact : true,
	        weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
	        weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
	        weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D [de] MMMM [de] YYYY',
	            LLL : 'D [de] MMMM [de] YYYY H:mm',
	            LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
	        },
	        calendar : {
	            sameDay : function () {
	                return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	            },
	            nextDay : function () {
	                return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	            },
	            nextWeek : function () {
	                return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	            },
	            lastDay : function () {
	                return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	            },
	            lastWeek : function () {
	                return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'en %s',
	            past : 'hace %s',
	            s : 'unos segundos',
	            m : 'un minuto',
	            mm : '%d minutos',
	            h : 'una hora',
	            hh : '%d horas',
	            d : 'un día',
	            dd : '%d días',
	            M : 'un mes',
	            MM : '%d meses',
	            y : 'un año',
	            yy : '%d años'
	        },
	        ordinalParse : /\d{1,2}º/,
	        ordinal : '%dº',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return es;

	}));

/***/ },
/* 245 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : estonian (et)
	//! author : Henry Kehlmann : https://github.com/madhenry
	//! improvements : Illimar Tambek : https://github.com/ragulka

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function processRelativeTime(number, withoutSuffix, key, isFuture) {
	        var format = {
	            's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
	            'm' : ['ühe minuti', 'üks minut'],
	            'mm': [number + ' minuti', number + ' minutit'],
	            'h' : ['ühe tunni', 'tund aega', 'üks tund'],
	            'hh': [number + ' tunni', number + ' tundi'],
	            'd' : ['ühe päeva', 'üks päev'],
	            'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
	            'MM': [number + ' kuu', number + ' kuud'],
	            'y' : ['ühe aasta', 'aasta', 'üks aasta'],
	            'yy': [number + ' aasta', number + ' aastat']
	        };
	        if (withoutSuffix) {
	            return format[key][2] ? format[key][2] : format[key][1];
	        }
	        return isFuture ? format[key][0] : format[key][1];
	    }

	    var et = moment.defineLocale('et', {
	        months        : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'),
	        monthsShort   : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'),
	        weekdays      : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'),
	        weekdaysShort : 'P_E_T_K_N_R_L'.split('_'),
	        weekdaysMin   : 'P_E_T_K_N_R_L'.split('_'),
	        longDateFormat : {
	            LT   : 'H:mm',
	            LTS : 'H:mm:ss',
	            L    : 'DD.MM.YYYY',
	            LL   : 'D. MMMM YYYY',
	            LLL  : 'D. MMMM YYYY H:mm',
	            LLLL : 'dddd, D. MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay  : '[Täna,] LT',
	            nextDay  : '[Homme,] LT',
	            nextWeek : '[Järgmine] dddd LT',
	            lastDay  : '[Eile,] LT',
	            lastWeek : '[Eelmine] dddd LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s pärast',
	            past   : '%s tagasi',
	            s      : processRelativeTime,
	            m      : processRelativeTime,
	            mm     : processRelativeTime,
	            h      : processRelativeTime,
	            hh     : processRelativeTime,
	            d      : processRelativeTime,
	            dd     : '%d päeva',
	            M      : processRelativeTime,
	            MM     : processRelativeTime,
	            y      : processRelativeTime,
	            yy     : processRelativeTime
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return et;

	}));

/***/ },
/* 246 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : euskara (eu)
	//! author : Eneko Illarramendi : https://github.com/eillarra

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var eu = moment.defineLocale('eu', {
	        months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
	        monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
	        weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'),
	        weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'YYYY-MM-DD',
	            LL : 'YYYY[ko] MMMM[ren] D[a]',
	            LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm',
	            LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
	            l : 'YYYY-M-D',
	            ll : 'YYYY[ko] MMM D[a]',
	            lll : 'YYYY[ko] MMM D[a] HH:mm',
	            llll : 'ddd, YYYY[ko] MMM D[a] HH:mm'
	        },
	        calendar : {
	            sameDay : '[gaur] LT[etan]',
	            nextDay : '[bihar] LT[etan]',
	            nextWeek : 'dddd LT[etan]',
	            lastDay : '[atzo] LT[etan]',
	            lastWeek : '[aurreko] dddd LT[etan]',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s barru',
	            past : 'duela %s',
	            s : 'segundo batzuk',
	            m : 'minutu bat',
	            mm : '%d minutu',
	            h : 'ordu bat',
	            hh : '%d ordu',
	            d : 'egun bat',
	            dd : '%d egun',
	            M : 'hilabete bat',
	            MM : '%d hilabete',
	            y : 'urte bat',
	            yy : '%d urte'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return eu;

	}));

/***/ },
/* 247 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Persian (fa)
	//! author : Ebrahim Byagowi : https://github.com/ebraminio

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '۱',
	        '2': '۲',
	        '3': '۳',
	        '4': '۴',
	        '5': '۵',
	        '6': '۶',
	        '7': '۷',
	        '8': '۸',
	        '9': '۹',
	        '0': '۰'
	    }, numberMap = {
	        '۱': '1',
	        '۲': '2',
	        '۳': '3',
	        '۴': '4',
	        '۵': '5',
	        '۶': '6',
	        '۷': '7',
	        '۸': '8',
	        '۹': '9',
	        '۰': '0'
	    };

	    var fa = moment.defineLocale('fa', {
	        months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
	        monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
	        weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
	        weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
	        weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        meridiemParse: /قبل از ظهر|بعد از ظهر/,
	        isPM: function (input) {
	            return /بعد از ظهر/.test(input);
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 12) {
	                return 'قبل از ظهر';
	            } else {
	                return 'بعد از ظهر';
	            }
	        },
	        calendar : {
	            sameDay : '[امروز ساعت] LT',
	            nextDay : '[فردا ساعت] LT',
	            nextWeek : 'dddd [ساعت] LT',
	            lastDay : '[دیروز ساعت] LT',
	            lastWeek : 'dddd [پیش] [ساعت] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'در %s',
	            past : '%s پیش',
	            s : 'چندین ثانیه',
	            m : 'یک دقیقه',
	            mm : '%d دقیقه',
	            h : 'یک ساعت',
	            hh : '%d ساعت',
	            d : 'یک روز',
	            dd : '%d روز',
	            M : 'یک ماه',
	            MM : '%d ماه',
	            y : 'یک سال',
	            yy : '%d سال'
	        },
	        preparse: function (string) {
	            return string.replace(/[۰-۹]/g, function (match) {
	                return numberMap[match];
	            }).replace(/،/g, ',');
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            }).replace(/,/g, '،');
	        },
	        ordinalParse: /\d{1,2}م/,
	        ordinal : '%dم',
	        week : {
	            dow : 6, // Saturday is the first day of the week.
	            doy : 12 // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return fa;

	}));

/***/ },
/* 248 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : finnish (fi)
	//! author : Tarmo Aidantausta : https://github.com/bleadof

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
	        numbersFuture = [
	            'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
	            numbersPast[7], numbersPast[8], numbersPast[9]
	        ];
	    function translate(number, withoutSuffix, key, isFuture) {
	        var result = '';
	        switch (key) {
	        case 's':
	            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
	        case 'm':
	            return isFuture ? 'minuutin' : 'minuutti';
	        case 'mm':
	            result = isFuture ? 'minuutin' : 'minuuttia';
	            break;
	        case 'h':
	            return isFuture ? 'tunnin' : 'tunti';
	        case 'hh':
	            result = isFuture ? 'tunnin' : 'tuntia';
	            break;
	        case 'd':
	            return isFuture ? 'päivän' : 'päivä';
	        case 'dd':
	            result = isFuture ? 'päivän' : 'päivää';
	            break;
	        case 'M':
	            return isFuture ? 'kuukauden' : 'kuukausi';
	        case 'MM':
	            result = isFuture ? 'kuukauden' : 'kuukautta';
	            break;
	        case 'y':
	            return isFuture ? 'vuoden' : 'vuosi';
	        case 'yy':
	            result = isFuture ? 'vuoden' : 'vuotta';
	            break;
	        }
	        result = verbalNumber(number, isFuture) + ' ' + result;
	        return result;
	    }
	    function verbalNumber(number, isFuture) {
	        return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
	    }

	    var fi = moment.defineLocale('fi', {
	        months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'),
	        monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
	        weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
	        weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'),
	        weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
	        longDateFormat : {
	            LT : 'HH.mm',
	            LTS : 'HH.mm.ss',
	            L : 'DD.MM.YYYY',
	            LL : 'Do MMMM[ta] YYYY',
	            LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm',
	            LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm',
	            l : 'D.M.YYYY',
	            ll : 'Do MMM YYYY',
	            lll : 'Do MMM YYYY, [klo] HH.mm',
	            llll : 'ddd, Do MMM YYYY, [klo] HH.mm'
	        },
	        calendar : {
	            sameDay : '[tänään] [klo] LT',
	            nextDay : '[huomenna] [klo] LT',
	            nextWeek : 'dddd [klo] LT',
	            lastDay : '[eilen] [klo] LT',
	            lastWeek : '[viime] dddd[na] [klo] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s päästä',
	            past : '%s sitten',
	            s : translate,
	            m : translate,
	            mm : translate,
	            h : translate,
	            hh : translate,
	            d : translate,
	            dd : translate,
	            M : translate,
	            MM : translate,
	            y : translate,
	            yy : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return fi;

	}));

/***/ },
/* 249 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : faroese (fo)
	//! author : Ragnar Johannesen : https://github.com/ragnar123

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var fo = moment.defineLocale('fo', {
	        months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
	        monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
	        weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'),
	        weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'),
	        weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D. MMMM, YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[Í dag kl.] LT',
	            nextDay : '[Í morgin kl.] LT',
	            nextWeek : 'dddd [kl.] LT',
	            lastDay : '[Í gjár kl.] LT',
	            lastWeek : '[síðstu] dddd [kl] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'um %s',
	            past : '%s síðani',
	            s : 'fá sekund',
	            m : 'ein minutt',
	            mm : '%d minuttir',
	            h : 'ein tími',
	            hh : '%d tímar',
	            d : 'ein dagur',
	            dd : '%d dagar',
	            M : 'ein mánaði',
	            MM : '%d mánaðir',
	            y : 'eitt ár',
	            yy : '%d ár'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return fo;

	}));

/***/ },
/* 250 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : french (fr)
	//! author : John Fischer : https://github.com/jfroffice

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var fr = moment.defineLocale('fr', {
	        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
	        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
	        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
	        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Aujourd\'hui à] LT',
	            nextDay: '[Demain à] LT',
	            nextWeek: 'dddd [à] LT',
	            lastDay: '[Hier à] LT',
	            lastWeek: 'dddd [dernier à] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'dans %s',
	            past : 'il y a %s',
	            s : 'quelques secondes',
	            m : 'une minute',
	            mm : '%d minutes',
	            h : 'une heure',
	            hh : '%d heures',
	            d : 'un jour',
	            dd : '%d jours',
	            M : 'un mois',
	            MM : '%d mois',
	            y : 'un an',
	            yy : '%d ans'
	        },
	        ordinalParse: /\d{1,2}(er|)/,
	        ordinal : function (number) {
	            return number + (number === 1 ? 'er' : '');
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return fr;

	}));

/***/ },
/* 251 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : canadian french (fr-ca)
	//! author : Jonathan Abourbih : https://github.com/jonbca

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var fr_ca = moment.defineLocale('fr-ca', {
	        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
	        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
	        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
	        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'YYYY-MM-DD',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Aujourd\'hui à] LT',
	            nextDay: '[Demain à] LT',
	            nextWeek: 'dddd [à] LT',
	            lastDay: '[Hier à] LT',
	            lastWeek: 'dddd [dernier à] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'dans %s',
	            past : 'il y a %s',
	            s : 'quelques secondes',
	            m : 'une minute',
	            mm : '%d minutes',
	            h : 'une heure',
	            hh : '%d heures',
	            d : 'un jour',
	            dd : '%d jours',
	            M : 'un mois',
	            MM : '%d mois',
	            y : 'un an',
	            yy : '%d ans'
	        },
	        ordinalParse: /\d{1,2}(er|e)/,
	        ordinal : function (number) {
	            return number + (number === 1 ? 'er' : 'e');
	        }
	    });

	    return fr_ca;

	}));

/***/ },
/* 252 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : swiss french (fr)
	//! author : Gaspard Bucher : https://github.com/gaspard

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var fr_ch = moment.defineLocale('fr-ch', {
	        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
	        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
	        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
	        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Aujourd\'hui à] LT',
	            nextDay: '[Demain à] LT',
	            nextWeek: 'dddd [à] LT',
	            lastDay: '[Hier à] LT',
	            lastWeek: 'dddd [dernier à] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'dans %s',
	            past : 'il y a %s',
	            s : 'quelques secondes',
	            m : 'une minute',
	            mm : '%d minutes',
	            h : 'une heure',
	            hh : '%d heures',
	            d : 'un jour',
	            dd : '%d jours',
	            M : 'un mois',
	            MM : '%d mois',
	            y : 'un an',
	            yy : '%d ans'
	        },
	        ordinalParse: /\d{1,2}(er|e)/,
	        ordinal : function (number) {
	            return number + (number === 1 ? 'er' : 'e');
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return fr_ch;

	}));

/***/ },
/* 253 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : frisian (fy)
	//! author : Robin van der Vliet : https://github.com/robin0van0der0v

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'),
	        monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_');

	    var fy = moment.defineLocale('fy', {
	        months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'),
	        monthsShort : function (m, format) {
	            if (/-MMM-/.test(format)) {
	                return monthsShortWithoutDots[m.month()];
	            } else {
	                return monthsShortWithDots[m.month()];
	            }
	        },
	        monthsParseExact : true,
	        weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'),
	        weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'),
	        weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD-MM-YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[hjoed om] LT',
	            nextDay: '[moarn om] LT',
	            nextWeek: 'dddd [om] LT',
	            lastDay: '[juster om] LT',
	            lastWeek: '[ôfrûne] dddd [om] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'oer %s',
	            past : '%s lyn',
	            s : 'in pear sekonden',
	            m : 'ien minút',
	            mm : '%d minuten',
	            h : 'ien oere',
	            hh : '%d oeren',
	            d : 'ien dei',
	            dd : '%d dagen',
	            M : 'ien moanne',
	            MM : '%d moannen',
	            y : 'ien jier',
	            yy : '%d jierren'
	        },
	        ordinalParse: /\d{1,2}(ste|de)/,
	        ordinal : function (number) {
	            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return fy;

	}));

/***/ },
/* 254 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : great britain scottish gealic (gd)
	//! author : Jon Ashdown : https://github.com/jonashdown

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var months = [
	        'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'
	    ];

	    var monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'];

	    var weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'];

	    var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'];

	    var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];

	    var gd = moment.defineLocale('gd', {
	        months : months,
	        monthsShort : monthsShort,
	        monthsParseExact : true,
	        weekdays : weekdays,
	        weekdaysShort : weekdaysShort,
	        weekdaysMin : weekdaysMin,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[An-diugh aig] LT',
	            nextDay : '[A-màireach aig] LT',
	            nextWeek : 'dddd [aig] LT',
	            lastDay : '[An-dè aig] LT',
	            lastWeek : 'dddd [seo chaidh] [aig] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'ann an %s',
	            past : 'bho chionn %s',
	            s : 'beagan diogan',
	            m : 'mionaid',
	            mm : '%d mionaidean',
	            h : 'uair',
	            hh : '%d uairean',
	            d : 'latha',
	            dd : '%d latha',
	            M : 'mìos',
	            MM : '%d mìosan',
	            y : 'bliadhna',
	            yy : '%d bliadhna'
	        },
	        ordinalParse : /\d{1,2}(d|na|mh)/,
	        ordinal : function (number) {
	            var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return gd;

	}));

/***/ },
/* 255 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : galician (gl)
	//! author : Juan G. Hurtado : https://github.com/juanghurtado

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var gl = moment.defineLocale('gl', {
	        months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'),
	        monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'),
	        monthsParseExact: true,
	        weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'),
	        weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'),
	        weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY H:mm',
	            LLLL : 'dddd D MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay : function () {
	                return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
	            },
	            nextDay : function () {
	                return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
	            },
	            nextWeek : function () {
	                return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
	            },
	            lastDay : function () {
	                return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
	            },
	            lastWeek : function () {
	                return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : function (str) {
	                if (str === 'uns segundos') {
	                    return 'nuns segundos';
	                }
	                return 'en ' + str;
	            },
	            past : 'hai %s',
	            s : 'uns segundos',
	            m : 'un minuto',
	            mm : '%d minutos',
	            h : 'unha hora',
	            hh : '%d horas',
	            d : 'un día',
	            dd : '%d días',
	            M : 'un mes',
	            MM : '%d meses',
	            y : 'un ano',
	            yy : '%d anos'
	        },
	        ordinalParse : /\d{1,2}º/,
	        ordinal : '%dº',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return gl;

	}));

/***/ },
/* 256 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Hebrew (he)
	//! author : Tomer Cohen : https://github.com/tomer
	//! author : Moshe Simantov : https://github.com/DevelopmentIL
	//! author : Tal Ater : https://github.com/TalAter

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var he = moment.defineLocale('he', {
	        months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'),
	        monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'),
	        weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
	        weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
	        weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D [ב]MMMM YYYY',
	            LLL : 'D [ב]MMMM YYYY HH:mm',
	            LLLL : 'dddd, D [ב]MMMM YYYY HH:mm',
	            l : 'D/M/YYYY',
	            ll : 'D MMM YYYY',
	            lll : 'D MMM YYYY HH:mm',
	            llll : 'ddd, D MMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[היום ב־]LT',
	            nextDay : '[מחר ב־]LT',
	            nextWeek : 'dddd [בשעה] LT',
	            lastDay : '[אתמול ב־]LT',
	            lastWeek : '[ביום] dddd [האחרון בשעה] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'בעוד %s',
	            past : 'לפני %s',
	            s : 'מספר שניות',
	            m : 'דקה',
	            mm : '%d דקות',
	            h : 'שעה',
	            hh : function (number) {
	                if (number === 2) {
	                    return 'שעתיים';
	                }
	                return number + ' שעות';
	            },
	            d : 'יום',
	            dd : function (number) {
	                if (number === 2) {
	                    return 'יומיים';
	                }
	                return number + ' ימים';
	            },
	            M : 'חודש',
	            MM : function (number) {
	                if (number === 2) {
	                    return 'חודשיים';
	                }
	                return number + ' חודשים';
	            },
	            y : 'שנה',
	            yy : function (number) {
	                if (number === 2) {
	                    return 'שנתיים';
	                } else if (number % 10 === 0 && number !== 10) {
	                    return number + ' שנה';
	                }
	                return number + ' שנים';
	            }
	        },
	        meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,
	        isPM : function (input) {
	            return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input);
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 5) {
	                return 'לפנות בוקר';
	            } else if (hour < 10) {
	                return 'בבוקר';
	            } else if (hour < 12) {
	                return isLower ? 'לפנה"צ' : 'לפני הצהריים';
	            } else if (hour < 18) {
	                return isLower ? 'אחה"צ' : 'אחרי הצהריים';
	            } else {
	                return 'בערב';
	            }
	        }
	    });

	    return he;

	}));

/***/ },
/* 257 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : hindi (hi)
	//! author : Mayank Singhal : https://github.com/mayanksinghal

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '१',
	        '2': '२',
	        '3': '३',
	        '4': '४',
	        '5': '५',
	        '6': '६',
	        '7': '७',
	        '8': '८',
	        '9': '९',
	        '0': '०'
	    },
	    numberMap = {
	        '१': '1',
	        '२': '2',
	        '३': '3',
	        '४': '4',
	        '५': '5',
	        '६': '6',
	        '७': '7',
	        '८': '8',
	        '९': '9',
	        '०': '0'
	    };

	    var hi = moment.defineLocale('hi', {
	        months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'),
	        monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'),
	        monthsParseExact: true,
	        weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
	        weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'),
	        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
	        longDateFormat : {
	            LT : 'A h:mm बजे',
	            LTS : 'A h:mm:ss बजे',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, A h:mm बजे',
	            LLLL : 'dddd, D MMMM YYYY, A h:mm बजे'
	        },
	        calendar : {
	            sameDay : '[आज] LT',
	            nextDay : '[कल] LT',
	            nextWeek : 'dddd, LT',
	            lastDay : '[कल] LT',
	            lastWeek : '[पिछले] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s में',
	            past : '%s पहले',
	            s : 'कुछ ही क्षण',
	            m : 'एक मिनट',
	            mm : '%d मिनट',
	            h : 'एक घंटा',
	            hh : '%d घंटे',
	            d : 'एक दिन',
	            dd : '%d दिन',
	            M : 'एक महीने',
	            MM : '%d महीने',
	            y : 'एक वर्ष',
	            yy : '%d वर्ष'
	        },
	        preparse: function (string) {
	            return string.replace(/[१२३४५६७८९०]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        // Hindi notation for meridiems are quite fuzzy in practice. While there exists
	        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
	        meridiemParse: /रात|सुबह|दोपहर|शाम/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'रात') {
	                return hour < 4 ? hour : hour + 12;
	            } else if (meridiem === 'सुबह') {
	                return hour;
	            } else if (meridiem === 'दोपहर') {
	                return hour >= 10 ? hour : hour + 12;
	            } else if (meridiem === 'शाम') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'रात';
	            } else if (hour < 10) {
	                return 'सुबह';
	            } else if (hour < 17) {
	                return 'दोपहर';
	            } else if (hour < 20) {
	                return 'शाम';
	            } else {
	                return 'रात';
	            }
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return hi;

	}));

/***/ },
/* 258 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : hrvatski (hr)
	//! author : Bojan Marković : https://github.com/bmarkovic

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function translate(number, withoutSuffix, key) {
	        var result = number + ' ';
	        switch (key) {
	        case 'm':
	            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
	        case 'mm':
	            if (number === 1) {
	                result += 'minuta';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'minute';
	            } else {
	                result += 'minuta';
	            }
	            return result;
	        case 'h':
	            return withoutSuffix ? 'jedan sat' : 'jednog sata';
	        case 'hh':
	            if (number === 1) {
	                result += 'sat';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'sata';
	            } else {
	                result += 'sati';
	            }
	            return result;
	        case 'dd':
	            if (number === 1) {
	                result += 'dan';
	            } else {
	                result += 'dana';
	            }
	            return result;
	        case 'MM':
	            if (number === 1) {
	                result += 'mjesec';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'mjeseca';
	            } else {
	                result += 'mjeseci';
	            }
	            return result;
	        case 'yy':
	            if (number === 1) {
	                result += 'godina';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'godine';
	            } else {
	                result += 'godina';
	            }
	            return result;
	        }
	    }

	    var hr = moment.defineLocale('hr', {
	        months : {
	            format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'),
	            standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_')
	        },
	        monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'),
	        monthsParseExact: true,
	        weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
	        weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
	        weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD. MM. YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY H:mm',
	            LLLL : 'dddd, D. MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay  : '[danas u] LT',
	            nextDay  : '[sutra u] LT',
	            nextWeek : function () {
	                switch (this.day()) {
	                case 0:
	                    return '[u] [nedjelju] [u] LT';
	                case 3:
	                    return '[u] [srijedu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	                }
	            },
	            lastDay  : '[jučer u] LT',
	            lastWeek : function () {
	                switch (this.day()) {
	                case 0:
	                case 3:
	                    return '[prošlu] dddd [u] LT';
	                case 6:
	                    return '[prošle] [subote] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[prošli] dddd [u] LT';
	                }
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'za %s',
	            past   : 'prije %s',
	            s      : 'par sekundi',
	            m      : translate,
	            mm     : translate,
	            h      : translate,
	            hh     : translate,
	            d      : 'dan',
	            dd     : translate,
	            M      : 'mjesec',
	            MM     : translate,
	            y      : 'godinu',
	            yy     : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return hr;

	}));

/***/ },
/* 259 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : hungarian (hu)
	//! author : Adam Brunner : https://github.com/adambrunner

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
	    function translate(number, withoutSuffix, key, isFuture) {
	        var num = number,
	            suffix;
	        switch (key) {
	        case 's':
	            return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
	        case 'm':
	            return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
	        case 'mm':
	            return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
	        case 'h':
	            return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
	        case 'hh':
	            return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
	        case 'd':
	            return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
	        case 'dd':
	            return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
	        case 'M':
	            return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
	        case 'MM':
	            return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
	        case 'y':
	            return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
	        case 'yy':
	            return num + (isFuture || withoutSuffix ? ' év' : ' éve');
	        }
	        return '';
	    }
	    function week(isFuture) {
	        return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
	    }

	    var hu = moment.defineLocale('hu', {
	        months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'),
	        monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'),
	        weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
	        weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
	        weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'YYYY.MM.DD.',
	            LL : 'YYYY. MMMM D.',
	            LLL : 'YYYY. MMMM D. H:mm',
	            LLLL : 'YYYY. MMMM D., dddd H:mm'
	        },
	        meridiemParse: /de|du/i,
	        isPM: function (input) {
	            return input.charAt(1).toLowerCase() === 'u';
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 12) {
	                return isLower === true ? 'de' : 'DE';
	            } else {
	                return isLower === true ? 'du' : 'DU';
	            }
	        },
	        calendar : {
	            sameDay : '[ma] LT[-kor]',
	            nextDay : '[holnap] LT[-kor]',
	            nextWeek : function () {
	                return week.call(this, true);
	            },
	            lastDay : '[tegnap] LT[-kor]',
	            lastWeek : function () {
	                return week.call(this, false);
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s múlva',
	            past : '%s',
	            s : translate,
	            m : translate,
	            mm : translate,
	            h : translate,
	            hh : translate,
	            d : translate,
	            dd : translate,
	            M : translate,
	            MM : translate,
	            y : translate,
	            yy : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return hu;

	}));

/***/ },
/* 260 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Armenian (hy-am)
	//! author : Armendarabyan : https://github.com/armendarabyan

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var hy_am = moment.defineLocale('hy-am', {
	        months : {
	            format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'),
	            standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_')
	        },
	        monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'),
	        weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'),
	        weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
	        weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY թ.',
	            LLL : 'D MMMM YYYY թ., HH:mm',
	            LLLL : 'dddd, D MMMM YYYY թ., HH:mm'
	        },
	        calendar : {
	            sameDay: '[այսօր] LT',
	            nextDay: '[վաղը] LT',
	            lastDay: '[երեկ] LT',
	            nextWeek: function () {
	                return 'dddd [օրը ժամը] LT';
	            },
	            lastWeek: function () {
	                return '[անցած] dddd [օրը ժամը] LT';
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : '%s հետո',
	            past : '%s առաջ',
	            s : 'մի քանի վայրկյան',
	            m : 'րոպե',
	            mm : '%d րոպե',
	            h : 'ժամ',
	            hh : '%d ժամ',
	            d : 'օր',
	            dd : '%d օր',
	            M : 'ամիս',
	            MM : '%d ամիս',
	            y : 'տարի',
	            yy : '%d տարի'
	        },
	        meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,
	        isPM: function (input) {
	            return /^(ցերեկվա|երեկոյան)$/.test(input);
	        },
	        meridiem : function (hour) {
	            if (hour < 4) {
	                return 'գիշերվա';
	            } else if (hour < 12) {
	                return 'առավոտվա';
	            } else if (hour < 17) {
	                return 'ցերեկվա';
	            } else {
	                return 'երեկոյան';
	            }
	        },
	        ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/,
	        ordinal: function (number, period) {
	            switch (period) {
	            case 'DDD':
	            case 'w':
	            case 'W':
	            case 'DDDo':
	                if (number === 1) {
	                    return number + '-ին';
	                }
	                return number + '-րդ';
	            default:
	                return number;
	            }
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return hy_am;

	}));

/***/ },
/* 261 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Bahasa Indonesia (id)
	//! author : Mohammad Satrio Utomo : https://github.com/tyok
	//! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var id = moment.defineLocale('id', {
	        months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'),
	        weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
	        weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
	        weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
	        longDateFormat : {
	            LT : 'HH.mm',
	            LTS : 'HH.mm.ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY [pukul] HH.mm',
	            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	        },
	        meridiemParse: /pagi|siang|sore|malam/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'pagi') {
	                return hour;
	            } else if (meridiem === 'siang') {
	                return hour >= 11 ? hour : hour + 12;
	            } else if (meridiem === 'sore' || meridiem === 'malam') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 11) {
	                return 'pagi';
	            } else if (hours < 15) {
	                return 'siang';
	            } else if (hours < 19) {
	                return 'sore';
	            } else {
	                return 'malam';
	            }
	        },
	        calendar : {
	            sameDay : '[Hari ini pukul] LT',
	            nextDay : '[Besok pukul] LT',
	            nextWeek : 'dddd [pukul] LT',
	            lastDay : '[Kemarin pukul] LT',
	            lastWeek : 'dddd [lalu pukul] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'dalam %s',
	            past : '%s yang lalu',
	            s : 'beberapa detik',
	            m : 'semenit',
	            mm : '%d menit',
	            h : 'sejam',
	            hh : '%d jam',
	            d : 'sehari',
	            dd : '%d hari',
	            M : 'sebulan',
	            MM : '%d bulan',
	            y : 'setahun',
	            yy : '%d tahun'
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return id;

	}));

/***/ },
/* 262 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : icelandic (is)
	//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function plural(n) {
	        if (n % 100 === 11) {
	            return true;
	        } else if (n % 10 === 1) {
	            return false;
	        }
	        return true;
	    }
	    function translate(number, withoutSuffix, key, isFuture) {
	        var result = number + ' ';
	        switch (key) {
	        case 's':
	            return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
	        case 'm':
	            return withoutSuffix ? 'mínúta' : 'mínútu';
	        case 'mm':
	            if (plural(number)) {
	                return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
	            } else if (withoutSuffix) {
	                return result + 'mínúta';
	            }
	            return result + 'mínútu';
	        case 'hh':
	            if (plural(number)) {
	                return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
	            }
	            return result + 'klukkustund';
	        case 'd':
	            if (withoutSuffix) {
	                return 'dagur';
	            }
	            return isFuture ? 'dag' : 'degi';
	        case 'dd':
	            if (plural(number)) {
	                if (withoutSuffix) {
	                    return result + 'dagar';
	                }
	                return result + (isFuture ? 'daga' : 'dögum');
	            } else if (withoutSuffix) {
	                return result + 'dagur';
	            }
	            return result + (isFuture ? 'dag' : 'degi');
	        case 'M':
	            if (withoutSuffix) {
	                return 'mánuður';
	            }
	            return isFuture ? 'mánuð' : 'mánuði';
	        case 'MM':
	            if (plural(number)) {
	                if (withoutSuffix) {
	                    return result + 'mánuðir';
	                }
	                return result + (isFuture ? 'mánuði' : 'mánuðum');
	            } else if (withoutSuffix) {
	                return result + 'mánuður';
	            }
	            return result + (isFuture ? 'mánuð' : 'mánuði');
	        case 'y':
	            return withoutSuffix || isFuture ? 'ár' : 'ári';
	        case 'yy':
	            if (plural(number)) {
	                return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
	            }
	            return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
	        }
	    }

	    var is = moment.defineLocale('is', {
	        months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'),
	        monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'),
	        weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'),
	        weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'),
	        weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY [kl.] H:mm',
	            LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm'
	        },
	        calendar : {
	            sameDay : '[í dag kl.] LT',
	            nextDay : '[á morgun kl.] LT',
	            nextWeek : 'dddd [kl.] LT',
	            lastDay : '[í gær kl.] LT',
	            lastWeek : '[síðasta] dddd [kl.] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'eftir %s',
	            past : 'fyrir %s síðan',
	            s : translate,
	            m : translate,
	            mm : translate,
	            h : 'klukkustund',
	            hh : translate,
	            d : translate,
	            dd : translate,
	            M : translate,
	            MM : translate,
	            y : translate,
	            yy : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return is;

	}));

/***/ },
/* 263 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : italian (it)
	//! author : Lorenzo : https://github.com/aliem
	//! author: Mattia Larentis: https://github.com/nostalgiaz

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var it = moment.defineLocale('it', {
	        months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'),
	        monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
	        weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'),
	        weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'),
	        weekdaysMin : 'Do_Lu_Ma_Me_Gi_Ve_Sa'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Oggi alle] LT',
	            nextDay: '[Domani alle] LT',
	            nextWeek: 'dddd [alle] LT',
	            lastDay: '[Ieri alle] LT',
	            lastWeek: function () {
	                switch (this.day()) {
	                    case 0:
	                        return '[la scorsa] dddd [alle] LT';
	                    default:
	                        return '[lo scorso] dddd [alle] LT';
	                }
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : function (s) {
	                return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s;
	            },
	            past : '%s fa',
	            s : 'alcuni secondi',
	            m : 'un minuto',
	            mm : '%d minuti',
	            h : 'un\'ora',
	            hh : '%d ore',
	            d : 'un giorno',
	            dd : '%d giorni',
	            M : 'un mese',
	            MM : '%d mesi',
	            y : 'un anno',
	            yy : '%d anni'
	        },
	        ordinalParse : /\d{1,2}º/,
	        ordinal: '%dº',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return it;

	}));

/***/ },
/* 264 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : japanese (ja)
	//! author : LI Long : https://github.com/baryon

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ja = moment.defineLocale('ja', {
	        months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	        weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
	        weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
	        weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
	        longDateFormat : {
	            LT : 'Ah時m分',
	            LTS : 'Ah時m分s秒',
	            L : 'YYYY/MM/DD',
	            LL : 'YYYY年M月D日',
	            LLL : 'YYYY年M月D日Ah時m分',
	            LLLL : 'YYYY年M月D日Ah時m分 dddd'
	        },
	        meridiemParse: /午前|午後/i,
	        isPM : function (input) {
	            return input === '午後';
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 12) {
	                return '午前';
	            } else {
	                return '午後';
	            }
	        },
	        calendar : {
	            sameDay : '[今日] LT',
	            nextDay : '[明日] LT',
	            nextWeek : '[来週]dddd LT',
	            lastDay : '[昨日] LT',
	            lastWeek : '[前週]dddd LT',
	            sameElse : 'L'
	        },
	        ordinalParse : /\d{1,2}日/,
	        ordinal : function (number, period) {
	            switch (period) {
	            case 'd':
	            case 'D':
	            case 'DDD':
	                return number + '日';
	            default:
	                return number;
	            }
	        },
	        relativeTime : {
	            future : '%s後',
	            past : '%s前',
	            s : '数秒',
	            m : '1分',
	            mm : '%d分',
	            h : '1時間',
	            hh : '%d時間',
	            d : '1日',
	            dd : '%d日',
	            M : '1ヶ月',
	            MM : '%dヶ月',
	            y : '1年',
	            yy : '%d年'
	        }
	    });

	    return ja;

	}));

/***/ },
/* 265 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Boso Jowo (jv)
	//! author : Rony Lantip : https://github.com/lantip
	//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var jv = moment.defineLocale('jv', {
	        months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'),
	        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'),
	        weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'),
	        weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'),
	        weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'),
	        longDateFormat : {
	            LT : 'HH.mm',
	            LTS : 'HH.mm.ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY [pukul] HH.mm',
	            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	        },
	        meridiemParse: /enjing|siyang|sonten|ndalu/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'enjing') {
	                return hour;
	            } else if (meridiem === 'siyang') {
	                return hour >= 11 ? hour : hour + 12;
	            } else if (meridiem === 'sonten' || meridiem === 'ndalu') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 11) {
	                return 'enjing';
	            } else if (hours < 15) {
	                return 'siyang';
	            } else if (hours < 19) {
	                return 'sonten';
	            } else {
	                return 'ndalu';
	            }
	        },
	        calendar : {
	            sameDay : '[Dinten puniko pukul] LT',
	            nextDay : '[Mbenjang pukul] LT',
	            nextWeek : 'dddd [pukul] LT',
	            lastDay : '[Kala wingi pukul] LT',
	            lastWeek : 'dddd [kepengker pukul] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'wonten ing %s',
	            past : '%s ingkang kepengker',
	            s : 'sawetawis detik',
	            m : 'setunggal menit',
	            mm : '%d menit',
	            h : 'setunggal jam',
	            hh : '%d jam',
	            d : 'sedinten',
	            dd : '%d dinten',
	            M : 'sewulan',
	            MM : '%d wulan',
	            y : 'setaun',
	            yy : '%d taun'
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return jv;

	}));

/***/ },
/* 266 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Georgian (ka)
	//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ka = moment.defineLocale('ka', {
	        months : {
	            standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
	            format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
	        },
	        monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
	        weekdays : {
	            standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
	            format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'),
	            isFormat: /(წინა|შემდეგ)/
	        },
	        weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
	        weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
	        longDateFormat : {
	            LT : 'h:mm A',
	            LTS : 'h:mm:ss A',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY h:mm A',
	            LLLL : 'dddd, D MMMM YYYY h:mm A'
	        },
	        calendar : {
	            sameDay : '[დღეს] LT[-ზე]',
	            nextDay : '[ხვალ] LT[-ზე]',
	            lastDay : '[გუშინ] LT[-ზე]',
	            nextWeek : '[შემდეგ] dddd LT[-ზე]',
	            lastWeek : '[წინა] dddd LT-ზე',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : function (s) {
	                return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
	                    s.replace(/ი$/, 'ში') :
	                    s + 'ში';
	            },
	            past : function (s) {
	                if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
	                    return s.replace(/(ი|ე)$/, 'ის წინ');
	                }
	                if ((/წელი/).test(s)) {
	                    return s.replace(/წელი$/, 'წლის წინ');
	                }
	            },
	            s : 'რამდენიმე წამი',
	            m : 'წუთი',
	            mm : '%d წუთი',
	            h : 'საათი',
	            hh : '%d საათი',
	            d : 'დღე',
	            dd : '%d დღე',
	            M : 'თვე',
	            MM : '%d თვე',
	            y : 'წელი',
	            yy : '%d წელი'
	        },
	        ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,
	        ordinal : function (number) {
	            if (number === 0) {
	                return number;
	            }
	            if (number === 1) {
	                return number + '-ლი';
	            }
	            if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
	                return 'მე-' + number;
	            }
	            return number + '-ე';
	        },
	        week : {
	            dow : 1,
	            doy : 7
	        }
	    });

	    return ka;

	}));

/***/ },
/* 267 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : kazakh (kk)
	//! authors : Nurlan Rakhimzhanov : https://github.com/nurlan

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var suffixes = {
	        0: '-ші',
	        1: '-ші',
	        2: '-ші',
	        3: '-ші',
	        4: '-ші',
	        5: '-ші',
	        6: '-шы',
	        7: '-ші',
	        8: '-ші',
	        9: '-шы',
	        10: '-шы',
	        20: '-шы',
	        30: '-шы',
	        40: '-шы',
	        50: '-ші',
	        60: '-шы',
	        70: '-ші',
	        80: '-ші',
	        90: '-шы',
	        100: '-ші'
	    };

	    var kk = moment.defineLocale('kk', {
	        months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'),
	        monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'),
	        weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'),
	        weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'),
	        weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[Бүгін сағат] LT',
	            nextDay : '[Ертең сағат] LT',
	            nextWeek : 'dddd [сағат] LT',
	            lastDay : '[Кеше сағат] LT',
	            lastWeek : '[Өткен аптаның] dddd [сағат] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s ішінде',
	            past : '%s бұрын',
	            s : 'бірнеше секунд',
	            m : 'бір минут',
	            mm : '%d минут',
	            h : 'бір сағат',
	            hh : '%d сағат',
	            d : 'бір күн',
	            dd : '%d күн',
	            M : 'бір ай',
	            MM : '%d ай',
	            y : 'бір жыл',
	            yy : '%d жыл'
	        },
	        ordinalParse: /\d{1,2}-(ші|шы)/,
	        ordinal : function (number) {
	            var a = number % 10,
	                b = number >= 100 ? 100 : null;
	            return number + (suffixes[number] || suffixes[a] || suffixes[b]);
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return kk;

	}));

/***/ },
/* 268 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : khmer (km)
	//! author : Kruy Vanna : https://github.com/kruyvanna

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var km = moment.defineLocale('km', {
	        months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
	        monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
	        weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
	        weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
	        weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
	        longDateFormat: {
	            LT: 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L: 'DD/MM/YYYY',
	            LL: 'D MMMM YYYY',
	            LLL: 'D MMMM YYYY HH:mm',
	            LLLL: 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar: {
	            sameDay: '[ថ្ងៃនេះ ម៉ោង] LT',
	            nextDay: '[ស្អែក ម៉ោង] LT',
	            nextWeek: 'dddd [ម៉ោង] LT',
	            lastDay: '[ម្សិលមិញ ម៉ោង] LT',
	            lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
	            sameElse: 'L'
	        },
	        relativeTime: {
	            future: '%sទៀត',
	            past: '%sមុន',
	            s: 'ប៉ុន្មានវិនាទី',
	            m: 'មួយនាទី',
	            mm: '%d នាទី',
	            h: 'មួយម៉ោង',
	            hh: '%d ម៉ោង',
	            d: 'មួយថ្ងៃ',
	            dd: '%d ថ្ងៃ',
	            M: 'មួយខែ',
	            MM: '%d ខែ',
	            y: 'មួយឆ្នាំ',
	            yy: '%d ឆ្នាំ'
	        },
	        week: {
	            dow: 1, // Monday is the first day of the week.
	            doy: 4 // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return km;

	}));

/***/ },
/* 269 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : korean (ko)
	//!
	//! authors
	//!
	//! - Kyungwook, Park : https://github.com/kyungw00k
	//! - Jeeeyul Lee <jeeeyul@gmail.com>

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ko = moment.defineLocale('ko', {
	        months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
	        monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
	        weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
	        weekdaysShort : '일_월_화_수_목_금_토'.split('_'),
	        weekdaysMin : '일_월_화_수_목_금_토'.split('_'),
	        longDateFormat : {
	            LT : 'A h시 m분',
	            LTS : 'A h시 m분 s초',
	            L : 'YYYY.MM.DD',
	            LL : 'YYYY년 MMMM D일',
	            LLL : 'YYYY년 MMMM D일 A h시 m분',
	            LLLL : 'YYYY년 MMMM D일 dddd A h시 m분'
	        },
	        calendar : {
	            sameDay : '오늘 LT',
	            nextDay : '내일 LT',
	            nextWeek : 'dddd LT',
	            lastDay : '어제 LT',
	            lastWeek : '지난주 dddd LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s 후',
	            past : '%s 전',
	            s : '몇 초',
	            ss : '%d초',
	            m : '일분',
	            mm : '%d분',
	            h : '한 시간',
	            hh : '%d시간',
	            d : '하루',
	            dd : '%d일',
	            M : '한 달',
	            MM : '%d달',
	            y : '일 년',
	            yy : '%d년'
	        },
	        ordinalParse : /\d{1,2}일/,
	        ordinal : '%d일',
	        meridiemParse : /오전|오후/,
	        isPM : function (token) {
	            return token === '오후';
	        },
	        meridiem : function (hour, minute, isUpper) {
	            return hour < 12 ? '오전' : '오후';
	        }
	    });

	    return ko;

	}));

/***/ },
/* 270 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : kyrgyz (ky)
	//! author : Chyngyz Arystan uulu : https://github.com/chyngyz

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';



	    var suffixes = {
	        0: '-чү',
	        1: '-чи',
	        2: '-чи',
	        3: '-чү',
	        4: '-чү',
	        5: '-чи',
	        6: '-чы',
	        7: '-чи',
	        8: '-чи',
	        9: '-чу',
	        10: '-чу',
	        20: '-чы',
	        30: '-чу',
	        40: '-чы',
	        50: '-чү',
	        60: '-чы',
	        70: '-чи',
	        80: '-чи',
	        90: '-чу',
	        100: '-чү'
	    };

	    var ky = moment.defineLocale('ky', {
	        months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
	        monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
	        weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'),
	        weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'),
	        weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[Бүгүн саат] LT',
	            nextDay : '[Эртең саат] LT',
	            nextWeek : 'dddd [саат] LT',
	            lastDay : '[Кече саат] LT',
	            lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s ичинде',
	            past : '%s мурун',
	            s : 'бирнече секунд',
	            m : 'бир мүнөт',
	            mm : '%d мүнөт',
	            h : 'бир саат',
	            hh : '%d саат',
	            d : 'бир күн',
	            dd : '%d күн',
	            M : 'бир ай',
	            MM : '%d ай',
	            y : 'бир жыл',
	            yy : '%d жыл'
	        },
	        ordinalParse: /\d{1,2}-(чи|чы|чү|чу)/,
	        ordinal : function (number) {
	            var a = number % 10,
	                b = number >= 100 ? 100 : null;
	            return number + (suffixes[number] || suffixes[a] || suffixes[b]);
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ky;

	}));

/***/ },
/* 271 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Luxembourgish (lb)
	//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function processRelativeTime(number, withoutSuffix, key, isFuture) {
	        var format = {
	            'm': ['eng Minutt', 'enger Minutt'],
	            'h': ['eng Stonn', 'enger Stonn'],
	            'd': ['een Dag', 'engem Dag'],
	            'M': ['ee Mount', 'engem Mount'],
	            'y': ['ee Joer', 'engem Joer']
	        };
	        return withoutSuffix ? format[key][0] : format[key][1];
	    }
	    function processFutureTime(string) {
	        var number = string.substr(0, string.indexOf(' '));
	        if (eifelerRegelAppliesToNumber(number)) {
	            return 'a ' + string;
	        }
	        return 'an ' + string;
	    }
	    function processPastTime(string) {
	        var number = string.substr(0, string.indexOf(' '));
	        if (eifelerRegelAppliesToNumber(number)) {
	            return 'viru ' + string;
	        }
	        return 'virun ' + string;
	    }
	    /**
	     * Returns true if the word before the given number loses the '-n' ending.
	     * e.g. 'an 10 Deeg' but 'a 5 Deeg'
	     *
	     * @param number {integer}
	     * @returns {boolean}
	     */
	    function eifelerRegelAppliesToNumber(number) {
	        number = parseInt(number, 10);
	        if (isNaN(number)) {
	            return false;
	        }
	        if (number < 0) {
	            // Negative Number --> always true
	            return true;
	        } else if (number < 10) {
	            // Only 1 digit
	            if (4 <= number && number <= 7) {
	                return true;
	            }
	            return false;
	        } else if (number < 100) {
	            // 2 digits
	            var lastDigit = number % 10, firstDigit = number / 10;
	            if (lastDigit === 0) {
	                return eifelerRegelAppliesToNumber(firstDigit);
	            }
	            return eifelerRegelAppliesToNumber(lastDigit);
	        } else if (number < 10000) {
	            // 3 or 4 digits --> recursively check first digit
	            while (number >= 10) {
	                number = number / 10;
	            }
	            return eifelerRegelAppliesToNumber(number);
	        } else {
	            // Anything larger than 4 digits: recursively check first n-3 digits
	            number = number / 1000;
	            return eifelerRegelAppliesToNumber(number);
	        }
	    }

	    var lb = moment.defineLocale('lb', {
	        months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
	        monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
	        monthsParseExact : true,
	        weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
	        weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
	        weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat: {
	            LT: 'H:mm [Auer]',
	            LTS: 'H:mm:ss [Auer]',
	            L: 'DD.MM.YYYY',
	            LL: 'D. MMMM YYYY',
	            LLL: 'D. MMMM YYYY H:mm [Auer]',
	            LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]'
	        },
	        calendar: {
	            sameDay: '[Haut um] LT',
	            sameElse: 'L',
	            nextDay: '[Muer um] LT',
	            nextWeek: 'dddd [um] LT',
	            lastDay: '[Gëschter um] LT',
	            lastWeek: function () {
	                // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
	                switch (this.day()) {
	                    case 2:
	                    case 4:
	                        return '[Leschten] dddd [um] LT';
	                    default:
	                        return '[Leschte] dddd [um] LT';
	                }
	            }
	        },
	        relativeTime : {
	            future : processFutureTime,
	            past : processPastTime,
	            s : 'e puer Sekonnen',
	            m : processRelativeTime,
	            mm : '%d Minutten',
	            h : processRelativeTime,
	            hh : '%d Stonnen',
	            d : processRelativeTime,
	            dd : '%d Deeg',
	            M : processRelativeTime,
	            MM : '%d Méint',
	            y : processRelativeTime,
	            yy : '%d Joer'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal: '%d.',
	        week: {
	            dow: 1, // Monday is the first day of the week.
	            doy: 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return lb;

	}));

/***/ },
/* 272 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : lao (lo)
	//! author : Ryan Hart : https://github.com/ryanhart2

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var lo = moment.defineLocale('lo', {
	        months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
	        monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
	        weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
	        weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
	        weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'ວັນdddd D MMMM YYYY HH:mm'
	        },
	        meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/,
	        isPM: function (input) {
	            return input === 'ຕອນແລງ';
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 12) {
	                return 'ຕອນເຊົ້າ';
	            } else {
	                return 'ຕອນແລງ';
	            }
	        },
	        calendar : {
	            sameDay : '[ມື້ນີ້ເວລາ] LT',
	            nextDay : '[ມື້ອື່ນເວລາ] LT',
	            nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT',
	            lastDay : '[ມື້ວານນີ້ເວລາ] LT',
	            lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'ອີກ %s',
	            past : '%sຜ່ານມາ',
	            s : 'ບໍ່ເທົ່າໃດວິນາທີ',
	            m : '1 ນາທີ',
	            mm : '%d ນາທີ',
	            h : '1 ຊົ່ວໂມງ',
	            hh : '%d ຊົ່ວໂມງ',
	            d : '1 ມື້',
	            dd : '%d ມື້',
	            M : '1 ເດືອນ',
	            MM : '%d ເດືອນ',
	            y : '1 ປີ',
	            yy : '%d ປີ'
	        },
	        ordinalParse: /(ທີ່)\d{1,2}/,
	        ordinal : function (number) {
	            return 'ທີ່' + number;
	        }
	    });

	    return lo;

	}));

/***/ },
/* 273 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Lithuanian (lt)
	//! author : Mindaugas Mozūras : https://github.com/mmozuras

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var units = {
	        'm' : 'minutė_minutės_minutę',
	        'mm': 'minutės_minučių_minutes',
	        'h' : 'valanda_valandos_valandą',
	        'hh': 'valandos_valandų_valandas',
	        'd' : 'diena_dienos_dieną',
	        'dd': 'dienos_dienų_dienas',
	        'M' : 'mėnuo_mėnesio_mėnesį',
	        'MM': 'mėnesiai_mėnesių_mėnesius',
	        'y' : 'metai_metų_metus',
	        'yy': 'metai_metų_metus'
	    };
	    function translateSeconds(number, withoutSuffix, key, isFuture) {
	        if (withoutSuffix) {
	            return 'kelios sekundės';
	        } else {
	            return isFuture ? 'kelių sekundžių' : 'kelias sekundes';
	        }
	    }
	    function translateSingular(number, withoutSuffix, key, isFuture) {
	        return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
	    }
	    function special(number) {
	        return number % 10 === 0 || (number > 10 && number < 20);
	    }
	    function forms(key) {
	        return units[key].split('_');
	    }
	    function translate(number, withoutSuffix, key, isFuture) {
	        var result = number + ' ';
	        if (number === 1) {
	            return result + translateSingular(number, withoutSuffix, key[0], isFuture);
	        } else if (withoutSuffix) {
	            return result + (special(number) ? forms(key)[1] : forms(key)[0]);
	        } else {
	            if (isFuture) {
	                return result + forms(key)[1];
	            } else {
	                return result + (special(number) ? forms(key)[1] : forms(key)[2]);
	            }
	        }
	    }
	    var lt = moment.defineLocale('lt', {
	        months : {
	            format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'),
	            standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_')
	        },
	        monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'),
	        weekdays : {
	            format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'),
	            standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'),
	            isFormat: /dddd HH:mm/
	        },
	        weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'),
	        weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'YYYY-MM-DD',
	            LL : 'YYYY [m.] MMMM D [d.]',
	            LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
	            LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]',
	            l : 'YYYY-MM-DD',
	            ll : 'YYYY [m.] MMMM D [d.]',
	            lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
	            llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]'
	        },
	        calendar : {
	            sameDay : '[Šiandien] LT',
	            nextDay : '[Rytoj] LT',
	            nextWeek : 'dddd LT',
	            lastDay : '[Vakar] LT',
	            lastWeek : '[Praėjusį] dddd LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'po %s',
	            past : 'prieš %s',
	            s : translateSeconds,
	            m : translateSingular,
	            mm : translate,
	            h : translateSingular,
	            hh : translate,
	            d : translateSingular,
	            dd : translate,
	            M : translateSingular,
	            MM : translate,
	            y : translateSingular,
	            yy : translate
	        },
	        ordinalParse: /\d{1,2}-oji/,
	        ordinal : function (number) {
	            return number + '-oji';
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return lt;

	}));

/***/ },
/* 274 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : latvian (lv)
	//! author : Kristaps Karlsons : https://github.com/skakri
	//! author : Jānis Elmeris : https://github.com/JanisE

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var units = {
	        'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
	        'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
	        'h': 'stundas_stundām_stunda_stundas'.split('_'),
	        'hh': 'stundas_stundām_stunda_stundas'.split('_'),
	        'd': 'dienas_dienām_diena_dienas'.split('_'),
	        'dd': 'dienas_dienām_diena_dienas'.split('_'),
	        'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
	        'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
	        'y': 'gada_gadiem_gads_gadi'.split('_'),
	        'yy': 'gada_gadiem_gads_gadi'.split('_')
	    };
	    /**
	     * @param withoutSuffix boolean true = a length of time; false = before/after a period of time.
	     */
	    function format(forms, number, withoutSuffix) {
	        if (withoutSuffix) {
	            // E.g. "21 minūte", "3 minūtes".
	            return number % 10 === 1 && number !== 11 ? forms[2] : forms[3];
	        } else {
	            // E.g. "21 minūtes" as in "pēc 21 minūtes".
	            // E.g. "3 minūtēm" as in "pēc 3 minūtēm".
	            return number % 10 === 1 && number !== 11 ? forms[0] : forms[1];
	        }
	    }
	    function relativeTimeWithPlural(number, withoutSuffix, key) {
	        return number + ' ' + format(units[key], number, withoutSuffix);
	    }
	    function relativeTimeWithSingular(number, withoutSuffix, key) {
	        return format(units[key], number, withoutSuffix);
	    }
	    function relativeSeconds(number, withoutSuffix) {
	        return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm';
	    }

	    var lv = moment.defineLocale('lv', {
	        months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'),
	        monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'),
	        weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'),
	        weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'),
	        weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY.',
	            LL : 'YYYY. [gada] D. MMMM',
	            LLL : 'YYYY. [gada] D. MMMM, HH:mm',
	            LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm'
	        },
	        calendar : {
	            sameDay : '[Šodien pulksten] LT',
	            nextDay : '[Rīt pulksten] LT',
	            nextWeek : 'dddd [pulksten] LT',
	            lastDay : '[Vakar pulksten] LT',
	            lastWeek : '[Pagājušā] dddd [pulksten] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'pēc %s',
	            past : 'pirms %s',
	            s : relativeSeconds,
	            m : relativeTimeWithSingular,
	            mm : relativeTimeWithPlural,
	            h : relativeTimeWithSingular,
	            hh : relativeTimeWithPlural,
	            d : relativeTimeWithSingular,
	            dd : relativeTimeWithPlural,
	            M : relativeTimeWithSingular,
	            MM : relativeTimeWithPlural,
	            y : relativeTimeWithSingular,
	            yy : relativeTimeWithPlural
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return lv;

	}));

/***/ },
/* 275 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Montenegrin (me)
	//! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var translator = {
	        words: { //Different grammatical cases
	            m: ['jedan minut', 'jednog minuta'],
	            mm: ['minut', 'minuta', 'minuta'],
	            h: ['jedan sat', 'jednog sata'],
	            hh: ['sat', 'sata', 'sati'],
	            dd: ['dan', 'dana', 'dana'],
	            MM: ['mjesec', 'mjeseca', 'mjeseci'],
	            yy: ['godina', 'godine', 'godina']
	        },
	        correctGrammaticalCase: function (number, wordKey) {
	            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
	        },
	        translate: function (number, withoutSuffix, key) {
	            var wordKey = translator.words[key];
	            if (key.length === 1) {
	                return withoutSuffix ? wordKey[0] : wordKey[1];
	            } else {
	                return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
	            }
	        }
	    };

	    var me = moment.defineLocale('me', {
	        months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
	        monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
	        monthsParseExact : true,
	        weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
	        weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
	        weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat: {
	            LT: 'H:mm',
	            LTS : 'H:mm:ss',
	            L: 'DD. MM. YYYY',
	            LL: 'D. MMMM YYYY',
	            LLL: 'D. MMMM YYYY H:mm',
	            LLLL: 'dddd, D. MMMM YYYY H:mm'
	        },
	        calendar: {
	            sameDay: '[danas u] LT',
	            nextDay: '[sjutra u] LT',

	            nextWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[u] [nedjelju] [u] LT';
	                case 3:
	                    return '[u] [srijedu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	                }
	            },
	            lastDay  : '[juče u] LT',
	            lastWeek : function () {
	                var lastWeekDays = [
	                    '[prošle] [nedjelje] [u] LT',
	                    '[prošlog] [ponedjeljka] [u] LT',
	                    '[prošlog] [utorka] [u] LT',
	                    '[prošle] [srijede] [u] LT',
	                    '[prošlog] [četvrtka] [u] LT',
	                    '[prošlog] [petka] [u] LT',
	                    '[prošle] [subote] [u] LT'
	                ];
	                return lastWeekDays[this.day()];
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'za %s',
	            past   : 'prije %s',
	            s      : 'nekoliko sekundi',
	            m      : translator.translate,
	            mm     : translator.translate,
	            h      : translator.translate,
	            hh     : translator.translate,
	            d      : 'dan',
	            dd     : translator.translate,
	            M      : 'mjesec',
	            MM     : translator.translate,
	            y      : 'godinu',
	            yy     : translator.translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return me;

	}));

/***/ },
/* 276 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : macedonian (mk)
	//! author : Borislav Mickov : https://github.com/B0k0

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var mk = moment.defineLocale('mk', {
	        months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'),
	        monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'),
	        weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'),
	        weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'),
	        weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'),
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'D.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY H:mm',
	            LLLL : 'dddd, D MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay : '[Денес во] LT',
	            nextDay : '[Утре во] LT',
	            nextWeek : '[Во] dddd [во] LT',
	            lastDay : '[Вчера во] LT',
	            lastWeek : function () {
	                switch (this.day()) {
	                case 0:
	                case 3:
	                case 6:
	                    return '[Изминатата] dddd [во] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[Изминатиот] dddd [во] LT';
	                }
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'после %s',
	            past : 'пред %s',
	            s : 'неколку секунди',
	            m : 'минута',
	            mm : '%d минути',
	            h : 'час',
	            hh : '%d часа',
	            d : 'ден',
	            dd : '%d дена',
	            M : 'месец',
	            MM : '%d месеци',
	            y : 'година',
	            yy : '%d години'
	        },
	        ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
	        ordinal : function (number) {
	            var lastDigit = number % 10,
	                last2Digits = number % 100;
	            if (number === 0) {
	                return number + '-ев';
	            } else if (last2Digits === 0) {
	                return number + '-ен';
	            } else if (last2Digits > 10 && last2Digits < 20) {
	                return number + '-ти';
	            } else if (lastDigit === 1) {
	                return number + '-ви';
	            } else if (lastDigit === 2) {
	                return number + '-ри';
	            } else if (lastDigit === 7 || lastDigit === 8) {
	                return number + '-ми';
	            } else {
	                return number + '-ти';
	            }
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return mk;

	}));

/***/ },
/* 277 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : malayalam (ml)
	//! author : Floyd Pink : https://github.com/floydpink

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ml = moment.defineLocale('ml', {
	        months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'),
	        monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'),
	        weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
	        weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
	        longDateFormat : {
	            LT : 'A h:mm -നു',
	            LTS : 'A h:mm:ss -നു',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, A h:mm -നു',
	            LLLL : 'dddd, D MMMM YYYY, A h:mm -നു'
	        },
	        calendar : {
	            sameDay : '[ഇന്ന്] LT',
	            nextDay : '[നാളെ] LT',
	            nextWeek : 'dddd, LT',
	            lastDay : '[ഇന്നലെ] LT',
	            lastWeek : '[കഴിഞ്ഞ] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s കഴിഞ്ഞ്',
	            past : '%s മുൻപ്',
	            s : 'അൽപ നിമിഷങ്ങൾ',
	            m : 'ഒരു മിനിറ്റ്',
	            mm : '%d മിനിറ്റ്',
	            h : 'ഒരു മണിക്കൂർ',
	            hh : '%d മണിക്കൂർ',
	            d : 'ഒരു ദിവസം',
	            dd : '%d ദിവസം',
	            M : 'ഒരു മാസം',
	            MM : '%d മാസം',
	            y : 'ഒരു വർഷം',
	            yy : '%d വർഷം'
	        },
	        meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if ((meridiem === 'രാത്രി' && hour >= 4) ||
	                    meridiem === 'ഉച്ച കഴിഞ്ഞ്' ||
	                    meridiem === 'വൈകുന്നേരം') {
	                return hour + 12;
	            } else {
	                return hour;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'രാത്രി';
	            } else if (hour < 12) {
	                return 'രാവിലെ';
	            } else if (hour < 17) {
	                return 'ഉച്ച കഴിഞ്ഞ്';
	            } else if (hour < 20) {
	                return 'വൈകുന്നേരം';
	            } else {
	                return 'രാത്രി';
	            }
	        }
	    });

	    return ml;

	}));

/***/ },
/* 278 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Marathi (mr)
	//! author : Harshad Kale : https://github.com/kalehv
	//! author : Vivek Athalye : https://github.com/vnathalye

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '१',
	        '2': '२',
	        '3': '३',
	        '4': '४',
	        '5': '५',
	        '6': '६',
	        '7': '७',
	        '8': '८',
	        '9': '९',
	        '0': '०'
	    },
	    numberMap = {
	        '१': '1',
	        '२': '2',
	        '३': '3',
	        '४': '4',
	        '५': '5',
	        '६': '6',
	        '७': '7',
	        '८': '8',
	        '९': '9',
	        '०': '0'
	    };

	    function relativeTimeMr(number, withoutSuffix, string, isFuture)
	    {
	        var output = '';
	        if (withoutSuffix) {
	            switch (string) {
	                case 's': output = 'काही सेकंद'; break;
	                case 'm': output = 'एक मिनिट'; break;
	                case 'mm': output = '%d मिनिटे'; break;
	                case 'h': output = 'एक तास'; break;
	                case 'hh': output = '%d तास'; break;
	                case 'd': output = 'एक दिवस'; break;
	                case 'dd': output = '%d दिवस'; break;
	                case 'M': output = 'एक महिना'; break;
	                case 'MM': output = '%d महिने'; break;
	                case 'y': output = 'एक वर्ष'; break;
	                case 'yy': output = '%d वर्षे'; break;
	            }
	        }
	        else {
	            switch (string) {
	                case 's': output = 'काही सेकंदां'; break;
	                case 'm': output = 'एका मिनिटा'; break;
	                case 'mm': output = '%d मिनिटां'; break;
	                case 'h': output = 'एका तासा'; break;
	                case 'hh': output = '%d तासां'; break;
	                case 'd': output = 'एका दिवसा'; break;
	                case 'dd': output = '%d दिवसां'; break;
	                case 'M': output = 'एका महिन्या'; break;
	                case 'MM': output = '%d महिन्यां'; break;
	                case 'y': output = 'एका वर्षा'; break;
	                case 'yy': output = '%d वर्षां'; break;
	            }
	        }
	        return output.replace(/%d/i, number);
	    }

	    var mr = moment.defineLocale('mr', {
	        months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'),
	        monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
	        weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'),
	        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
	        longDateFormat : {
	            LT : 'A h:mm वाजता',
	            LTS : 'A h:mm:ss वाजता',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, A h:mm वाजता',
	            LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता'
	        },
	        calendar : {
	            sameDay : '[आज] LT',
	            nextDay : '[उद्या] LT',
	            nextWeek : 'dddd, LT',
	            lastDay : '[काल] LT',
	            lastWeek: '[मागील] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future: '%sमध्ये',
	            past: '%sपूर्वी',
	            s: relativeTimeMr,
	            m: relativeTimeMr,
	            mm: relativeTimeMr,
	            h: relativeTimeMr,
	            hh: relativeTimeMr,
	            d: relativeTimeMr,
	            dd: relativeTimeMr,
	            M: relativeTimeMr,
	            MM: relativeTimeMr,
	            y: relativeTimeMr,
	            yy: relativeTimeMr
	        },
	        preparse: function (string) {
	            return string.replace(/[१२३४५६७८९०]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'रात्री') {
	                return hour < 4 ? hour : hour + 12;
	            } else if (meridiem === 'सकाळी') {
	                return hour;
	            } else if (meridiem === 'दुपारी') {
	                return hour >= 10 ? hour : hour + 12;
	            } else if (meridiem === 'सायंकाळी') {
	                return hour + 12;
	            }
	        },
	        meridiem: function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'रात्री';
	            } else if (hour < 10) {
	                return 'सकाळी';
	            } else if (hour < 17) {
	                return 'दुपारी';
	            } else if (hour < 20) {
	                return 'सायंकाळी';
	            } else {
	                return 'रात्री';
	            }
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return mr;

	}));

/***/ },
/* 279 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Bahasa Malaysia (ms-MY)
	//! author : Weldan Jamili : https://github.com/weldan

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ms = moment.defineLocale('ms', {
	        months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
	        monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
	        weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
	        weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
	        weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
	        longDateFormat : {
	            LT : 'HH.mm',
	            LTS : 'HH.mm.ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY [pukul] HH.mm',
	            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	        },
	        meridiemParse: /pagi|tengahari|petang|malam/,
	        meridiemHour: function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'pagi') {
	                return hour;
	            } else if (meridiem === 'tengahari') {
	                return hour >= 11 ? hour : hour + 12;
	            } else if (meridiem === 'petang' || meridiem === 'malam') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 11) {
	                return 'pagi';
	            } else if (hours < 15) {
	                return 'tengahari';
	            } else if (hours < 19) {
	                return 'petang';
	            } else {
	                return 'malam';
	            }
	        },
	        calendar : {
	            sameDay : '[Hari ini pukul] LT',
	            nextDay : '[Esok pukul] LT',
	            nextWeek : 'dddd [pukul] LT',
	            lastDay : '[Kelmarin pukul] LT',
	            lastWeek : 'dddd [lepas pukul] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'dalam %s',
	            past : '%s yang lepas',
	            s : 'beberapa saat',
	            m : 'seminit',
	            mm : '%d minit',
	            h : 'sejam',
	            hh : '%d jam',
	            d : 'sehari',
	            dd : '%d hari',
	            M : 'sebulan',
	            MM : '%d bulan',
	            y : 'setahun',
	            yy : '%d tahun'
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ms;

	}));

/***/ },
/* 280 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Bahasa Malaysia (ms-MY)
	//! author : Weldan Jamili : https://github.com/weldan

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var ms_my = moment.defineLocale('ms-my', {
	        months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
	        monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
	        weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
	        weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
	        weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
	        longDateFormat : {
	            LT : 'HH.mm',
	            LTS : 'HH.mm.ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY [pukul] HH.mm',
	            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	        },
	        meridiemParse: /pagi|tengahari|petang|malam/,
	        meridiemHour: function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'pagi') {
	                return hour;
	            } else if (meridiem === 'tengahari') {
	                return hour >= 11 ? hour : hour + 12;
	            } else if (meridiem === 'petang' || meridiem === 'malam') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 11) {
	                return 'pagi';
	            } else if (hours < 15) {
	                return 'tengahari';
	            } else if (hours < 19) {
	                return 'petang';
	            } else {
	                return 'malam';
	            }
	        },
	        calendar : {
	            sameDay : '[Hari ini pukul] LT',
	            nextDay : '[Esok pukul] LT',
	            nextWeek : 'dddd [pukul] LT',
	            lastDay : '[Kelmarin pukul] LT',
	            lastWeek : 'dddd [lepas pukul] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'dalam %s',
	            past : '%s yang lepas',
	            s : 'beberapa saat',
	            m : 'seminit',
	            mm : '%d minit',
	            h : 'sejam',
	            hh : '%d jam',
	            d : 'sehari',
	            dd : '%d hari',
	            M : 'sebulan',
	            MM : '%d bulan',
	            y : 'setahun',
	            yy : '%d tahun'
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ms_my;

	}));

/***/ },
/* 281 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Burmese (my)
	//! author : Squar team, mysquar.com

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '၁',
	        '2': '၂',
	        '3': '၃',
	        '4': '၄',
	        '5': '၅',
	        '6': '၆',
	        '7': '၇',
	        '8': '၈',
	        '9': '၉',
	        '0': '၀'
	    }, numberMap = {
	        '၁': '1',
	        '၂': '2',
	        '၃': '3',
	        '၄': '4',
	        '၅': '5',
	        '၆': '6',
	        '၇': '7',
	        '၈': '8',
	        '၉': '9',
	        '၀': '0'
	    };

	    var my = moment.defineLocale('my', {
	        months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
	        monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'),
	        weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
	        weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
	        weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),

	        longDateFormat: {
	            LT: 'HH:mm',
	            LTS: 'HH:mm:ss',
	            L: 'DD/MM/YYYY',
	            LL: 'D MMMM YYYY',
	            LLL: 'D MMMM YYYY HH:mm',
	            LLLL: 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar: {
	            sameDay: '[ယနေ.] LT [မှာ]',
	            nextDay: '[မနက်ဖြန်] LT [မှာ]',
	            nextWeek: 'dddd LT [မှာ]',
	            lastDay: '[မနေ.က] LT [မှာ]',
	            lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]',
	            sameElse: 'L'
	        },
	        relativeTime: {
	            future: 'လာမည့် %s မှာ',
	            past: 'လွန်ခဲ့သော %s က',
	            s: 'စက္ကန်.အနည်းငယ်',
	            m: 'တစ်မိနစ်',
	            mm: '%d မိနစ်',
	            h: 'တစ်နာရီ',
	            hh: '%d နာရီ',
	            d: 'တစ်ရက်',
	            dd: '%d ရက်',
	            M: 'တစ်လ',
	            MM: '%d လ',
	            y: 'တစ်နှစ်',
	            yy: '%d နှစ်'
	        },
	        preparse: function (string) {
	            return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        week: {
	            dow: 1, // Monday is the first day of the week.
	            doy: 4 // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return my;

	}));

/***/ },
/* 282 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : norwegian bokmål (nb)
	//! authors : Espen Hovlandsdal : https://github.com/rexxars
	//!           Sigurd Gartmann : https://github.com/sigurdga

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var nb = moment.defineLocale('nb', {
	        months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
	        monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
	        weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
	        weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY [kl.] HH:mm',
	            LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
	        },
	        calendar : {
	            sameDay: '[i dag kl.] LT',
	            nextDay: '[i morgen kl.] LT',
	            nextWeek: 'dddd [kl.] LT',
	            lastDay: '[i går kl.] LT',
	            lastWeek: '[forrige] dddd [kl.] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'om %s',
	            past : '%s siden',
	            s : 'noen sekunder',
	            m : 'ett minutt',
	            mm : '%d minutter',
	            h : 'en time',
	            hh : '%d timer',
	            d : 'en dag',
	            dd : '%d dager',
	            M : 'en måned',
	            MM : '%d måneder',
	            y : 'ett år',
	            yy : '%d år'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return nb;

	}));

/***/ },
/* 283 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : nepali/nepalese
	//! author : suvash : https://github.com/suvash

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '१',
	        '2': '२',
	        '3': '३',
	        '4': '४',
	        '5': '५',
	        '6': '६',
	        '7': '७',
	        '8': '८',
	        '9': '९',
	        '0': '०'
	    },
	    numberMap = {
	        '१': '1',
	        '२': '2',
	        '३': '3',
	        '४': '4',
	        '५': '5',
	        '६': '6',
	        '७': '7',
	        '८': '8',
	        '९': '9',
	        '०': '0'
	    };

	    var ne = moment.defineLocale('ne', {
	        months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'),
	        monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'),
	        weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'),
	        weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'Aको h:mm बजे',
	            LTS : 'Aको h:mm:ss बजे',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, Aको h:mm बजे',
	            LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे'
	        },
	        preparse: function (string) {
	            return string.replace(/[१२३४५६७८९०]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        meridiemParse: /राति|बिहान|दिउँसो|साँझ/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'राति') {
	                return hour < 4 ? hour : hour + 12;
	            } else if (meridiem === 'बिहान') {
	                return hour;
	            } else if (meridiem === 'दिउँसो') {
	                return hour >= 10 ? hour : hour + 12;
	            } else if (meridiem === 'साँझ') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 3) {
	                return 'राति';
	            } else if (hour < 12) {
	                return 'बिहान';
	            } else if (hour < 16) {
	                return 'दिउँसो';
	            } else if (hour < 20) {
	                return 'साँझ';
	            } else {
	                return 'राति';
	            }
	        },
	        calendar : {
	            sameDay : '[आज] LT',
	            nextDay : '[भोलि] LT',
	            nextWeek : '[आउँदो] dddd[,] LT',
	            lastDay : '[हिजो] LT',
	            lastWeek : '[गएको] dddd[,] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%sमा',
	            past : '%s अगाडि',
	            s : 'केही क्षण',
	            m : 'एक मिनेट',
	            mm : '%d मिनेट',
	            h : 'एक घण्टा',
	            hh : '%d घण्टा',
	            d : 'एक दिन',
	            dd : '%d दिन',
	            M : 'एक महिना',
	            MM : '%d महिना',
	            y : 'एक बर्ष',
	            yy : '%d बर्ष'
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ne;

	}));

/***/ },
/* 284 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : dutch (nl)
	//! author : Joris Röling : https://github.com/jjupiter

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'),
	        monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');

	    var nl = moment.defineLocale('nl', {
	        months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
	        monthsShort : function (m, format) {
	            if (/-MMM-/.test(format)) {
	                return monthsShortWithoutDots[m.month()];
	            } else {
	                return monthsShortWithDots[m.month()];
	            }
	        },
	        monthsParseExact : true,
	        weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
	        weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
	        weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD-MM-YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[vandaag om] LT',
	            nextDay: '[morgen om] LT',
	            nextWeek: 'dddd [om] LT',
	            lastDay: '[gisteren om] LT',
	            lastWeek: '[afgelopen] dddd [om] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'over %s',
	            past : '%s geleden',
	            s : 'een paar seconden',
	            m : 'één minuut',
	            mm : '%d minuten',
	            h : 'één uur',
	            hh : '%d uur',
	            d : 'één dag',
	            dd : '%d dagen',
	            M : 'één maand',
	            MM : '%d maanden',
	            y : 'één jaar',
	            yy : '%d jaar'
	        },
	        ordinalParse: /\d{1,2}(ste|de)/,
	        ordinal : function (number) {
	            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return nl;

	}));

/***/ },
/* 285 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : norwegian nynorsk (nn)
	//! author : https://github.com/mechuwind

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var nn = moment.defineLocale('nn', {
	        months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
	        monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
	        weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
	        weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'),
	        weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY [kl.] H:mm',
	            LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
	        },
	        calendar : {
	            sameDay: '[I dag klokka] LT',
	            nextDay: '[I morgon klokka] LT',
	            nextWeek: 'dddd [klokka] LT',
	            lastDay: '[I går klokka] LT',
	            lastWeek: '[Føregåande] dddd [klokka] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'om %s',
	            past : '%s sidan',
	            s : 'nokre sekund',
	            m : 'eit minutt',
	            mm : '%d minutt',
	            h : 'ein time',
	            hh : '%d timar',
	            d : 'ein dag',
	            dd : '%d dagar',
	            M : 'ein månad',
	            MM : '%d månader',
	            y : 'eit år',
	            yy : '%d år'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return nn;

	}));

/***/ },
/* 286 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : punjabi india (pa-in)
	//! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '੧',
	        '2': '੨',
	        '3': '੩',
	        '4': '੪',
	        '5': '੫',
	        '6': '੬',
	        '7': '੭',
	        '8': '੮',
	        '9': '੯',
	        '0': '੦'
	    },
	    numberMap = {
	        '੧': '1',
	        '੨': '2',
	        '੩': '3',
	        '੪': '4',
	        '੫': '5',
	        '੬': '6',
	        '੭': '7',
	        '੮': '8',
	        '੯': '9',
	        '੦': '0'
	    };

	    var pa_in = moment.defineLocale('pa-in', {
	        // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi.
	        months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
	        monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
	        weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'),
	        weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
	        weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
	        longDateFormat : {
	            LT : 'A h:mm ਵਜੇ',
	            LTS : 'A h:mm:ss ਵਜੇ',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, A h:mm ਵਜੇ',
	            LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ'
	        },
	        calendar : {
	            sameDay : '[ਅਜ] LT',
	            nextDay : '[ਕਲ] LT',
	            nextWeek : 'dddd, LT',
	            lastDay : '[ਕਲ] LT',
	            lastWeek : '[ਪਿਛਲੇ] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s ਵਿੱਚ',
	            past : '%s ਪਿਛਲੇ',
	            s : 'ਕੁਝ ਸਕਿੰਟ',
	            m : 'ਇਕ ਮਿੰਟ',
	            mm : '%d ਮਿੰਟ',
	            h : 'ਇੱਕ ਘੰਟਾ',
	            hh : '%d ਘੰਟੇ',
	            d : 'ਇੱਕ ਦਿਨ',
	            dd : '%d ਦਿਨ',
	            M : 'ਇੱਕ ਮਹੀਨਾ',
	            MM : '%d ਮਹੀਨੇ',
	            y : 'ਇੱਕ ਸਾਲ',
	            yy : '%d ਸਾਲ'
	        },
	        preparse: function (string) {
	            return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        // Punjabi notation for meridiems are quite fuzzy in practice. While there exists
	        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi.
	        meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'ਰਾਤ') {
	                return hour < 4 ? hour : hour + 12;
	            } else if (meridiem === 'ਸਵੇਰ') {
	                return hour;
	            } else if (meridiem === 'ਦੁਪਹਿਰ') {
	                return hour >= 10 ? hour : hour + 12;
	            } else if (meridiem === 'ਸ਼ਾਮ') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'ਰਾਤ';
	            } else if (hour < 10) {
	                return 'ਸਵੇਰ';
	            } else if (hour < 17) {
	                return 'ਦੁਪਹਿਰ';
	            } else if (hour < 20) {
	                return 'ਸ਼ਾਮ';
	            } else {
	                return 'ਰਾਤ';
	            }
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return pa_in;

	}));

/***/ },
/* 287 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : polish (pl)
	//! author : Rafal Hirsz : https://github.com/evoL

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'),
	        monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_');
	    function plural(n) {
	        return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
	    }
	    function translate(number, withoutSuffix, key) {
	        var result = number + ' ';
	        switch (key) {
	        case 'm':
	            return withoutSuffix ? 'minuta' : 'minutę';
	        case 'mm':
	            return result + (plural(number) ? 'minuty' : 'minut');
	        case 'h':
	            return withoutSuffix  ? 'godzina'  : 'godzinę';
	        case 'hh':
	            return result + (plural(number) ? 'godziny' : 'godzin');
	        case 'MM':
	            return result + (plural(number) ? 'miesiące' : 'miesięcy');
	        case 'yy':
	            return result + (plural(number) ? 'lata' : 'lat');
	        }
	    }

	    var pl = moment.defineLocale('pl', {
	        months : function (momentToFormat, format) {
	            if (format === '') {
	                // Hack: if format empty we know this is used to generate
	                // RegExp by moment. Give then back both valid forms of months
	                // in RegExp ready format.
	                return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')';
	            } else if (/D MMMM/.test(format)) {
	                return monthsSubjective[momentToFormat.month()];
	            } else {
	                return monthsNominative[momentToFormat.month()];
	            }
	        },
	        monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
	        weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'),
	        weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'),
	        weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Dziś o] LT',
	            nextDay: '[Jutro o] LT',
	            nextWeek: '[W] dddd [o] LT',
	            lastDay: '[Wczoraj o] LT',
	            lastWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[W zeszłą niedzielę o] LT';
	                case 3:
	                    return '[W zeszłą środę o] LT';
	                case 6:
	                    return '[W zeszłą sobotę o] LT';
	                default:
	                    return '[W zeszły] dddd [o] LT';
	                }
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'za %s',
	            past : '%s temu',
	            s : 'kilka sekund',
	            m : translate,
	            mm : translate,
	            h : translate,
	            hh : translate,
	            d : '1 dzień',
	            dd : '%d dni',
	            M : 'miesiąc',
	            MM : translate,
	            y : 'rok',
	            yy : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return pl;

	}));

/***/ },
/* 288 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : portuguese (pt)
	//! author : Jefferson : https://github.com/jalex79

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var pt = moment.defineLocale('pt', {
	        months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'),
	        monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'),
	        weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'),
	        weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
	        weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D [de] MMMM [de] YYYY',
	            LLL : 'D [de] MMMM [de] YYYY HH:mm',
	            LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Hoje às] LT',
	            nextDay: '[Amanhã às] LT',
	            nextWeek: 'dddd [às] LT',
	            lastDay: '[Ontem às] LT',
	            lastWeek: function () {
	                return (this.day() === 0 || this.day() === 6) ?
	                    '[Último] dddd [às] LT' : // Saturday + Sunday
	                    '[Última] dddd [às] LT'; // Monday - Friday
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'em %s',
	            past : 'há %s',
	            s : 'segundos',
	            m : 'um minuto',
	            mm : '%d minutos',
	            h : 'uma hora',
	            hh : '%d horas',
	            d : 'um dia',
	            dd : '%d dias',
	            M : 'um mês',
	            MM : '%d meses',
	            y : 'um ano',
	            yy : '%d anos'
	        },
	        ordinalParse: /\d{1,2}º/,
	        ordinal : '%dº',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return pt;

	}));

/***/ },
/* 289 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : brazilian portuguese (pt-br)
	//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var pt_br = moment.defineLocale('pt-br', {
	        months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'),
	        monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'),
	        weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
	        weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
	        weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D [de] MMMM [de] YYYY',
	            LLL : 'D [de] MMMM [de] YYYY [às] HH:mm',
	            LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm'
	        },
	        calendar : {
	            sameDay: '[Hoje às] LT',
	            nextDay: '[Amanhã às] LT',
	            nextWeek: 'dddd [às] LT',
	            lastDay: '[Ontem às] LT',
	            lastWeek: function () {
	                return (this.day() === 0 || this.day() === 6) ?
	                    '[Último] dddd [às] LT' : // Saturday + Sunday
	                    '[Última] dddd [às] LT'; // Monday - Friday
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'em %s',
	            past : '%s atrás',
	            s : 'poucos segundos',
	            m : 'um minuto',
	            mm : '%d minutos',
	            h : 'uma hora',
	            hh : '%d horas',
	            d : 'um dia',
	            dd : '%d dias',
	            M : 'um mês',
	            MM : '%d meses',
	            y : 'um ano',
	            yy : '%d anos'
	        },
	        ordinalParse: /\d{1,2}º/,
	        ordinal : '%dº'
	    });

	    return pt_br;

	}));

/***/ },
/* 290 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : romanian (ro)
	//! author : Vlad Gurdiga : https://github.com/gurdiga
	//! author : Valentin Agachi : https://github.com/avaly

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function relativeTimeWithPlural(number, withoutSuffix, key) {
	        var format = {
	                'mm': 'minute',
	                'hh': 'ore',
	                'dd': 'zile',
	                'MM': 'luni',
	                'yy': 'ani'
	            },
	            separator = ' ';
	        if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
	            separator = ' de ';
	        }
	        return number + separator + format[key];
	    }

	    var ro = moment.defineLocale('ro', {
	        months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'),
	        monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'),
	        monthsParseExact: true,
	        weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'),
	        weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'),
	        weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY H:mm',
	            LLLL : 'dddd, D MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay: '[azi la] LT',
	            nextDay: '[mâine la] LT',
	            nextWeek: 'dddd [la] LT',
	            lastDay: '[ieri la] LT',
	            lastWeek: '[fosta] dddd [la] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'peste %s',
	            past : '%s în urmă',
	            s : 'câteva secunde',
	            m : 'un minut',
	            mm : relativeTimeWithPlural,
	            h : 'o oră',
	            hh : relativeTimeWithPlural,
	            d : 'o zi',
	            dd : relativeTimeWithPlural,
	            M : 'o lună',
	            MM : relativeTimeWithPlural,
	            y : 'un an',
	            yy : relativeTimeWithPlural
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ro;

	}));

/***/ },
/* 291 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : russian (ru)
	//! author : Viktorminator : https://github.com/Viktorminator
	//! Author : Menelion Elensúle : https://github.com/Oire
	//! author : Коренберг Марк : https://github.com/socketpair

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function plural(word, num) {
	        var forms = word.split('_');
	        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
	    }
	    function relativeTimeWithPlural(number, withoutSuffix, key) {
	        var format = {
	            'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
	            'hh': 'час_часа_часов',
	            'dd': 'день_дня_дней',
	            'MM': 'месяц_месяца_месяцев',
	            'yy': 'год_года_лет'
	        };
	        if (key === 'm') {
	            return withoutSuffix ? 'минута' : 'минуту';
	        }
	        else {
	            return number + ' ' + plural(format[key], +number);
	        }
	    }
	    var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i];

	    // http://new.gramota.ru/spravka/rules/139-prop : § 103
	    // Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637
	    // CLDR data:          http://www.unicode.org/cldr/charts/28/summary/ru.html#1753
	    var ru = moment.defineLocale('ru', {
	        months : {
	            format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'),
	            standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_')
	        },
	        monthsShort : {
	            // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ?
	            format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'),
	            standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_')
	        },
	        weekdays : {
	            standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
	            format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'),
	            isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/
	        },
	        weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
	        weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
	        monthsParse : monthsParse,
	        longMonthsParse : monthsParse,
	        shortMonthsParse : monthsParse,
	        monthsRegex: /^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,
	        monthsShortRegex: /^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,
	        monthsStrictRegex: /^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|марта?|июн[яь]|июл[яь]|ма[яй])/i,
	        monthsShortStrictRegex: /^(нояб\.|февр\.|сент\.|июль|янв\.|июн[яь]|мар[.т]|авг\.|апр\.|окт\.|дек\.|ма[яй])/i,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY г.',
	            LLL : 'D MMMM YYYY г., HH:mm',
	            LLLL : 'dddd, D MMMM YYYY г., HH:mm'
	        },
	        calendar : {
	            sameDay: '[Сегодня в] LT',
	            nextDay: '[Завтра в] LT',
	            lastDay: '[Вчера в] LT',
	            nextWeek: function (now) {
	                if (now.week() !== this.week()) {
	                    switch (this.day()) {
	                    case 0:
	                        return '[В следующее] dddd [в] LT';
	                    case 1:
	                    case 2:
	                    case 4:
	                        return '[В следующий] dddd [в] LT';
	                    case 3:
	                    case 5:
	                    case 6:
	                        return '[В следующую] dddd [в] LT';
	                    }
	                } else {
	                    if (this.day() === 2) {
	                        return '[Во] dddd [в] LT';
	                    } else {
	                        return '[В] dddd [в] LT';
	                    }
	                }
	            },
	            lastWeek: function (now) {
	                if (now.week() !== this.week()) {
	                    switch (this.day()) {
	                    case 0:
	                        return '[В прошлое] dddd [в] LT';
	                    case 1:
	                    case 2:
	                    case 4:
	                        return '[В прошлый] dddd [в] LT';
	                    case 3:
	                    case 5:
	                    case 6:
	                        return '[В прошлую] dddd [в] LT';
	                    }
	                } else {
	                    if (this.day() === 2) {
	                        return '[Во] dddd [в] LT';
	                    } else {
	                        return '[В] dddd [в] LT';
	                    }
	                }
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'через %s',
	            past : '%s назад',
	            s : 'несколько секунд',
	            m : relativeTimeWithPlural,
	            mm : relativeTimeWithPlural,
	            h : 'час',
	            hh : relativeTimeWithPlural,
	            d : 'день',
	            dd : relativeTimeWithPlural,
	            M : 'месяц',
	            MM : relativeTimeWithPlural,
	            y : 'год',
	            yy : relativeTimeWithPlural
	        },
	        meridiemParse: /ночи|утра|дня|вечера/i,
	        isPM : function (input) {
	            return /^(дня|вечера)$/.test(input);
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'ночи';
	            } else if (hour < 12) {
	                return 'утра';
	            } else if (hour < 17) {
	                return 'дня';
	            } else {
	                return 'вечера';
	            }
	        },
	        ordinalParse: /\d{1,2}-(й|го|я)/,
	        ordinal: function (number, period) {
	            switch (period) {
	            case 'M':
	            case 'd':
	            case 'DDD':
	                return number + '-й';
	            case 'D':
	                return number + '-го';
	            case 'w':
	            case 'W':
	                return number + '-я';
	            default:
	                return number;
	            }
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ru;

	}));

/***/ },
/* 292 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Northern Sami (se)
	//! authors : Bård Rolstad Henriksen : https://github.com/karamell

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';



	    var se = moment.defineLocale('se', {
	        months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'),
	        monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'),
	        weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'),
	        weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'),
	        weekdaysMin : 's_v_m_g_d_b_L'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'MMMM D. [b.] YYYY',
	            LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm',
	            LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm'
	        },
	        calendar : {
	            sameDay: '[otne ti] LT',
	            nextDay: '[ihttin ti] LT',
	            nextWeek: 'dddd [ti] LT',
	            lastDay: '[ikte ti] LT',
	            lastWeek: '[ovddit] dddd [ti] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : '%s geažes',
	            past : 'maŋit %s',
	            s : 'moadde sekunddat',
	            m : 'okta minuhta',
	            mm : '%d minuhtat',
	            h : 'okta diimmu',
	            hh : '%d diimmut',
	            d : 'okta beaivi',
	            dd : '%d beaivvit',
	            M : 'okta mánnu',
	            MM : '%d mánut',
	            y : 'okta jahki',
	            yy : '%d jagit'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return se;

	}));

/***/ },
/* 293 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Sinhalese (si)
	//! author : Sampath Sitinamaluwa : https://github.com/sampathsris

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    /*jshint -W100*/
	    var si = moment.defineLocale('si', {
	        months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'),
	        monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'),
	        weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'),
	        weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන'.split('_'),
	        weekdaysMin : 'ඉ_ස_අ_බ_බ්‍ර_සි_සෙ'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'a h:mm',
	            LTS : 'a h:mm:ss',
	            L : 'YYYY/MM/DD',
	            LL : 'YYYY MMMM D',
	            LLL : 'YYYY MMMM D, a h:mm',
	            LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss'
	        },
	        calendar : {
	            sameDay : '[අද] LT[ට]',
	            nextDay : '[හෙට] LT[ට]',
	            nextWeek : 'dddd LT[ට]',
	            lastDay : '[ඊයේ] LT[ට]',
	            lastWeek : '[පසුගිය] dddd LT[ට]',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%sකින්',
	            past : '%sකට පෙර',
	            s : 'තත්පර කිහිපය',
	            m : 'මිනිත්තුව',
	            mm : 'මිනිත්තු %d',
	            h : 'පැය',
	            hh : 'පැය %d',
	            d : 'දිනය',
	            dd : 'දින %d',
	            M : 'මාසය',
	            MM : 'මාස %d',
	            y : 'වසර',
	            yy : 'වසර %d'
	        },
	        ordinalParse: /\d{1,2} වැනි/,
	        ordinal : function (number) {
	            return number + ' වැනි';
	        },
	        meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,
	        isPM : function (input) {
	            return input === 'ප.ව.' || input === 'පස් වරු';
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours > 11) {
	                return isLower ? 'ප.ව.' : 'පස් වරු';
	            } else {
	                return isLower ? 'පෙ.ව.' : 'පෙර වරු';
	            }
	        }
	    });

	    return si;

	}));

/***/ },
/* 294 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : slovak (sk)
	//! author : Martin Minka : https://github.com/k2s
	//! based on work of petrbela : https://github.com/petrbela

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'),
	        monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_');
	    function plural(n) {
	        return (n > 1) && (n < 5);
	    }
	    function translate(number, withoutSuffix, key, isFuture) {
	        var result = number + ' ';
	        switch (key) {
	        case 's':  // a few seconds / in a few seconds / a few seconds ago
	            return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
	        case 'm':  // a minute / in a minute / a minute ago
	            return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
	        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'minúty' : 'minút');
	            } else {
	                return result + 'minútami';
	            }
	            break;
	        case 'h':  // an hour / in an hour / an hour ago
	            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
	        case 'hh': // 9 hours / in 9 hours / 9 hours ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'hodiny' : 'hodín');
	            } else {
	                return result + 'hodinami';
	            }
	            break;
	        case 'd':  // a day / in a day / a day ago
	            return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
	        case 'dd': // 9 days / in 9 days / 9 days ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'dni' : 'dní');
	            } else {
	                return result + 'dňami';
	            }
	            break;
	        case 'M':  // a month / in a month / a month ago
	            return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
	        case 'MM': // 9 months / in 9 months / 9 months ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'mesiace' : 'mesiacov');
	            } else {
	                return result + 'mesiacmi';
	            }
	            break;
	        case 'y':  // a year / in a year / a year ago
	            return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
	        case 'yy': // 9 years / in 9 years / 9 years ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'roky' : 'rokov');
	            } else {
	                return result + 'rokmi';
	            }
	            break;
	        }
	    }

	    var sk = moment.defineLocale('sk', {
	        months : months,
	        monthsShort : monthsShort,
	        weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'),
	        weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'),
	        weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'),
	        longDateFormat : {
	            LT: 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY H:mm',
	            LLLL : 'dddd D. MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay: '[dnes o] LT',
	            nextDay: '[zajtra o] LT',
	            nextWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[v nedeľu o] LT';
	                case 1:
	                case 2:
	                    return '[v] dddd [o] LT';
	                case 3:
	                    return '[v stredu o] LT';
	                case 4:
	                    return '[vo štvrtok o] LT';
	                case 5:
	                    return '[v piatok o] LT';
	                case 6:
	                    return '[v sobotu o] LT';
	                }
	            },
	            lastDay: '[včera o] LT',
	            lastWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[minulú nedeľu o] LT';
	                case 1:
	                case 2:
	                    return '[minulý] dddd [o] LT';
	                case 3:
	                    return '[minulú stredu o] LT';
	                case 4:
	                case 5:
	                    return '[minulý] dddd [o] LT';
	                case 6:
	                    return '[minulú sobotu o] LT';
	                }
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'za %s',
	            past : 'pred %s',
	            s : translate,
	            m : translate,
	            mm : translate,
	            h : translate,
	            hh : translate,
	            d : translate,
	            dd : translate,
	            M : translate,
	            MM : translate,
	            y : translate,
	            yy : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return sk;

	}));

/***/ },
/* 295 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : slovenian (sl)
	//! author : Robert Sedovšek : https://github.com/sedovsek

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function processRelativeTime(number, withoutSuffix, key, isFuture) {
	        var result = number + ' ';
	        switch (key) {
	        case 's':
	            return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami';
	        case 'm':
	            return withoutSuffix ? 'ena minuta' : 'eno minuto';
	        case 'mm':
	            if (number === 1) {
	                result += withoutSuffix ? 'minuta' : 'minuto';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'minuti' : 'minutama';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'minute' : 'minutami';
	            } else {
	                result += withoutSuffix || isFuture ? 'minut' : 'minutami';
	            }
	            return result;
	        case 'h':
	            return withoutSuffix ? 'ena ura' : 'eno uro';
	        case 'hh':
	            if (number === 1) {
	                result += withoutSuffix ? 'ura' : 'uro';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'uri' : 'urama';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'ure' : 'urami';
	            } else {
	                result += withoutSuffix || isFuture ? 'ur' : 'urami';
	            }
	            return result;
	        case 'd':
	            return withoutSuffix || isFuture ? 'en dan' : 'enim dnem';
	        case 'dd':
	            if (number === 1) {
	                result += withoutSuffix || isFuture ? 'dan' : 'dnem';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'dni' : 'dnevoma';
	            } else {
	                result += withoutSuffix || isFuture ? 'dni' : 'dnevi';
	            }
	            return result;
	        case 'M':
	            return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem';
	        case 'MM':
	            if (number === 1) {
	                result += withoutSuffix || isFuture ? 'mesec' : 'mesecem';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'meseca' : 'mesecema';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'mesece' : 'meseci';
	            } else {
	                result += withoutSuffix || isFuture ? 'mesecev' : 'meseci';
	            }
	            return result;
	        case 'y':
	            return withoutSuffix || isFuture ? 'eno leto' : 'enim letom';
	        case 'yy':
	            if (number === 1) {
	                result += withoutSuffix || isFuture ? 'leto' : 'letom';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'leti' : 'letoma';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'leta' : 'leti';
	            } else {
	                result += withoutSuffix || isFuture ? 'let' : 'leti';
	            }
	            return result;
	        }
	    }

	    var sl = moment.defineLocale('sl', {
	        months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'),
	        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
	        monthsParseExact: true,
	        weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'),
	        weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'),
	        weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'H:mm',
	            LTS : 'H:mm:ss',
	            L : 'DD. MM. YYYY',
	            LL : 'D. MMMM YYYY',
	            LLL : 'D. MMMM YYYY H:mm',
	            LLLL : 'dddd, D. MMMM YYYY H:mm'
	        },
	        calendar : {
	            sameDay  : '[danes ob] LT',
	            nextDay  : '[jutri ob] LT',

	            nextWeek : function () {
	                switch (this.day()) {
	                case 0:
	                    return '[v] [nedeljo] [ob] LT';
	                case 3:
	                    return '[v] [sredo] [ob] LT';
	                case 6:
	                    return '[v] [soboto] [ob] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[v] dddd [ob] LT';
	                }
	            },
	            lastDay  : '[včeraj ob] LT',
	            lastWeek : function () {
	                switch (this.day()) {
	                case 0:
	                    return '[prejšnjo] [nedeljo] [ob] LT';
	                case 3:
	                    return '[prejšnjo] [sredo] [ob] LT';
	                case 6:
	                    return '[prejšnjo] [soboto] [ob] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[prejšnji] dddd [ob] LT';
	                }
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'čez %s',
	            past   : 'pred %s',
	            s      : processRelativeTime,
	            m      : processRelativeTime,
	            mm     : processRelativeTime,
	            h      : processRelativeTime,
	            hh     : processRelativeTime,
	            d      : processRelativeTime,
	            dd     : processRelativeTime,
	            M      : processRelativeTime,
	            MM     : processRelativeTime,
	            y      : processRelativeTime,
	            yy     : processRelativeTime
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return sl;

	}));

/***/ },
/* 296 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Albanian (sq)
	//! author : Flakërim Ismani : https://github.com/flakerimi
	//! author: Menelion Elensúle: https://github.com/Oire (tests)
	//! author : Oerd Cukalla : https://github.com/oerd (fixes)

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var sq = moment.defineLocale('sq', {
	        months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'),
	        monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'),
	        weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'),
	        weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'),
	        weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'),
	        weekdaysParseExact : true,
	        meridiemParse: /PD|MD/,
	        isPM: function (input) {
	            return input.charAt(0) === 'M';
	        },
	        meridiem : function (hours, minutes, isLower) {
	            return hours < 12 ? 'PD' : 'MD';
	        },
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[Sot në] LT',
	            nextDay : '[Nesër në] LT',
	            nextWeek : 'dddd [në] LT',
	            lastDay : '[Dje në] LT',
	            lastWeek : 'dddd [e kaluar në] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'në %s',
	            past : '%s më parë',
	            s : 'disa sekonda',
	            m : 'një minutë',
	            mm : '%d minuta',
	            h : 'një orë',
	            hh : '%d orë',
	            d : 'një ditë',
	            dd : '%d ditë',
	            M : 'një muaj',
	            MM : '%d muaj',
	            y : 'një vit',
	            yy : '%d vite'
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return sq;

	}));

/***/ },
/* 297 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Serbian-latin (sr)
	//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var translator = {
	        words: { //Different grammatical cases
	            m: ['jedan minut', 'jedne minute'],
	            mm: ['minut', 'minute', 'minuta'],
	            h: ['jedan sat', 'jednog sata'],
	            hh: ['sat', 'sata', 'sati'],
	            dd: ['dan', 'dana', 'dana'],
	            MM: ['mesec', 'meseca', 'meseci'],
	            yy: ['godina', 'godine', 'godina']
	        },
	        correctGrammaticalCase: function (number, wordKey) {
	            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
	        },
	        translate: function (number, withoutSuffix, key) {
	            var wordKey = translator.words[key];
	            if (key.length === 1) {
	                return withoutSuffix ? wordKey[0] : wordKey[1];
	            } else {
	                return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
	            }
	        }
	    };

	    var sr = moment.defineLocale('sr', {
	        months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
	        monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
	        monthsParseExact: true,
	        weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'),
	        weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'),
	        weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat: {
	            LT: 'H:mm',
	            LTS : 'H:mm:ss',
	            L: 'DD. MM. YYYY',
	            LL: 'D. MMMM YYYY',
	            LLL: 'D. MMMM YYYY H:mm',
	            LLLL: 'dddd, D. MMMM YYYY H:mm'
	        },
	        calendar: {
	            sameDay: '[danas u] LT',
	            nextDay: '[sutra u] LT',
	            nextWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[u] [nedelju] [u] LT';
	                case 3:
	                    return '[u] [sredu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	                }
	            },
	            lastDay  : '[juče u] LT',
	            lastWeek : function () {
	                var lastWeekDays = [
	                    '[prošle] [nedelje] [u] LT',
	                    '[prošlog] [ponedeljka] [u] LT',
	                    '[prošlog] [utorka] [u] LT',
	                    '[prošle] [srede] [u] LT',
	                    '[prošlog] [četvrtka] [u] LT',
	                    '[prošlog] [petka] [u] LT',
	                    '[prošle] [subote] [u] LT'
	                ];
	                return lastWeekDays[this.day()];
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'za %s',
	            past   : 'pre %s',
	            s      : 'nekoliko sekundi',
	            m      : translator.translate,
	            mm     : translator.translate,
	            h      : translator.translate,
	            hh     : translator.translate,
	            d      : 'dan',
	            dd     : translator.translate,
	            M      : 'mesec',
	            MM     : translator.translate,
	            y      : 'godinu',
	            yy     : translator.translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return sr;

	}));

/***/ },
/* 298 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Serbian-cyrillic (sr-cyrl)
	//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var translator = {
	        words: { //Different grammatical cases
	            m: ['један минут', 'једне минуте'],
	            mm: ['минут', 'минуте', 'минута'],
	            h: ['један сат', 'једног сата'],
	            hh: ['сат', 'сата', 'сати'],
	            dd: ['дан', 'дана', 'дана'],
	            MM: ['месец', 'месеца', 'месеци'],
	            yy: ['година', 'године', 'година']
	        },
	        correctGrammaticalCase: function (number, wordKey) {
	            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
	        },
	        translate: function (number, withoutSuffix, key) {
	            var wordKey = translator.words[key];
	            if (key.length === 1) {
	                return withoutSuffix ? wordKey[0] : wordKey[1];
	            } else {
	                return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
	            }
	        }
	    };

	    var sr_cyrl = moment.defineLocale('sr-cyrl', {
	        months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'),
	        monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'),
	        monthsParseExact: true,
	        weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'),
	        weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'),
	        weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat: {
	            LT: 'H:mm',
	            LTS : 'H:mm:ss',
	            L: 'DD. MM. YYYY',
	            LL: 'D. MMMM YYYY',
	            LLL: 'D. MMMM YYYY H:mm',
	            LLLL: 'dddd, D. MMMM YYYY H:mm'
	        },
	        calendar: {
	            sameDay: '[данас у] LT',
	            nextDay: '[сутра у] LT',
	            nextWeek: function () {
	                switch (this.day()) {
	                case 0:
	                    return '[у] [недељу] [у] LT';
	                case 3:
	                    return '[у] [среду] [у] LT';
	                case 6:
	                    return '[у] [суботу] [у] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[у] dddd [у] LT';
	                }
	            },
	            lastDay  : '[јуче у] LT',
	            lastWeek : function () {
	                var lastWeekDays = [
	                    '[прошле] [недеље] [у] LT',
	                    '[прошлог] [понедељка] [у] LT',
	                    '[прошлог] [уторка] [у] LT',
	                    '[прошле] [среде] [у] LT',
	                    '[прошлог] [четвртка] [у] LT',
	                    '[прошлог] [петка] [у] LT',
	                    '[прошле] [суботе] [у] LT'
	                ];
	                return lastWeekDays[this.day()];
	            },
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'за %s',
	            past   : 'пре %s',
	            s      : 'неколико секунди',
	            m      : translator.translate,
	            mm     : translator.translate,
	            h      : translator.translate,
	            hh     : translator.translate,
	            d      : 'дан',
	            dd     : translator.translate,
	            M      : 'месец',
	            MM     : translator.translate,
	            y      : 'годину',
	            yy     : translator.translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return sr_cyrl;

	}));

/***/ },
/* 299 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : siSwati (ss)
	//! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';



	    var ss = moment.defineLocale('ss', {
	        months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'),
	        monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'),
	        weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'),
	        weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'),
	        weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'h:mm A',
	            LTS : 'h:mm:ss A',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY h:mm A',
	            LLLL : 'dddd, D MMMM YYYY h:mm A'
	        },
	        calendar : {
	            sameDay : '[Namuhla nga] LT',
	            nextDay : '[Kusasa nga] LT',
	            nextWeek : 'dddd [nga] LT',
	            lastDay : '[Itolo nga] LT',
	            lastWeek : 'dddd [leliphelile] [nga] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'nga %s',
	            past : 'wenteka nga %s',
	            s : 'emizuzwana lomcane',
	            m : 'umzuzu',
	            mm : '%d emizuzu',
	            h : 'lihora',
	            hh : '%d emahora',
	            d : 'lilanga',
	            dd : '%d emalanga',
	            M : 'inyanga',
	            MM : '%d tinyanga',
	            y : 'umnyaka',
	            yy : '%d iminyaka'
	        },
	        meridiemParse: /ekuseni|emini|entsambama|ebusuku/,
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 11) {
	                return 'ekuseni';
	            } else if (hours < 15) {
	                return 'emini';
	            } else if (hours < 19) {
	                return 'entsambama';
	            } else {
	                return 'ebusuku';
	            }
	        },
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'ekuseni') {
	                return hour;
	            } else if (meridiem === 'emini') {
	                return hour >= 11 ? hour : hour + 12;
	            } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') {
	                if (hour === 0) {
	                    return 0;
	                }
	                return hour + 12;
	            }
	        },
	        ordinalParse: /\d{1,2}/,
	        ordinal : '%d',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return ss;

	}));

/***/ },
/* 300 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : swedish (sv)
	//! author : Jens Alm : https://github.com/ulmus

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var sv = moment.defineLocale('sv', {
	        months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'),
	        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
	        weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
	        weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
	        weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'YYYY-MM-DD',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY [kl.] HH:mm',
	            LLLL : 'dddd D MMMM YYYY [kl.] HH:mm',
	            lll : 'D MMM YYYY HH:mm',
	            llll : 'ddd D MMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Idag] LT',
	            nextDay: '[Imorgon] LT',
	            lastDay: '[Igår] LT',
	            nextWeek: '[På] dddd LT',
	            lastWeek: '[I] dddd[s] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'om %s',
	            past : 'för %s sedan',
	            s : 'några sekunder',
	            m : 'en minut',
	            mm : '%d minuter',
	            h : 'en timme',
	            hh : '%d timmar',
	            d : 'en dag',
	            dd : '%d dagar',
	            M : 'en månad',
	            MM : '%d månader',
	            y : 'ett år',
	            yy : '%d år'
	        },
	        ordinalParse: /\d{1,2}(e|a)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (~~(number % 100 / 10) === 1) ? 'e' :
	                (b === 1) ? 'a' :
	                (b === 2) ? 'a' :
	                (b === 3) ? 'e' : 'e';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return sv;

	}));

/***/ },
/* 301 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : swahili (sw)
	//! author : Fahad Kassim : https://github.com/fadsel

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var sw = moment.defineLocale('sw', {
	        months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'),
	        monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'),
	        weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'),
	        weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'),
	        weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[leo saa] LT',
	            nextDay : '[kesho saa] LT',
	            nextWeek : '[wiki ijayo] dddd [saat] LT',
	            lastDay : '[jana] LT',
	            lastWeek : '[wiki iliyopita] dddd [saat] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s baadaye',
	            past : 'tokea %s',
	            s : 'hivi punde',
	            m : 'dakika moja',
	            mm : 'dakika %d',
	            h : 'saa limoja',
	            hh : 'masaa %d',
	            d : 'siku moja',
	            dd : 'masiku %d',
	            M : 'mwezi mmoja',
	            MM : 'miezi %d',
	            y : 'mwaka mmoja',
	            yy : 'miaka %d'
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return sw;

	}));

/***/ },
/* 302 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : tamil (ta)
	//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var symbolMap = {
	        '1': '௧',
	        '2': '௨',
	        '3': '௩',
	        '4': '௪',
	        '5': '௫',
	        '6': '௬',
	        '7': '௭',
	        '8': '௮',
	        '9': '௯',
	        '0': '௦'
	    }, numberMap = {
	        '௧': '1',
	        '௨': '2',
	        '௩': '3',
	        '௪': '4',
	        '௫': '5',
	        '௬': '6',
	        '௭': '7',
	        '௮': '8',
	        '௯': '9',
	        '௦': '0'
	    };

	    var ta = moment.defineLocale('ta', {
	        months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
	        monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
	        weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'),
	        weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'),
	        weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, HH:mm',
	            LLLL : 'dddd, D MMMM YYYY, HH:mm'
	        },
	        calendar : {
	            sameDay : '[இன்று] LT',
	            nextDay : '[நாளை] LT',
	            nextWeek : 'dddd, LT',
	            lastDay : '[நேற்று] LT',
	            lastWeek : '[கடந்த வாரம்] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s இல்',
	            past : '%s முன்',
	            s : 'ஒரு சில விநாடிகள்',
	            m : 'ஒரு நிமிடம்',
	            mm : '%d நிமிடங்கள்',
	            h : 'ஒரு மணி நேரம்',
	            hh : '%d மணி நேரம்',
	            d : 'ஒரு நாள்',
	            dd : '%d நாட்கள்',
	            M : 'ஒரு மாதம்',
	            MM : '%d மாதங்கள்',
	            y : 'ஒரு வருடம்',
	            yy : '%d ஆண்டுகள்'
	        },
	        ordinalParse: /\d{1,2}வது/,
	        ordinal : function (number) {
	            return number + 'வது';
	        },
	        preparse: function (string) {
	            return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
	                return numberMap[match];
	            });
	        },
	        postformat: function (string) {
	            return string.replace(/\d/g, function (match) {
	                return symbolMap[match];
	            });
	        },
	        // refer http://ta.wikipedia.org/s/1er1
	        meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 2) {
	                return ' யாமம்';
	            } else if (hour < 6) {
	                return ' வைகறை';  // வைகறை
	            } else if (hour < 10) {
	                return ' காலை'; // காலை
	            } else if (hour < 14) {
	                return ' நண்பகல்'; // நண்பகல்
	            } else if (hour < 18) {
	                return ' எற்பாடு'; // எற்பாடு
	            } else if (hour < 22) {
	                return ' மாலை'; // மாலை
	            } else {
	                return ' யாமம்';
	            }
	        },
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'யாமம்') {
	                return hour < 2 ? hour : hour + 12;
	            } else if (meridiem === 'வைகறை' || meridiem === 'காலை') {
	                return hour;
	            } else if (meridiem === 'நண்பகல்') {
	                return hour >= 10 ? hour : hour + 12;
	            } else {
	                return hour + 12;
	            }
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return ta;

	}));

/***/ },
/* 303 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : telugu (te)
	//! author : Krishna Chaitanya Thota : https://github.com/kcthota

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var te = moment.defineLocale('te', {
	        months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'),
	        monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'),
	        weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'),
	        weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'),
	        longDateFormat : {
	            LT : 'A h:mm',
	            LTS : 'A h:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY, A h:mm',
	            LLLL : 'dddd, D MMMM YYYY, A h:mm'
	        },
	        calendar : {
	            sameDay : '[నేడు] LT',
	            nextDay : '[రేపు] LT',
	            nextWeek : 'dddd, LT',
	            lastDay : '[నిన్న] LT',
	            lastWeek : '[గత] dddd, LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s లో',
	            past : '%s క్రితం',
	            s : 'కొన్ని క్షణాలు',
	            m : 'ఒక నిమిషం',
	            mm : '%d నిమిషాలు',
	            h : 'ఒక గంట',
	            hh : '%d గంటలు',
	            d : 'ఒక రోజు',
	            dd : '%d రోజులు',
	            M : 'ఒక నెల',
	            MM : '%d నెలలు',
	            y : 'ఒక సంవత్సరం',
	            yy : '%d సంవత్సరాలు'
	        },
	        ordinalParse : /\d{1,2}వ/,
	        ordinal : '%dవ',
	        meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === 'రాత్రి') {
	                return hour < 4 ? hour : hour + 12;
	            } else if (meridiem === 'ఉదయం') {
	                return hour;
	            } else if (meridiem === 'మధ్యాహ్నం') {
	                return hour >= 10 ? hour : hour + 12;
	            } else if (meridiem === 'సాయంత్రం') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'రాత్రి';
	            } else if (hour < 10) {
	                return 'ఉదయం';
	            } else if (hour < 17) {
	                return 'మధ్యాహ్నం';
	            } else if (hour < 20) {
	                return 'సాయంత్రం';
	            } else {
	                return 'రాత్రి';
	            }
	        },
	        week : {
	            dow : 0, // Sunday is the first day of the week.
	            doy : 6  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return te;

	}));

/***/ },
/* 304 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : thai (th)
	//! author : Kridsada Thanabulpong : https://github.com/sirn

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var th = moment.defineLocale('th', {
	        months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'),
	        monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'),
	        monthsParseExact: true,
	        weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
	        weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference
	        weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'H นาฬิกา m นาที',
	            LTS : 'H นาฬิกา m นาที s วินาที',
	            L : 'YYYY/MM/DD',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY เวลา H นาฬิกา m นาที',
	            LLLL : 'วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที'
	        },
	        meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/,
	        isPM: function (input) {
	            return input === 'หลังเที่ยง';
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 12) {
	                return 'ก่อนเที่ยง';
	            } else {
	                return 'หลังเที่ยง';
	            }
	        },
	        calendar : {
	            sameDay : '[วันนี้ เวลา] LT',
	            nextDay : '[พรุ่งนี้ เวลา] LT',
	            nextWeek : 'dddd[หน้า เวลา] LT',
	            lastDay : '[เมื่อวานนี้ เวลา] LT',
	            lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'อีก %s',
	            past : '%sที่แล้ว',
	            s : 'ไม่กี่วินาที',
	            m : '1 นาที',
	            mm : '%d นาที',
	            h : '1 ชั่วโมง',
	            hh : '%d ชั่วโมง',
	            d : '1 วัน',
	            dd : '%d วัน',
	            M : '1 เดือน',
	            MM : '%d เดือน',
	            y : '1 ปี',
	            yy : '%d ปี'
	        }
	    });

	    return th;

	}));

/***/ },
/* 305 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Tagalog/Filipino (tl-ph)
	//! author : Dan Hagman

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var tl_ph = moment.defineLocale('tl-ph', {
	        months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'),
	        monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
	        weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'),
	        weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
	        weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'MM/D/YYYY',
	            LL : 'MMMM D, YYYY',
	            LLL : 'MMMM D, YYYY HH:mm',
	            LLLL : 'dddd, MMMM DD, YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Ngayon sa] LT',
	            nextDay: '[Bukas sa] LT',
	            nextWeek: 'dddd [sa] LT',
	            lastDay: '[Kahapon sa] LT',
	            lastWeek: 'dddd [huling linggo] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'sa loob ng %s',
	            past : '%s ang nakalipas',
	            s : 'ilang segundo',
	            m : 'isang minuto',
	            mm : '%d minuto',
	            h : 'isang oras',
	            hh : '%d oras',
	            d : 'isang araw',
	            dd : '%d araw',
	            M : 'isang buwan',
	            MM : '%d buwan',
	            y : 'isang taon',
	            yy : '%d taon'
	        },
	        ordinalParse: /\d{1,2}/,
	        ordinal : function (number) {
	            return number;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return tl_ph;

	}));

/***/ },
/* 306 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Klingon (tlh)
	//! author : Dominika Kruk : https://github.com/amaranthrose

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_');

	    function translateFuture(output) {
	        var time = output;
	        time = (output.indexOf('jaj') !== -1) ?
	    	time.slice(0, -3) + 'leS' :
	    	(output.indexOf('jar') !== -1) ?
	    	time.slice(0, -3) + 'waQ' :
	    	(output.indexOf('DIS') !== -1) ?
	    	time.slice(0, -3) + 'nem' :
	    	time + ' pIq';
	        return time;
	    }

	    function translatePast(output) {
	        var time = output;
	        time = (output.indexOf('jaj') !== -1) ?
	    	time.slice(0, -3) + 'Hu’' :
	    	(output.indexOf('jar') !== -1) ?
	    	time.slice(0, -3) + 'wen' :
	    	(output.indexOf('DIS') !== -1) ?
	    	time.slice(0, -3) + 'ben' :
	    	time + ' ret';
	        return time;
	    }

	    function translate(number, withoutSuffix, string, isFuture) {
	        var numberNoun = numberAsNoun(number);
	        switch (string) {
	            case 'mm':
	                return numberNoun + ' tup';
	            case 'hh':
	                return numberNoun + ' rep';
	            case 'dd':
	                return numberNoun + ' jaj';
	            case 'MM':
	                return numberNoun + ' jar';
	            case 'yy':
	                return numberNoun + ' DIS';
	        }
	    }

	    function numberAsNoun(number) {
	        var hundred = Math.floor((number % 1000) / 100),
	    	ten = Math.floor((number % 100) / 10),
	    	one = number % 10,
	    	word = '';
	        if (hundred > 0) {
	            word += numbersNouns[hundred] + 'vatlh';
	        }
	        if (ten > 0) {
	            word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH';
	        }
	        if (one > 0) {
	            word += ((word !== '') ? ' ' : '') + numbersNouns[one];
	        }
	        return (word === '') ? 'pagh' : word;
	    }

	    var tlh = moment.defineLocale('tlh', {
	        months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'),
	        monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
	        weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
	        weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[DaHjaj] LT',
	            nextDay: '[wa’leS] LT',
	            nextWeek: 'LLL',
	            lastDay: '[wa’Hu’] LT',
	            lastWeek: 'LLL',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : translateFuture,
	            past : translatePast,
	            s : 'puS lup',
	            m : 'wa’ tup',
	            mm : translate,
	            h : 'wa’ rep',
	            hh : translate,
	            d : 'wa’ jaj',
	            dd : translate,
	            M : 'wa’ jar',
	            MM : translate,
	            y : 'wa’ DIS',
	            yy : translate
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return tlh;

	}));

/***/ },
/* 307 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : turkish (tr)
	//! authors : Erhan Gundogan : https://github.com/erhangundogan,
	//!           Burak Yiğit Kaya: https://github.com/BYK

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var suffixes = {
	        1: '\'inci',
	        5: '\'inci',
	        8: '\'inci',
	        70: '\'inci',
	        80: '\'inci',
	        2: '\'nci',
	        7: '\'nci',
	        20: '\'nci',
	        50: '\'nci',
	        3: '\'üncü',
	        4: '\'üncü',
	        100: '\'üncü',
	        6: '\'ncı',
	        9: '\'uncu',
	        10: '\'uncu',
	        30: '\'uncu',
	        60: '\'ıncı',
	        90: '\'ıncı'
	    };

	    var tr = moment.defineLocale('tr', {
	        months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
	        monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
	        weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
	        weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
	        weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[bugün saat] LT',
	            nextDay : '[yarın saat] LT',
	            nextWeek : '[haftaya] dddd [saat] LT',
	            lastDay : '[dün] LT',
	            lastWeek : '[geçen hafta] dddd [saat] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : '%s sonra',
	            past : '%s önce',
	            s : 'birkaç saniye',
	            m : 'bir dakika',
	            mm : '%d dakika',
	            h : 'bir saat',
	            hh : '%d saat',
	            d : 'bir gün',
	            dd : '%d gün',
	            M : 'bir ay',
	            MM : '%d ay',
	            y : 'bir yıl',
	            yy : '%d yıl'
	        },
	        ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
	        ordinal : function (number) {
	            if (number === 0) {  // special case for zero
	                return number + '\'ıncı';
	            }
	            var a = number % 10,
	                b = number % 100 - a,
	                c = number >= 100 ? 100 : null;
	            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return tr;

	}));

/***/ },
/* 308 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : talossan (tzl)
	//! author : Robin van der Vliet : https://github.com/robin0van0der0v with the help of Iustì Canun

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';



	    // After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals.
	    // This is currently too difficult (maybe even impossible) to add.
	    var tzl = moment.defineLocale('tzl', {
	        months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'),
	        monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'),
	        weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'),
	        weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'),
	        weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'),
	        longDateFormat : {
	            LT : 'HH.mm',
	            LTS : 'HH.mm.ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D. MMMM [dallas] YYYY',
	            LLL : 'D. MMMM [dallas] YYYY HH.mm',
	            LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm'
	        },
	        meridiemParse: /d\'o|d\'a/i,
	        isPM : function (input) {
	            return 'd\'o' === input.toLowerCase();
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours > 11) {
	                return isLower ? 'd\'o' : 'D\'O';
	            } else {
	                return isLower ? 'd\'a' : 'D\'A';
	            }
	        },
	        calendar : {
	            sameDay : '[oxhi à] LT',
	            nextDay : '[demà à] LT',
	            nextWeek : 'dddd [à] LT',
	            lastDay : '[ieiri à] LT',
	            lastWeek : '[sür el] dddd [lasteu à] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'osprei %s',
	            past : 'ja%s',
	            s : processRelativeTime,
	            m : processRelativeTime,
	            mm : processRelativeTime,
	            h : processRelativeTime,
	            hh : processRelativeTime,
	            d : processRelativeTime,
	            dd : processRelativeTime,
	            M : processRelativeTime,
	            MM : processRelativeTime,
	            y : processRelativeTime,
	            yy : processRelativeTime
	        },
	        ordinalParse: /\d{1,2}\./,
	        ordinal : '%d.',
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    function processRelativeTime(number, withoutSuffix, key, isFuture) {
	        var format = {
	            's': ['viensas secunds', '\'iensas secunds'],
	            'm': ['\'n míut', '\'iens míut'],
	            'mm': [number + ' míuts', '' + number + ' míuts'],
	            'h': ['\'n þora', '\'iensa þora'],
	            'hh': [number + ' þoras', '' + number + ' þoras'],
	            'd': ['\'n ziua', '\'iensa ziua'],
	            'dd': [number + ' ziuas', '' + number + ' ziuas'],
	            'M': ['\'n mes', '\'iens mes'],
	            'MM': [number + ' mesen', '' + number + ' mesen'],
	            'y': ['\'n ar', '\'iens ar'],
	            'yy': [number + ' ars', '' + number + ' ars']
	        };
	        return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]);
	    }

	    return tzl;

	}));

/***/ },
/* 309 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Morocco Central Atlas Tamaziɣt (tzm)
	//! author : Abdel Said : https://github.com/abdelsaid

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var tzm = moment.defineLocale('tzm', {
	        months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
	        monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
	        weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
	        weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
	        weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS: 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[ⴰⵙⴷⵅ ⴴ] LT',
	            nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
	            nextWeek: 'dddd [ⴴ] LT',
	            lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
	            lastWeek: 'dddd [ⴴ] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s',
	            past : 'ⵢⴰⵏ %s',
	            s : 'ⵉⵎⵉⴽ',
	            m : 'ⵎⵉⵏⵓⴺ',
	            mm : '%d ⵎⵉⵏⵓⴺ',
	            h : 'ⵙⴰⵄⴰ',
	            hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ',
	            d : 'ⴰⵙⵙ',
	            dd : '%d oⵙⵙⴰⵏ',
	            M : 'ⴰⵢoⵓⵔ',
	            MM : '%d ⵉⵢⵢⵉⵔⵏ',
	            y : 'ⴰⵙⴳⴰⵙ',
	            yy : '%d ⵉⵙⴳⴰⵙⵏ'
	        },
	        week : {
	            dow : 6, // Saturday is the first day of the week.
	            doy : 12  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return tzm;

	}));

/***/ },
/* 310 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn)
	//! author : Abdel Said : https://github.com/abdelsaid

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var tzm_latn = moment.defineLocale('tzm-latn', {
	        months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
	        monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
	        weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
	        weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
	        weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[asdkh g] LT',
	            nextDay: '[aska g] LT',
	            nextWeek: 'dddd [g] LT',
	            lastDay: '[assant g] LT',
	            lastWeek: 'dddd [g] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'dadkh s yan %s',
	            past : 'yan %s',
	            s : 'imik',
	            m : 'minuḍ',
	            mm : '%d minuḍ',
	            h : 'saɛa',
	            hh : '%d tassaɛin',
	            d : 'ass',
	            dd : '%d ossan',
	            M : 'ayowr',
	            MM : '%d iyyirn',
	            y : 'asgas',
	            yy : '%d isgasn'
	        },
	        week : {
	            dow : 6, // Saturday is the first day of the week.
	            doy : 12  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return tzm_latn;

	}));

/***/ },
/* 311 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : ukrainian (uk)
	//! author : zemlanin : https://github.com/zemlanin
	//! Author : Menelion Elensúle : https://github.com/Oire

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    function plural(word, num) {
	        var forms = word.split('_');
	        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
	    }
	    function relativeTimeWithPlural(number, withoutSuffix, key) {
	        var format = {
	            'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин',
	            'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин',
	            'dd': 'день_дні_днів',
	            'MM': 'місяць_місяці_місяців',
	            'yy': 'рік_роки_років'
	        };
	        if (key === 'm') {
	            return withoutSuffix ? 'хвилина' : 'хвилину';
	        }
	        else if (key === 'h') {
	            return withoutSuffix ? 'година' : 'годину';
	        }
	        else {
	            return number + ' ' + plural(format[key], +number);
	        }
	    }
	    function weekdaysCaseReplace(m, format) {
	        var weekdays = {
	            'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
	            'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
	            'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
	        },
	        nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
	            'accusative' :
	            ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
	                'genitive' :
	                'nominative');
	        return weekdays[nounCase][m.day()];
	    }
	    function processHoursFunction(str) {
	        return function () {
	            return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
	        };
	    }

	    var uk = moment.defineLocale('uk', {
	        months : {
	            'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'),
	            'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_')
	        },
	        monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'),
	        weekdays : weekdaysCaseReplace,
	        weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
	        weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD.MM.YYYY',
	            LL : 'D MMMM YYYY р.',
	            LLL : 'D MMMM YYYY р., HH:mm',
	            LLLL : 'dddd, D MMMM YYYY р., HH:mm'
	        },
	        calendar : {
	            sameDay: processHoursFunction('[Сьогодні '),
	            nextDay: processHoursFunction('[Завтра '),
	            lastDay: processHoursFunction('[Вчора '),
	            nextWeek: processHoursFunction('[У] dddd ['),
	            lastWeek: function () {
	                switch (this.day()) {
	                case 0:
	                case 3:
	                case 5:
	                case 6:
	                    return processHoursFunction('[Минулої] dddd [').call(this);
	                case 1:
	                case 2:
	                case 4:
	                    return processHoursFunction('[Минулого] dddd [').call(this);
	                }
	            },
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : 'за %s',
	            past : '%s тому',
	            s : 'декілька секунд',
	            m : relativeTimeWithPlural,
	            mm : relativeTimeWithPlural,
	            h : 'годину',
	            hh : relativeTimeWithPlural,
	            d : 'день',
	            dd : relativeTimeWithPlural,
	            M : 'місяць',
	            MM : relativeTimeWithPlural,
	            y : 'рік',
	            yy : relativeTimeWithPlural
	        },
	        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
	        meridiemParse: /ночі|ранку|дня|вечора/,
	        isPM: function (input) {
	            return /^(дня|вечора)$/.test(input);
	        },
	        meridiem : function (hour, minute, isLower) {
	            if (hour < 4) {
	                return 'ночі';
	            } else if (hour < 12) {
	                return 'ранку';
	            } else if (hour < 17) {
	                return 'дня';
	            } else {
	                return 'вечора';
	            }
	        },
	        ordinalParse: /\d{1,2}-(й|го)/,
	        ordinal: function (number, period) {
	            switch (period) {
	            case 'M':
	            case 'd':
	            case 'DDD':
	            case 'w':
	            case 'W':
	                return number + '-й';
	            case 'D':
	                return number + '-го';
	            default:
	                return number;
	            }
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 1st is the first week of the year.
	        }
	    });

	    return uk;

	}));

/***/ },
/* 312 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : uzbek (uz)
	//! author : Sardor Muminov : https://github.com/muminoff

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var uz = moment.defineLocale('uz', {
	        months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'),
	        monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
	        weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
	        weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'),
	        weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'D MMMM YYYY, dddd HH:mm'
	        },
	        calendar : {
	            sameDay : '[Бугун соат] LT [да]',
	            nextDay : '[Эртага] LT [да]',
	            nextWeek : 'dddd [куни соат] LT [да]',
	            lastDay : '[Кеча соат] LT [да]',
	            lastWeek : '[Утган] dddd [куни соат] LT [да]',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'Якин %s ичида',
	            past : 'Бир неча %s олдин',
	            s : 'фурсат',
	            m : 'бир дакика',
	            mm : '%d дакика',
	            h : 'бир соат',
	            hh : '%d соат',
	            d : 'бир кун',
	            dd : '%d кун',
	            M : 'бир ой',
	            MM : '%d ой',
	            y : 'бир йил',
	            yy : '%d йил'
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 7  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return uz;

	}));

/***/ },
/* 313 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : vietnamese (vi)
	//! author : Bang Nguyen : https://github.com/bangnk

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var vi = moment.defineLocale('vi', {
	        months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'),
	        monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'),
	        weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
	        weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
	        weekdaysParseExact : true,
	        meridiemParse: /sa|ch/i,
	        isPM : function (input) {
	            return /^ch$/i.test(input);
	        },
	        meridiem : function (hours, minutes, isLower) {
	            if (hours < 12) {
	                return isLower ? 'sa' : 'SA';
	            } else {
	                return isLower ? 'ch' : 'CH';
	            }
	        },
	        longDateFormat : {
	            LT : 'HH:mm',
	            LTS : 'HH:mm:ss',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM [năm] YYYY',
	            LLL : 'D MMMM [năm] YYYY HH:mm',
	            LLLL : 'dddd, D MMMM [năm] YYYY HH:mm',
	            l : 'DD/M/YYYY',
	            ll : 'D MMM YYYY',
	            lll : 'D MMM YYYY HH:mm',
	            llll : 'ddd, D MMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay: '[Hôm nay lúc] LT',
	            nextDay: '[Ngày mai lúc] LT',
	            nextWeek: 'dddd [tuần tới lúc] LT',
	            lastDay: '[Hôm qua lúc] LT',
	            lastWeek: 'dddd [tuần rồi lúc] LT',
	            sameElse: 'L'
	        },
	        relativeTime : {
	            future : '%s tới',
	            past : '%s trước',
	            s : 'vài giây',
	            m : 'một phút',
	            mm : '%d phút',
	            h : 'một giờ',
	            hh : '%d giờ',
	            d : 'một ngày',
	            dd : '%d ngày',
	            M : 'một tháng',
	            MM : '%d tháng',
	            y : 'một năm',
	            yy : '%d năm'
	        },
	        ordinalParse: /\d{1,2}/,
	        ordinal : function (number) {
	            return number;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return vi;

	}));

/***/ },
/* 314 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : pseudo (x-pseudo)
	//! author : Andrew Hood : https://github.com/andrewhood125

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var x_pseudo = moment.defineLocale('x-pseudo', {
	        months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'),
	        monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'),
	        monthsParseExact : true,
	        weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'),
	        weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'),
	        weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'),
	        weekdaysParseExact : true,
	        longDateFormat : {
	            LT : 'HH:mm',
	            L : 'DD/MM/YYYY',
	            LL : 'D MMMM YYYY',
	            LLL : 'D MMMM YYYY HH:mm',
	            LLLL : 'dddd, D MMMM YYYY HH:mm'
	        },
	        calendar : {
	            sameDay : '[T~ódá~ý át] LT',
	            nextDay : '[T~ómó~rró~w át] LT',
	            nextWeek : 'dddd [át] LT',
	            lastDay : '[Ý~ést~érdá~ý át] LT',
	            lastWeek : '[L~ást] dddd [át] LT',
	            sameElse : 'L'
	        },
	        relativeTime : {
	            future : 'í~ñ %s',
	            past : '%s á~gó',
	            s : 'á ~féw ~sécó~ñds',
	            m : 'á ~míñ~úté',
	            mm : '%d m~íñú~tés',
	            h : 'á~ñ hó~úr',
	            hh : '%d h~óúrs',
	            d : 'á ~dáý',
	            dd : '%d d~áýs',
	            M : 'á ~móñ~th',
	            MM : '%d m~óñt~hs',
	            y : 'á ~ýéár',
	            yy : '%d ý~éárs'
	        },
	        ordinalParse: /\d{1,2}(th|st|nd|rd)/,
	        ordinal : function (number) {
	            var b = number % 10,
	                output = (~~(number % 100 / 10) === 1) ? 'th' :
	                (b === 1) ? 'st' :
	                (b === 2) ? 'nd' :
	                (b === 3) ? 'rd' : 'th';
	            return number + output;
	        },
	        week : {
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return x_pseudo;

	}));

/***/ },
/* 315 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : chinese (zh-cn)
	//! author : suupic : https://github.com/suupic
	//! author : Zeno Zeng : https://github.com/zenozeng

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var zh_cn = moment.defineLocale('zh-cn', {
	        months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
	        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	        weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
	        weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'),
	        weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
	        longDateFormat : {
	            LT : 'Ah点mm分',
	            LTS : 'Ah点m分s秒',
	            L : 'YYYY-MM-DD',
	            LL : 'YYYY年MMMD日',
	            LLL : 'YYYY年MMMD日Ah点mm分',
	            LLLL : 'YYYY年MMMD日ddddAh点mm分',
	            l : 'YYYY-MM-DD',
	            ll : 'YYYY年MMMD日',
	            lll : 'YYYY年MMMD日Ah点mm分',
	            llll : 'YYYY年MMMD日ddddAh点mm分'
	        },
	        meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
	        meridiemHour: function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === '凌晨' || meridiem === '早上' ||
	                    meridiem === '上午') {
	                return hour;
	            } else if (meridiem === '下午' || meridiem === '晚上') {
	                return hour + 12;
	            } else {
	                // '中午'
	                return hour >= 11 ? hour : hour + 12;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            var hm = hour * 100 + minute;
	            if (hm < 600) {
	                return '凌晨';
	            } else if (hm < 900) {
	                return '早上';
	            } else if (hm < 1130) {
	                return '上午';
	            } else if (hm < 1230) {
	                return '中午';
	            } else if (hm < 1800) {
	                return '下午';
	            } else {
	                return '晚上';
	            }
	        },
	        calendar : {
	            sameDay : function () {
	                return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT';
	            },
	            nextDay : function () {
	                return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT';
	            },
	            lastDay : function () {
	                return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT';
	            },
	            nextWeek : function () {
	                var startOfWeek, prefix;
	                startOfWeek = moment().startOf('week');
	                prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]';
	                return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
	            },
	            lastWeek : function () {
	                var startOfWeek, prefix;
	                startOfWeek = moment().startOf('week');
	                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
	                return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
	            },
	            sameElse : 'LL'
	        },
	        ordinalParse: /\d{1,2}(日|月|周)/,
	        ordinal : function (number, period) {
	            switch (period) {
	            case 'd':
	            case 'D':
	            case 'DDD':
	                return number + '日';
	            case 'M':
	                return number + '月';
	            case 'w':
	            case 'W':
	                return number + '周';
	            default:
	                return number;
	            }
	        },
	        relativeTime : {
	            future : '%s内',
	            past : '%s前',
	            s : '几秒',
	            m : '1 分钟',
	            mm : '%d 分钟',
	            h : '1 小时',
	            hh : '%d 小时',
	            d : '1 天',
	            dd : '%d 天',
	            M : '1 个月',
	            MM : '%d 个月',
	            y : '1 年',
	            yy : '%d 年'
	        },
	        week : {
	            // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
	            dow : 1, // Monday is the first day of the week.
	            doy : 4  // The week that contains Jan 4th is the first week of the year.
	        }
	    });

	    return zh_cn;

	}));

/***/ },
/* 316 */
/***/ function(module, exports, __webpack_require__) {

	//! moment.js locale configuration
	//! locale : traditional chinese (zh-tw)
	//! author : Ben : https://github.com/ben-lin

	;(function (global, factory) {
	    true ? factory(__webpack_require__(215)) :
	   typeof define === 'function' && define.amd ? define(['moment'], factory) :
	   factory(global.moment)
	}(this, function (moment) { 'use strict';


	    var zh_tw = moment.defineLocale('zh-tw', {
	        months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
	        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	        weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
	        weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
	        weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
	        longDateFormat : {
	            LT : 'Ah點mm分',
	            LTS : 'Ah點m分s秒',
	            L : 'YYYY年MMMD日',
	            LL : 'YYYY年MMMD日',
	            LLL : 'YYYY年MMMD日Ah點mm分',
	            LLLL : 'YYYY年MMMD日ddddAh點mm分',
	            l : 'YYYY年MMMD日',
	            ll : 'YYYY年MMMD日',
	            lll : 'YYYY年MMMD日Ah點mm分',
	            llll : 'YYYY年MMMD日ddddAh點mm分'
	        },
	        meridiemParse: /早上|上午|中午|下午|晚上/,
	        meridiemHour : function (hour, meridiem) {
	            if (hour === 12) {
	                hour = 0;
	            }
	            if (meridiem === '早上' || meridiem === '上午') {
	                return hour;
	            } else if (meridiem === '中午') {
	                return hour >= 11 ? hour : hour + 12;
	            } else if (meridiem === '下午' || meridiem === '晚上') {
	                return hour + 12;
	            }
	        },
	        meridiem : function (hour, minute, isLower) {
	            var hm = hour * 100 + minute;
	            if (hm < 900) {
	                return '早上';
	            } else if (hm < 1130) {
	                return '上午';
	            } else if (hm < 1230) {
	                return '中午';
	            } else if (hm < 1800) {
	                return '下午';
	            } else {
	                return '晚上';
	            }
	        },
	        calendar : {
	            sameDay : '[今天]LT',
	            nextDay : '[明天]LT',
	            nextWeek : '[下]ddddLT',
	            lastDay : '[昨天]LT',
	            lastWeek : '[上]ddddLT',
	            sameElse : 'L'
	        },
	        ordinalParse: /\d{1,2}(日|月|週)/,
	        ordinal : function (number, period) {
	            switch (period) {
	            case 'd' :
	            case 'D' :
	            case 'DDD' :
	                return number + '日';
	            case 'M' :
	                return number + '月';
	            case 'w' :
	            case 'W' :
	                return number + '週';
	            default :
	                return number;
	            }
	        },
	        relativeTime : {
	            future : '%s內',
	            past : '%s前',
	            s : '幾秒',
	            m : '1分鐘',
	            mm : '%d分鐘',
	            h : '1小時',
	            hh : '%d小時',
	            d : '1天',
	            dd : '%d天',
	            M : '1個月',
	            MM : '%d個月',
	            y : '1年',
	            yy : '%d年'
	        }
	    });

	    return zh_tw;

	}));

/***/ },
/* 317 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["Highcharts"] = __webpack_require__(318);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 318 */
/***/ function(module, exports) {

	/*
	 Highcharts JS v4.2.4 (2016-04-14)

	 (c) 2009-2016 Torstein Honsi

	 License: www.highcharts.com/license
	*/
	(function(C,Z){typeof module==="object"&&module.exports?module.exports=C.document?Z(C):Z:C.Highcharts=Z(C)})(typeof window!=="undefined"?window:this,function(C){function Z(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw Error(c);C.console&&console.log(c)}function qb(a,b,c){this.options=b;this.elem=a;this.prop=c}function D(){var a,b=arguments,c,d={},e=function(a,b){var c,d;typeof a!=="object"&&(a={});for(d in b)b.hasOwnProperty(d)&&(c=b[d],a[d]=c&&typeof c==="object"&&
	Object.prototype.toString.call(c)!=="[object Array]"&&d!=="renderTo"&&typeof c.nodeType!=="number"?e(a[d]||{},c):b[d]);return a};b[0]===!0&&(d=b[1],b=Array.prototype.slice.call(b,2));c=b.length;for(a=0;a<c;a++)d=e(d,b[a]);return d}function F(a,b){return parseInt(a,b||10)}function xa(a){return typeof a==="string"}function X(a){return a&&typeof a==="object"}function Da(a){return Object.prototype.toString.call(a)==="[object Array]"}function ma(a){return typeof a==="number"}function na(a,b){for(var c=
	a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function r(a){return a!==z&&a!==null}function K(a,b,c){var d,e;if(xa(b))r(c)?a.setAttribute(b,c):a&&a.getAttribute&&(e=a.getAttribute(b));else if(r(b)&&X(b))for(d in b)a.setAttribute(d,b[d]);return e}function ta(a){return Da(a)?a:[a]}function Oa(a,b,c){if(b)return setTimeout(a,b,c);a.call(0,c)}function L(a,b){if(ya&&!ca&&b&&b.opacity!==z)b.filter="alpha(opacity="+b.opacity*100+")";s(a.style,b)}function $(a,b,c,d,e){a=A.createElement(a);b&&s(a,b);e&&
	L(a,{padding:0,border:"none",margin:0});c&&L(a,c);d&&d.appendChild(a);return a}function oa(a,b){var c=function(){};c.prototype=new a;s(c.prototype,b);return c}function Ea(a,b,c){return Array((b||2)+1-String(a).length).join(c||0)+a}function Ya(a){return(Za&&Za(a)||rb||0)*6E4}function Ja(a,b){for(var c="{",d=!1,e,f,g,h,i,k=[];(c=a.indexOf(c))!==-1;){e=a.slice(0,c);if(d){f=e.split(":");g=f.shift().split(".");i=g.length;e=b;for(h=0;h<i;h++)e=e[g[h]];if(f.length)f=f.join(":"),g=/\.([0-9])/,h=S.lang,i=
	void 0,/f$/.test(f)?(i=(i=f.match(g))?i[1]:-1,e!==null&&(e=w.numberFormat(e,i,h.decimalPoint,f.indexOf(",")>-1?h.thousandsSep:""))):e=Pa(f,e)}k.push(e);a=a.slice(c+1);c=(d=!d)?"}":"{"}k.push(a);return k.join("")}function sb(a){return W.pow(10,T(W.log(a)/W.LN10))}function tb(a,b,c,d,e){var f,g=a,c=p(c,1);f=a/c;b||(b=[1,2,2.5,5,10],d===!1&&(c===1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d<b.length;d++)if(g=b[d],e&&g*c>=a||!e&&f<=(b[d]+(b[d+1]||b[d]))/2)break;g*=c;return g}function hb(a,b){var c=a.length,
	d,e;for(e=0;e<c;e++)a[e].safeI=e;a.sort(function(a,c){d=b(a,c);return d===0?a.safeI-c.safeI:d});for(e=0;e<c;e++)delete a[e].safeI}function Qa(a){for(var b=a.length,c=a[0];b--;)a[b]<c&&(c=a[b]);return c}function Fa(a){for(var b=a.length,c=a[0];b--;)a[b]>c&&(c=a[b]);return c}function Ra(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Sa(a){ib||(ib=$(Ka));a&&ib.appendChild(a);ib.innerHTML=""}function da(a,b){return parseFloat(a.toPrecision(b||14))}function Ta(a,
	b){b.renderer.globalAnimation=p(a,b.animation)}function $a(a){return X(a)?D(a):{duration:a?500:0}}function Eb(){var a=S.global,b=a.useUTC,c=b?"getUTC":"get",d=b?"setUTC":"set";pa=a.Date||C.Date;rb=b&&a.timezoneOffset;Za=b&&a.getTimezoneOffset;jb=function(a,c,d,h,i,k){var j;b?(j=pa.UTC.apply(0,arguments),j+=Ya(j)):j=(new pa(a,c,p(d,1),p(h,0),p(i,0),p(k,0))).getTime();return j};ub=c+"Minutes";vb=c+"Hours";wb=c+"Day";Ua=c+"Date";ab=c+"Month";bb=c+"FullYear";Fb=d+"Milliseconds";Gb=d+"Seconds";Hb=d+"Minutes";
	Ib=d+"Hours";kb=d+"Date";xb=d+"Month";yb=d+"FullYear"}function ja(a){if(!(this instanceof ja))return new ja(a);this.init(a)}function P(){}function Va(a,b,c,d){this.axis=a;this.pos=b;this.type=c||"";this.isNew=!0;!c&&!d&&this.addLabel()}function Jb(a,b,c,d,e){var f=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.total=null;this.points={};this.stack=e;this.rightCliff=this.leftCliff=0;this.alignOptions={align:b.align||(f?c?"left":"right":"center"),verticalAlign:b.verticalAlign||
	(f?"middle":c?"bottom":"top"),y:p(b.y,f?4:c?14:-6),x:p(b.x,f?c?-6:6:0)};this.textAlign=b.textAlign||(f?c?"right":"left":"center")}var z,A=C.document,W=Math,B=W.round,T=W.floor,ua=W.ceil,t=W.max,E=W.min,Q=W.abs,U=W.cos,aa=W.sin,qa=W.PI,ha=qa*2/360,za=C.navigator&&C.navigator.userAgent||"",Kb=C.opera,ya=/(msie|trident|edge)/i.test(za)&&!Kb,lb=A&&A.documentMode===8,mb=!ya&&/AppleWebKit/.test(za),La=/Firefox/.test(za),Lb=/(Mobile|Android|Windows Phone)/.test(za),Ga="http://www.w3.org/2000/svg",ca=A&&
	A.createElementNS&&!!A.createElementNS(Ga,"svg").createSVGRect,Pb=La&&parseInt(za.split("Firefox/")[1],10)<4,ia=A&&!ca&&!ya&&!!A.createElement("canvas").getContext,cb,db,Mb={},zb=0,ib,S,Pa,G,Aa=function(){},O=[],eb=0,Ka="div",Qb=/^[0-9]+$/,nb=["plotTop","marginRight","marginBottom","plotLeft"],pa,jb,rb,Za,ub,vb,wb,Ua,ab,bb,Fb,Gb,Hb,Ib,kb,xb,yb,I={},w;w=C.Highcharts?Z(16,!0):{win:C};w.seriesTypes=I;var Ha=[],ka,ra,o,Ma,Ab,Ba,N,V,H,Wa,Na;qb.prototype={dSetter:function(){var a=this.paths[0],b=this.paths[1],
	c=[],d=this.now,e=a.length,f;if(d===1)c=this.toD;else if(e===b.length&&d<1)for(;e--;)f=parseFloat(a[e]),c[e]=isNaN(f)?a[e]:d*parseFloat(b[e]-f)+f;else c=b;this.elem.attr("d",c)},update:function(){var a=this.elem,b=this.prop,c=this.now,d=this.options.step;if(this[b+"Setter"])this[b+"Setter"]();else a.attr?a.element&&a.attr(b,c):a.style[b]=c+this.unit;d&&d.call(a,c,this)},run:function(a,b,c){var d=this,e=function(a){return e.stopped?!1:d.step(a)},f;this.startTime=+new pa;this.start=a;this.end=b;this.unit=
	c;this.now=this.start;this.pos=0;e.elem=this.elem;if(e()&&Ha.push(e)===1)e.timerId=setInterval(function(){for(f=0;f<Ha.length;f++)Ha[f]()||Ha.splice(f--,1);Ha.length||clearInterval(e.timerId)},13)},step:function(a){var b=+new pa,c,d=this.options;c=this.elem;var e=d.complete,f=d.duration,g=d.curAnim,h;if(c.attr&&!c.element)c=!1;else if(a||b>=f+this.startTime){this.now=this.end;this.pos=1;this.update();a=g[this.prop]=!0;for(h in g)g[h]!==!0&&(a=!1);a&&e&&e.call(c);c=!1}else this.pos=d.easing((b-this.startTime)/
	f),this.now=this.start+(this.end-this.start)*this.pos,this.update(),c=!0;return c},initPath:function(a,b,c){var b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g,b=b.split(" "),c=[].concat(c),h=a.isArea,i=h?2:1,k=function(a){for(g=a.length;g--;)(a[g]==="M"||a[g]==="L")&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&(k(b),k(c));if(d<=c.length/f&&b.length===c.length)for(;d--;)c=c.slice(0,f).concat(c),h&&(c=c.concat(c.slice(c.length-f)));a.shift=0;if(b.length)for(a=c.length;b.length<a;)d=b.slice().splice(b.length/
	i-f,f*i),e&&(d[f-6]=d[f-2],d[f-5]=d[f-1]),[].splice.apply(b,[b.length/i,0].concat(d));return[b,c]}};var s=w.extend=function(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a},p=w.pick=function(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++)if(c=a[b],c!==z&&c!==null)return c},fb=w.wrap=function(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);a.unshift(d);return c.apply(this,a)}};Pa=function(a,b,c){if(!r(b)||isNaN(b))return S.lang.invalidDate||"";var a=p(a,"%Y-%m-%d %H:%M:%S"),
	d=new pa(b-Ya(b)),e,f=d[vb](),g=d[wb](),h=d[Ua](),i=d[ab](),k=d[bb](),j=S.lang,l=j.weekdays,m=j.shortWeekdays,d=s({a:m?m[g]:l[g].substr(0,3),A:l[g],d:Ea(h),e:Ea(h,2," "),w:g,b:j.shortMonths[i],B:j.months[i],m:Ea(i+1),y:k.toString().substr(2,2),Y:k,H:Ea(f),k:f,I:Ea(f%12||12),l:f%12||12,M:Ea(d[ub]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",S:Ea(d.getSeconds()),L:Ea(B(b%1E3),3)},w.dateFormats);for(e in d)for(;a.indexOf("%"+e)!==-1;)a=a.replace("%"+e,typeof d[e]==="function"?d[e](b):d[e]);return c?a.substr(0,
	1).toUpperCase()+a.substr(1):a};G={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};w.numberFormat=function(a,b,c,d){var a=+a||0,e=S.lang,f=(a.toString().split(".")[1]||"").length,g,h,i=Math.abs(a);b===-1?b=Math.min(f,20):isNaN(b)&&(b=2);g=String(F(i.toFixed(b)));h=g.length>3?g.length%3:0;c=p(c,e.decimalPoint);d=p(d,e.thousandsSep);a=a<0?"-":"";a+=h?g.substr(0,h)+d:"";a+=g.substr(h).replace(/(\d{3})(?=\d)/g,"$1"+d);+b&&(d=Math.abs(i-g+Math.pow(10,-Math.max(b,
	f)-1)),a+=c+d.toFixed(b).slice(2));return a};Math.easeInOutSine=function(a){return-0.5*(Math.cos(Math.PI*a)-1)};ka=function(a,b){var c;if(b==="width")return Math.min(a.offsetWidth,a.scrollWidth)-ka(a,"padding-left")-ka(a,"padding-right");else if(b==="height")return Math.min(a.offsetHeight,a.scrollHeight)-ka(a,"padding-top")-ka(a,"padding-bottom");return(c=C.getComputedStyle(a,void 0))&&F(c.getPropertyValue(b))};ra=function(a,b){return b.indexOf?b.indexOf(a):[].indexOf.call(b,a)};Ma=function(a,b){return[].filter.call(a,
	b)};Ba=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++)c[d]=b.call(a[d],a[d],d,a);return c};Ab=function(a){var b=A.documentElement,a=a.getBoundingClientRect();return{top:a.top+(C.pageYOffset||b.scrollTop)-(b.clientTop||0),left:a.left+(C.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}};Na=function(a){for(var b=Ha.length;b--;)if(Ha[b].elem===a)Ha[b].stopped=!0};o=function(a,b){return Array.prototype.forEach.call(a,b)};N=function(a,b,c){function d(b){b.target=b.srcElement||C;c.call(a,b)}var e=a.hcEvents=
	a.hcEvents||{};if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent){if(!a.hcEventsIE)a.hcEventsIE={};a.hcEventsIE[c.toString()]=d;a.attachEvent("on"+b,d)}e[b]||(e[b]=[]);e[b].push(c)};V=function(a,b,c){function d(b,c){a.removeEventListener?a.removeEventListener(b,c,!1):a.attachEvent&&(c=a.hcEventsIE[c.toString()],a.detachEvent("on"+b,c))}function e(){var c,e,f;if(a.nodeName)for(f in b?(c={},c[b]=!0):c=g,c)if(g[f])for(e=g[f].length;e--;)d(f,g[f][e])}var f,g=a.hcEvents,h;if(g)b?(f=
	g[b]||[],c?(h=ra(c,f),h>-1&&(f.splice(h,1),g[b]=f),d(b,c)):(e(),g[b]=[])):(e(),a.hcEvents={})};H=function(a,b,c,d){var e;e=a.hcEvents;var f,g,c=c||{};if(A.createEvent&&(a.dispatchEvent||a.fireEvent))e=A.createEvent("Events"),e.initEvent(b,!0,!0),e.target=a,s(e,c),a.dispatchEvent?a.dispatchEvent(e):a.fireEvent(b,e);else if(e){e=e[b]||[];f=e.length;if(!c.preventDefault)c.preventDefault=function(){c.defaultPrevented=!0};c.target=a;if(!c.type)c.type=b;for(b=0;b<f;b++)g=e[b],g.call(a,c)===!1&&c.preventDefault()}d&&
	!c.defaultPrevented&&d(c)};Wa=function(a,b,c){var d,e="",f,g,h;X(c)||(d=arguments,c={duration:d[2],easing:d[3],complete:d[4]});if(!ma(c.duration))c.duration=400;c.easing=typeof c.easing==="function"?c.easing:Math[c.easing]||Math.easeInOutSine;c.curAnim=D(b);for(h in b)g=new qb(a,c,h),f=null,h==="d"?(g.paths=g.initPath(a,a.d,b.d),g.toD=b.d,d=0,f=1):a.attr?d=a.attr(h):(d=parseFloat(ka(a,h))||0,h!=="opacity"&&(e="px")),f||(f=b[h]),f.match&&f.match("px")&&(f=f.replace(/px/g,"")),g.run(d,f,e)};if(C.jQuery)C.jQuery.fn.highcharts=
	function(){var a=[].slice.call(arguments);if(this[0])return a[0]?(new (w[xa(a[0])?a.shift():"Chart"])(this[0],a[0],a[1]),this):O[K(this[0],"data-highcharts-chart")]};A&&!A.defaultView&&(ka=function(a,b){var c;c={width:"clientWidth",height:"clientHeight"}[b];if(a.style[b])return F(a.style[b]);b==="opacity"&&(b="filter");if(c)return a.style.zoom=1,Math.max(a[c]-2*ka(a,"padding"),0);c=a.currentStyle[b.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()})];b==="filter"&&(c=c.replace(/alpha\(opacity=([0-9]+)\)/,
	function(a,b){return b/100}));return c===""?1:F(c)});Array.prototype.forEach||(o=function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===!1)return c});Array.prototype.indexOf||(ra=function(a,b){var c,d=0;if(b)for(c=b.length;d<c;d++)if(b[d]===a)return d;return-1});Array.prototype.filter||(Ma=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++)b(a[d],d)&&c.push(a[d]);return c});w.Fx=qb;w.inArray=ra;w.each=o;w.grep=Ma;w.offset=Ab;w.map=Ba;w.addEvent=N;w.removeEvent=V;w.fireEvent=H;w.animate=
	Wa;w.animObject=$a;w.stop=Na;S={colors:"#7cb5ec,#434348,#90ed7d,#f7a35c,#8085e9,#f15c80,#e4d354,#2b908f,#f45b5b,#91e8e1".split(","),symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),weekdays:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),decimalPoint:".",numericSymbols:"k,M,G,T,P,E".split(","),
	resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:" "},global:{useUTC:!0,canvasToolsURL:"http://code.highcharts.com/modules/canvas-tools.js",VMLRadialGradientURL:"http://code.highcharts.com/4.2.4/gfx/vml-radial-gradient.png"},chart:{borderColor:"#4572A7",borderRadius:0,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacing:[10,10,15,10],backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0",resetZoomButton:{theme:{zIndex:20},position:{align:"right",x:-10,y:10}}},title:{text:"Chart title",
	align:"center",margin:15,style:{color:"#333333",fontSize:"18px"}},subtitle:{text:"",align:"center",style:{color:"#555555"}},plotOptions:{line:{allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},lineWidth:2,marker:{lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{enabled:!0,lineWidthPlus:1,radiusPlus:2},select:{fillColor:"#FFFFFF",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return this.y===null?"":w.numberFormat(this.y,
	-1)},style:{color:"contrast",fontSize:"11px",fontWeight:"bold",textShadow:"0 0 6px contrast, 0 0 3px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{lineWidthPlus:1,marker:{},halo:{size:10,opacity:0.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3}},labels:{style:{position:"absolute",color:"#3E576F"}},legend:{enabled:!0,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderColor:"#909090",
	borderRadius:0,navigation:{activeColor:"#274b6d",inactiveColor:"#CCC"},shadow:!1,itemStyle:{color:"#333333",fontSize:"12px",fontWeight:"bold"},itemHoverStyle:{color:"#000"},itemHiddenStyle:{color:"#CCC"},itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},symbolPadding:5,verticalAlign:"bottom",x:0,y:0,title:{style:{fontWeight:"bold"}}},loading:{labelStyle:{fontWeight:"bold",position:"relative",top:"45%"},style:{position:"absolute",backgroundColor:"white",opacity:0.5,textAlign:"center"}},
	tooltip:{enabled:!0,animation:ca,backgroundColor:"rgba(249, 249, 249, .85)",borderWidth:1,borderRadius:3,dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L",second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},footerFormat:"",headerFormat:'<span style="font-size: 10px">{point.key}</span><br/>',pointFormat:'<span style="color:{point.color}">\u25cf</span> {series.name}: <b>{point.y}</b><br/>',
	shadow:!0,snap:Lb?25:10,style:{color:"#333333",cursor:"default",fontSize:"12px",padding:"8px",pointerEvents:"none",whiteSpace:"nowrap"}},credits:{enabled:!0,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"9px"}}};var ba=S.plotOptions,ea=ba.line;Eb();ja.prototype={parsers:[{regex:/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/,parse:function(a){return[F(a[1]),
	F(a[2]),F(a[3]),parseFloat(a[4],10)]}},{regex:/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,parse:function(a){return[F(a[1],16),F(a[2],16),F(a[3],16),1]}},{regex:/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,parse:function(a){return[F(a[1]),F(a[2]),F(a[3]),1]}}],init:function(a){var b,c,d,e;if((this.input=a)&&a.stops)this.stops=Ba(a.stops,function(a){return new ja(a[1])});else for(d=this.parsers.length;d--&&!c;)e=this.parsers[d],(b=e.regex.exec(a))&&(c=e.parse(b));this.rgba=
	c||[]},get:function(a){var b=this.input,c=this.rgba,d;this.stops?(d=D(b),d.stops=[].concat(d.stops),o(this.stops,function(b,c){d.stops[c]=[d.stops[c][0],b.get(a)]})):d=c&&!isNaN(c[0])?a==="rgb"||!a&&c[3]===1?"rgb("+c[0]+","+c[1]+","+c[2]+")":a==="a"?c[3]:"rgba("+c.join(",")+")":b;return d},brighten:function(a){var b,c=this.rgba;if(this.stops)o(this.stops,function(b){b.brighten(a)});else if(ma(a)&&a!==0)for(b=0;b<3;b++)c[b]+=F(a*255),c[b]<0&&(c[b]=0),c[b]>255&&(c[b]=255);return this},setOpacity:function(a){this.rgba[3]=
	a;return this}};P.prototype={opacity:1,textProps:"direction,fontSize,fontWeight,fontFamily,fontStyle,color,lineHeight,width,textDecoration,textOverflow,textShadow".split(","),init:function(a,b){this.element=b==="span"?$(b):A.createElementNS(Ga,b);this.renderer=a},animate:function(a,b,c){b=p(b,this.renderer.globalAnimation,!0);Na(this);if(b){if(c)b.complete=c;Wa(this,a,b)}else this.attr(a,null,c);return this},colorGradient:function(a,b,c){var d=this.renderer,e,f,g,h,i,k,j,l,m,n,q,v=[],y;a.linearGradient?
	f="linearGradient":a.radialGradient&&(f="radialGradient");if(f){g=a[f];i=d.gradients;j=a.stops;n=c.radialReference;Da(g)&&(a[f]=g={x1:g[0],y1:g[1],x2:g[2],y2:g[3],gradientUnits:"userSpaceOnUse"});f==="radialGradient"&&n&&!r(g.gradientUnits)&&(h=g,g=D(g,d.getRadialAttr(n,h),{gradientUnits:"userSpaceOnUse"}));for(q in g)q!=="id"&&v.push(q,g[q]);for(q in j)v.push(j[q]);v=v.join(",");i[v]?n=i[v].attr("id"):(g.id=n="highcharts-"+zb++,i[v]=k=d.createElement(f).attr(g).add(d.defs),k.radAttr=h,k.stops=[],
	o(j,function(a){a[1].indexOf("rgba")===0?(e=ja(a[1]),l=e.get("rgb"),m=e.get("a")):(l=a[1],m=1);a=d.createElement("stop").attr({offset:a[0],"stop-color":l,"stop-opacity":m}).add(k);k.stops.push(a)}));y="url("+d.url+"#"+n+")";c.setAttribute(b,y);c.gradient=v;a.toString=function(){return y}}},applyTextShadow:function(a){var b=this.element,c,d=a.indexOf("contrast")!==-1,e={},f=this.renderer.forExport,g=f||b.style.textShadow!==z&&!ya;if(d)e.textShadow=a=a.replace(/contrast/g,this.renderer.getContrast(b.style.fill));
	if(mb||f)e.textRendering="geometricPrecision";g?this.css(e):(this.fakeTS=!0,this.ySetter=this.xSetter,c=[].slice.call(b.getElementsByTagName("tspan")),o(a.split(/\s?,\s?/g),function(a){var d=b.firstChild,e,f,a=a.split(" ");e=a[a.length-1];(f=a[a.length-2])&&o(c,function(a,c){var g;c===0&&(a.setAttribute("x",b.getAttribute("x")),c=b.getAttribute("y"),a.setAttribute("y",c||0),c===null&&b.setAttribute("y",0));g=a.cloneNode(1);K(g,{"class":"highcharts-text-shadow",fill:e,stroke:e,"stroke-opacity":1/t(F(f),
	3),"stroke-width":f,"stroke-linejoin":"round"});b.insertBefore(g,d)})}))},attr:function(a,b,c){var d,e=this.element,f,g=this,h;typeof a==="string"&&b!==z&&(d=a,a={},a[d]=b);if(typeof a==="string")g=(this[a+"Getter"]||this._defaultGetter).call(this,a,e);else{for(d in a){b=a[d];h=!1;this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(d)&&(f||(this.symbolAttr(a),f=!0),h=!0);if(this.rotation&&(d==="x"||d==="y"))this.doTransform=!0;h||(h=this[d+"Setter"]||this._defaultSetter,
	h.call(this,b,d,e),this.shadows&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(d)&&this.updateShadows(d,b,h))}if(this.doTransform)this.updateTransform(),this.doTransform=!1}c&&c();return g},updateShadows:function(a,b,c){for(var d=this.shadows,e=d.length;e--;)c.call(d[e],a==="height"?Math.max(b-(d[e].cutHeight||0),0):a==="d"?this.d:b,a,d[e])},addClass:function(a){var b=this.element,c=K(b,"class")||"";c.indexOf(a)===-1&&K(b,"class",c+" "+a);return this},symbolAttr:function(a){var b=this;
	o("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=p(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](b.x,b.y,b.width,b.height,b)})},clip:function(a){return this.attr("clip-path",a?"url("+this.renderer.url+"#"+a.id+")":"none")},crisp:function(a){var b,c={},d,e=this.strokeWidth||0;d=B(e)%2/2;a.x=T(a.x||this.x||0)+d;a.y=T(a.y||this.y||0)+d;a.width=T((a.width||this.width||0)-2*d);a.height=T((a.height||this.height||0)-2*d);a.strokeWidth=e;for(b in a)this[b]!==a[b]&&
	(this[b]=c[b]=a[b]);return c},css:function(a){var b=this.styles,c={},d=this.element,e,f,g="";e=!b;if(a&&a.color)a.fill=a.color;if(b)for(f in a)a[f]!==b[f]&&(c[f]=a[f],e=!0);if(e){e=this.textWidth=a&&a.width&&d.nodeName.toLowerCase()==="text"&&F(a.width)||this.textWidth;b&&(a=s(b,c));this.styles=a;e&&(ia||!ca&&this.renderer.forExport)&&delete a.width;if(ya&&!ca)L(this.element,a);else{b=function(a,b){return"-"+b.toLowerCase()};for(f in a)g+=f.replace(/([A-Z])/g,b)+":"+a[f]+";";K(d,"style",g)}e&&this.added&&
	this.renderer.buildText(this)}return this},on:function(a,b){var c=this,d=c.element;db&&a==="click"?(d.ontouchstart=function(a){c.touchEventFired=pa.now();a.preventDefault();b.call(d,a)},d.onclick=function(a){(za.indexOf("Android")===-1||pa.now()-(c.touchEventFired||0)>1100)&&b.call(d,a)}):d["on"+a]=b;return this},setRadialReference:function(a){var b=this.renderer.gradients[this.element.gradient];this.element.radialReference=a;b&&b.radAttr&&b.animate(this.renderer.getRadialAttr(a,b.radAttr));return this},
	translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation,g=this.element;e&&(a+=this.attr("width"),b+=this.attr("height"));a=["translate("+a+","+b+")"];e?a.push("rotate(90) scale(-1,1)"):f&&a.push("rotate("+f+" "+(g.getAttribute("x")||0)+" "+(g.getAttribute("y")||0)+")");(r(c)||r(d))&&
	a.push("scale("+p(c,1)+" "+p(d,1)+")");a.length&&g.setAttribute("transform",a.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){var d,e,f,g,h={};e=this.renderer;f=e.alignedObjects;if(a){if(this.alignOptions=a,this.alignByTranslate=b,!c||xa(c))this.alignTo=d=c||"renderer",na(f,this),f.push(this),c=null}else a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo;c=p(c,e[d],e);d=a.align;e=a.verticalAlign;f=(c.x||0)+(a.x||0);g=(c.y||0)+
	(a.y||0);if(d==="right"||d==="center")f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=B(f);if(e==="bottom"||e==="middle")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=B(g);this[this.placed?"animate":"attr"](h);this.placed=!0;this.alignAttr=h;return this},getBBox:function(a,b){var c,d=this.renderer,e,f,g,h=this.element,i=this.styles;e=this.textStr;var k,j=h.style,l,m=d.cache,n=d.cacheKeys,q;f=p(b,this.rotation);g=f*ha;e!==z&&(q=["",f||0,i&&i.fontSize,
	h.style.width].join(","),q=e===""||Qb.test(e)?"num:"+e.toString().length+q:e+q);q&&!a&&(c=m[q]);if(!c){if(h.namespaceURI===Ga||d.forExport){try{l=this.fakeTS&&function(a){o(h.querySelectorAll(".highcharts-text-shadow"),function(b){b.style.display=a})},La&&j.textShadow?(k=j.textShadow,j.textShadow=""):l&&l("none"),c=h.getBBox?s({},h.getBBox()):{width:h.offsetWidth,height:h.offsetHeight},k?j.textShadow=k:l&&l("")}catch(v){}if(!c||c.width<0)c={width:0,height:0}}else c=this.htmlGetBBox();if(d.isSVG){d=
	c.width;e=c.height;if(ya&&i&&i.fontSize==="11px"&&e.toPrecision(3)==="16.9")c.height=e=14;if(f)c.width=Q(e*aa(g))+Q(d*U(g)),c.height=Q(e*U(g))+Q(d*aa(g))}if(q){for(;n.length>250;)delete m[n.shift()];m[q]||n.push(q);m[q]=c}}return c},show:function(a){return this.attr({visibility:a?"inherit":"visible"})},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.attr({y:-9999})}})},add:function(a){var b=this.renderer,
	c=this.element,d;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);this.added=!0;if(!a||a.handleZ||this.zIndex)d=this.zIndexSetter();d||(a?a.element:b.box).appendChild(c);if(this.onAdd)this.onAdd();return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&b.nodeName==="SPAN"&&a.parentGroup,e,f;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=
	null;Na(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(f=0;f<a.stops.length;f++)a.stops[f]=a.stops[f].destroy();a.stops=null}a.safeRemoveChild(b);for(c&&o(c,function(b){a.safeRemoveChild(b)});d&&d.div&&d.div.childNodes.length===0;)b=d.parentGroup,a.safeRemoveChild(d.div),delete d.div,d=b;a.alignTo&&na(a.renderer.alignedObjects,a);for(e in a)delete a[e];return null},shadow:function(a,b,c){var d=[],e,f,g=this.element,h,i,k,j;if(a){i=p(a.width,3);k=(a.opacity||0.15)/i;j=this.parentInverted?
	"(-1,-1)":"("+p(a.offsetX,1)+", "+p(a.offsetY,1)+")";for(e=1;e<=i;e++){f=g.cloneNode(0);h=i*2+1-2*e;K(f,{isShadow:"true",stroke:a.color||"black","stroke-opacity":k*e,"stroke-width":h,transform:"translate"+j,fill:"none"});if(c)K(f,"height",t(K(f,"height")-h,0)),f.cutHeight=h;b?b.element.appendChild(f):g.parentNode.insertBefore(f,g);d.push(f)}this.shadows=d}return this},xGetter:function(a){this.element.nodeName==="circle"&&(a={x:"cx",y:"cy"}[a]||a);return this._defaultGetter(a)},_defaultGetter:function(a){a=
	p(this[a],this.element?this.element.getAttribute(a):null,0);/^[\-0-9\.]+$/.test(a)&&(a=parseFloat(a));return a},dSetter:function(a,b,c){a&&a.join&&(a=a.join(" "));/(NaN| {2}|^$)/.test(a)&&(a="M 0 0");c.setAttribute(b,a);this[b]=a},dashstyleSetter:function(a){var b,c=this["stroke-width"];c==="inherit"&&(c=1);if(a=a&&a.toLowerCase()){a=a.replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot","3,1,1,1").replace("shortdot","1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,
	"1,3,").replace("dash","4,3,").replace(/,$/,"").split(",");for(b=a.length;b--;)a[b]=F(a[b])*c;a=a.join(",").replace(/NaN/g,"none");this.element.setAttribute("stroke-dasharray",a)}},alignSetter:function(a){this.element.setAttribute("text-anchor",{left:"start",center:"middle",right:"end"}[a])},opacitySetter:function(a,b,c){this[b]=a;c.setAttribute(b,a)},titleSetter:function(a){var b=this.element.getElementsByTagName("title")[0];b||(b=A.createElementNS(Ga,"title"),this.element.appendChild(b));b.appendChild(A.createTextNode(String(p(a),
	"").replace(/<[^>]*>/g,"")))},textSetter:function(a){if(a!==this.textStr)delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this)},fillSetter:function(a,b,c){typeof a==="string"?c.setAttribute(b,a):a&&this.colorGradient(a,b,c)},visibilitySetter:function(a,b,c){a==="inherit"?c.removeAttribute(b):c.setAttribute(b,a)},zIndexSetter:function(a,b){var c=this.renderer,d=this.parentGroup,c=(d||c).element||c.box,e,f,g=this.element,h;e=this.added;var i;if(r(a))g.zIndex=a,a=+a,this[b]===a&&
	(e=!1),this[b]=a;if(e){if((a=this.zIndex)&&d)d.handleZ=!0;d=c.childNodes;for(i=0;i<d.length&&!h;i++)if(e=d[i],f=e.zIndex,e!==g&&(F(f)>a||!r(a)&&r(f)))c.insertBefore(g,e),h=!0;h||c.appendChild(g)}return h},_defaultSetter:function(a,b,c){c.setAttribute(b,a)}};P.prototype.yGetter=P.prototype.xGetter;P.prototype.translateXSetter=P.prototype.translateYSetter=P.prototype.rotationSetter=P.prototype.verticalAlignSetter=P.prototype.scaleXSetter=P.prototype.scaleYSetter=function(a,b){this[b]=a;this.doTransform=
	!0};P.prototype["stroke-widthSetter"]=P.prototype.strokeSetter=function(a,b,c){this[b]=a;if(this.stroke&&this["stroke-width"])this.strokeWidth=this["stroke-width"],P.prototype.fillSetter.call(this,this.stroke,"stroke",c),c.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0;else if(b==="stroke-width"&&a===0&&this.hasStroke)c.removeAttribute("stroke"),this.hasStroke=!1};var Ca=function(){this.init.apply(this,arguments)};Ca.prototype={Element:P,init:function(a,b,c,d,e,f){var g,d=this.createElement("svg").attr({version:"1.1"}).css(this.getStyle(d));
	g=d.element;a.appendChild(g);a.innerHTML.indexOf("xmlns")===-1&&K(g,"xmlns",Ga);this.isSVG=!0;this.box=g;this.boxWrapper=d;this.alignedObjects=[];this.url=(La||mb)&&A.getElementsByTagName("base").length?C.location.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(A.createTextNode("Created with Highcharts 4.2.4"));this.defs=this.createElement("defs").add();this.allowHTML=f;this.forExport=e;this.gradients={};this.cache=
	{};this.cacheKeys=[];this.imgCount=0;this.setSize(b,c,!1);var h;if(La&&a.getBoundingClientRect)this.subPixelFix=b=function(){L(a,{left:0,top:0});h=a.getBoundingClientRect();L(a,{left:ua(h.left)-h.left+"px",top:ua(h.top)-h.top+"px"})},b(),N(C,"resize",b)},getStyle:function(a){return this.style=s({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=
	null;this.boxWrapper=this.boxWrapper.destroy();Ra(this.gradients||{});this.gradients=null;if(a)this.defs=a.destroy();this.subPixelFix&&V(C,"resize",this.subPixelFix);return this.alignedObjects=null},createElement:function(a){var b=new this.Element;b.init(this,a);return b},draw:function(){},getRadialAttr:function(a,b){return{cx:a[0]-a[2]/2+b.cx*a[2],cy:a[1]-a[2]/2+b.cy*a[2],r:b.r*a[2]}},buildText:function(a){for(var b=a.element,c=this,d=c.forExport,e=p(a.textStr,"").toString(),f=e.indexOf("<")!==-1,
	g=b.childNodes,h,i,k=K(b,"x"),j=a.styles,l=a.textWidth,m=j&&j.lineHeight,n=j&&j.textShadow,q=j&&j.textOverflow==="ellipsis",v=g.length,y=l&&!a.added&&this.box,sa=function(a){return m?F(m):c.fontMetrics(/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:j&&j.fontSize||c.style.fontSize||12,a).h},x=function(a){return a.replace(/&lt;/g,"<").replace(/&gt;/g,">")};v--;)b.removeChild(g[v]);!f&&!n&&!q&&e.indexOf(" ")===-1?b.appendChild(A.createTextNode(x(e))):(h=/<.*style="([^"]+)".*>/,i=/<.*href="(http[^"]+)".*>/,
	y&&y.appendChild(b),e=f?e.replace(/<(b|strong)>/g,'<span style="font-weight:bold">').replace(/<(i|em)>/g,'<span style="font-style:italic">').replace(/<a/g,"<span").replace(/<\/(b|strong|i|em|a)>/g,"</span>").split(/<br.*?>/g):[e],e[e.length-1]===""&&e.pop(),o(e,function(e,f){var g,m=0,e=e.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");g=e.split("|||");o(g,function(e){if(e!==""||g.length===1){var n={},v=A.createElementNS(Ga,"tspan"),y;h.test(e)&&(y=e.match(h)[1].replace(/(;| |^)color([ :])/,
	"$1fill$2"),K(v,"style",y));i.test(e)&&!d&&(K(v,"onclick",'location.href="'+e.match(i)[1]+'"'),L(v,{cursor:"pointer"}));e=x(e.replace(/<(.|\n)*?>/g,"")||" ");if(e!==" "){v.appendChild(A.createTextNode(e));if(m)n.dx=0;else if(f&&k!==null)n.x=k;K(v,n);b.appendChild(v);!m&&f&&(!ca&&d&&L(v,{display:"block"}),K(v,"dy",sa(v)));if(l){for(var n=e.replace(/([^\^])-/g,"$1- ").split(" "),p=g.length>1||f||n.length>1&&j.whiteSpace!=="nowrap",o,u,r,t=[],s=sa(v),B=1,z=a.rotation,w=e,D=w.length;(p||q)&&(n.length||
	t.length);)a.rotation=0,o=a.getBBox(!0),r=o.width,!ca&&c.forExport&&(r=c.measureSpanWidth(v.firstChild.data,a.styles)),o=r>l,u===void 0&&(u=o),q&&u?(D/=2,w===""||!o&&D<0.5?n=[]:(o&&(u=!0),w=e.substring(0,w.length+(o?-1:1)*ua(D)),n=[w+(l>3?"\u2026":"")],v.removeChild(v.firstChild))):!o||n.length===1?(n=t,t=[],n.length&&(B++,v=A.createElementNS(Ga,"tspan"),K(v,{dy:s,x:k}),y&&K(v,"style",y),b.appendChild(v)),r>l&&(l=r)):(v.removeChild(v.firstChild),t.unshift(n.pop())),n.length&&v.appendChild(A.createTextNode(n.join(" ").replace(/- /g,
	"-")));u&&a.attr("title",a.textStr);a.rotation=z}m++}}})}),y&&y.removeChild(b),n&&a.applyTextShadow&&a.applyTextShadow(n))},getContrast:function(a){a=ja(a).rgba;return a[0]+a[1]+a[2]>384?"#000000":"#FFFFFF"},button:function(a,b,c,d,e,f,g,h,i){var k=this.label(a,b,c,i,null,null,null,null,"button"),j=0,l,m,n,q,v,y,a={x1:0,y1:0,x2:0,y2:1},e=D({"stroke-width":1,stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);n=e.style;delete e.style;
	f=D(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f);q=f.style;delete f.style;g=D(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g);v=g.style;delete g.style;h=D(e,{style:{color:"#CCC"}},h);y=h.style;delete h.style;N(k.element,ya?"mouseover":"mouseenter",function(){j!==3&&k.attr(f).css(q)});N(k.element,ya?"mouseout":"mouseleave",function(){j!==3&&(l=[e,f,g][j],m=[n,q,v][j],k.attr(l).css(m))});k.setState=function(a){(k.state=j=a)?a===2?k.attr(g).css(v):
	a===3&&k.attr(h).css(y):k.attr(e).css(n)};return k.on("click",function(a){j!==3&&d.call(k,a)}).attr(e).css(s({cursor:"default"},n))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=B(a[1])-b%2/2);a[2]===a[5]&&(a[2]=a[5]=B(a[2])+b%2/2);return a},path:function(a){var b={fill:"none"};Da(a)?b.d=a:X(a)&&s(b,a);return this.createElement("path").attr(b)},circle:function(a,b,c){a=X(a)?a:{x:a,y:b,r:c};b=this.createElement("circle");b.xSetter=b.ySetter=function(a,b,c){c.setAttribute("c"+b,a)};return b.attr(a)},
	arc:function(a,b,c,d,e,f){if(X(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;a=this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0});a.r=c;return a},rect:function(a,b,c,d,e,f){var e=X(a)?a.r:e,g=this.createElement("rect"),a=X(a)?a:a===z?{}:{x:a,y:b,width:t(c,0),height:t(d,0)};if(f!==z)g.strokeWidth=f,a=g.crisp(a);if(e)a.r=e;g.rSetter=function(a,b,c){K(c,{rx:a,ry:a})};return g.attr(a)},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[p(c,
	!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return r(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:"none"};arguments.length>1&&s(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e,f){var g=this,h,i=this.symbols[a],
	i=i&&i(B(b),B(c),d,e,f),k=/^url\((.*?)\)$/,j,l;if(i)h=this.path(i),s(h,{symbolName:a,x:b,y:c,width:d,height:e}),f&&s(h,f);else if(k.test(a))l=function(a,b){a.element&&(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(B((d-b[0])/2),B((e-b[1])/2)))},j=a.match(k)[1],a=Mb[j]||f&&f.width&&f.height&&[f.width,f.height],h=this.image(j).attr({x:b,y:c}),h.isImg=!0,a?l(h,a):(h.attr({width:0,height:0}),$("img",{onload:function(){this.width===0&&(L(this,{position:"absolute",top:"-999em"}),A.body.appendChild(this));
	l(h,Mb[j]=[this.width,this.height]);this.parentNode&&this.parentNode.removeChild(this);g.imgCount--;if(!g.imgCount&&O[g.chartIndex].onload)O[g.chartIndex].onload()},src:j}),this.imgCount++);return h},symbols:{circle:function(a,b,c,d){var e=0.166*c;return["M",a+c/2,b,"C",a+c+e,b,a+c+e,b+d,a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/2,b,"Z"]},square:function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,
	d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-0.001,d=e.innerR,h=e.open,i=U(f),k=aa(f),j=U(g),g=aa(g),e=e.end-f<qa?0:1;return["M",a+c*i,b+c*k,"A",c,c,0,e,1,a+c*j,b+c*g,h?"M":"L",a+d*j,b+d*g,"A",d,d,0,e,0,a+d*i,b+d*k,h?"":"Z"]},callout:function(a,b,c,d,e){var f=E(e&&e.r||0,c,d),g=f+6,h=e&&e.anchorX,e=e&&e.anchorY,i;i=["M",a+f,b,"L",a+c-f,b,"C",a+c,b,a+c,b,a+c,b+
	f,"L",a+c,b+d-f,"C",a+c,b+d,a+c,b+d,a+c-f,b+d,"L",a+f,b+d,"C",a,b+d,a,b+d,a,b+d-f,"L",a,b+f,"C",a,b,a,b,a+f,b];h&&h>c&&e>b+g&&e<b+d-g?i.splice(13,3,"L",a+c,e-6,a+c+6,e,a+c,e+6,a+c,b+d-f):h&&h<0&&e>b+g&&e<b+d-g?i.splice(33,3,"L",a,e+6,a-6,e,a,e-6,a,b+f):e&&e>d&&h>a+g&&h<a+c-g?i.splice(23,3,"L",h+6,b+d,h,b+d+6,h-6,b+d,a+f,b+d):e&&e<0&&h>a+g&&h<a+c-g&&i.splice(3,3,"L",h-6,b,h,b-6,h+6,b,c-f,b);return i}},clipRect:function(a,b,c,d){var e="highcharts-"+zb++,f=this.createElement("clipPath").attr({id:e}).add(this.defs),
	a=this.rect(a,b,c,d,0).add(f);a.id=e;a.clipPath=f;a.count=0;return a},text:function(a,b,c,d){var e=ia||!ca&&this.forExport,f={};if(d&&(this.allowHTML||!this.forExport))return this.html(a,b,c);f.x=Math.round(b||0);if(c)f.y=Math.round(c);if(a||a===0)f.text=a;a=this.createElement("text").attr(f);e&&a.css({position:"absolute"});if(!d)a.xSetter=function(a,b,c){var d=c.getElementsByTagName("tspan"),e,f=c.getAttribute(b),m;for(m=0;m<d.length;m++)e=d[m],e.getAttribute(b)===f&&e.setAttribute(b,a);c.setAttribute(b,
	a)};return a},fontMetrics:function(a,b){var c,d,a=a||this.style.fontSize;!a&&b&&C.getComputedStyle&&(b=b.element||b,a=(c=C.getComputedStyle(b,""))&&c.fontSize);a=/px/.test(a)?F(a):/em/.test(a)?parseFloat(a)*12:12;c=a<24?a+3:B(a*1.2);d=B(c*0.8);return{h:c,b:d,f:a}},rotCorr:function(a,b,c){var d=a;b&&c&&(d=t(d*U(b*ha),4));return{x:-a/3*aa(b*ha),y:d}},label:function(a,b,c,d,e,f,g,h,i){var k=this,j=k.g(i),l=k.text("",0,0,g).attr({zIndex:1}),m,n,q=0,v=3,y=0,p,x,u,t,ob=0,Y={},w,A,J,E,C;J=function(){var a,
	b;a=l.element.style;n=(p===void 0||x===void 0||j.styles.textAlign)&&r(l.textStr)&&l.getBBox();j.width=(p||n.width||0)+2*v+y;j.height=(x||n.height||0)+2*v;w=v+k.fontMetrics(a&&a.fontSize,l).b;if(A){if(!m)a=ob,b=(h?-w:0)+ob,j.box=m=d?k.symbol(d,a,b,j.width,j.height,Y):k.rect(a,b,j.width,j.height,0,Y["stroke-width"]),m.isImg||m.attr("fill","none"),m.add(j);m.isImg||m.attr(s({width:B(j.width),height:B(j.height)},Y));Y=null}};E=function(){var a=j.styles,a=a&&a.textAlign,b=y+v,c;c=h?0:w;if(r(p)&&n&&(a===
	"center"||a==="right"))b+={center:0.5,right:1}[a]*(p-n.width);if(b!==l.x||c!==l.y)l.attr("x",b),c!==z&&l.attr("y",c);l.x=b;l.y=c};C=function(a,b){m?m.attr(a,b):Y[a]=b};j.onAdd=function(){l.add(j);j.attr({text:a||a===0?a:"",x:b,y:c});m&&r(e)&&j.attr({anchorX:e,anchorY:f})};j.widthSetter=function(a){p=a};j.heightSetter=function(a){x=a};j.paddingSetter=function(a){if(r(a)&&a!==v)v=j.padding=a,E()};j.paddingLeftSetter=function(a){r(a)&&a!==y&&(y=a,E())};j.alignSetter=function(a){a={left:0,center:0.5,
	right:1}[a];a!==q&&(q=a,n&&j.attr({x:u}))};j.textSetter=function(a){a!==z&&l.textSetter(a);J();E()};j["stroke-widthSetter"]=function(a,b){a&&(A=!0);ob=a%2/2;C(b,a)};j.strokeSetter=j.fillSetter=j.rSetter=function(a,b){b==="fill"&&a&&(A=!0);C(b,a)};j.anchorXSetter=function(a,b){e=a;C(b,B(a)-ob-u)};j.anchorYSetter=function(a,b){f=a;C(b,a-t)};j.xSetter=function(a){j.x=a;q&&(a-=q*((p||n.width)+2*v));u=B(a);j.attr("translateX",u)};j.ySetter=function(a){t=j.y=B(a);j.attr("translateY",t)};var F=j.css;return s(j,
	{css:function(a){if(a){var b={},a=D(a);o(j.textProps,function(c){a[c]!==z&&(b[c]=a[c],delete a[c])});l.css(b)}return F.call(j,a)},getBBox:function(){return{width:n.width+2*v,height:n.height+2*v,x:n.x-v,y:n.y-v}},shadow:function(a){m&&m.shadow(a);return j},destroy:function(){V(j.element,"mouseenter");V(j.element,"mouseleave");l&&(l=l.destroy());m&&(m=m.destroy());P.prototype.destroy.call(j);j=k=J=E=C=null}})}};cb=Ca;s(P.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&b.tagName==="SPAN"&&
	a.width)delete a.width,this.textWidth=b,this.updateTransform();if(a&&a.textOverflow==="ellipsis")a.whiteSpace="nowrap",a.overflow="hidden";this.styles=s(this.styles,a);L(this.element,a);return this},htmlGetBBox:function(){var a=this.element;if(a.nodeName==="text")a.style.position="absolute";return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}},htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,c=this.translateX||0,d=this.translateY||0,e=this.x||
	0,f=this.y||0,g=this.textAlign||"left",h={left:0,center:0.5,right:1}[g],i=this.shadows,k=this.styles;L(b,{marginLeft:c,marginTop:d});i&&o(i,function(a){L(a,{marginLeft:c+1,marginTop:d+1})});this.inverted&&o(b.childNodes,function(c){a.invertChild(c,b)});if(b.tagName==="SPAN"){var i=this.rotation,j=F(this.textWidth),l=k&&k.whiteSpace,m=[i,g,b.innerHTML,this.textWidth,this.textAlign].join(",");if(m!==this.cTT){k=a.fontMetrics(b.style.fontSize).b;r(i)&&this.setSpanRotation(i,h,k);if(b.offsetWidth>j&&
	/[ \-]/.test(b.textContent||b.innerText))L(b,{width:j+"px",display:"block",whiteSpace:l||"normal"}),this.hasTextWidth=!0;else if(this.hasTextWidth)L(b,{width:"",display:"",whiteSpace:l||"nowrap"}),this.hasTextWidth=!1;this.getSpanCorrection(this.hasTextWidth?j:b.offsetWidth,k,h,i,g)}L(b,{left:e+(this.xCorr||0)+"px",top:f+(this.yCorr||0)+"px"});if(mb)k=b.offsetHeight;this.cTT=m}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,c){var d={},e=ya?"-ms-transform":mb?"-webkit-transform":La?"MozTransform":
	Kb?"-o-transform":"";d[e]=d.transform="rotate("+a+"deg)";d[e+(La?"Origin":"-origin")]=d.transformOrigin=b*100+"% "+c+"px";L(this.element,d)},getSpanCorrection:function(a,b,c){this.xCorr=-a*c;this.yCorr=-b}});s(Ca.prototype,{html:function(a,b,c){var d=this.createElement("span"),e=d.element,f=d.renderer,g=f.isSVG,h=function(a,b){o(["opacity","visibility"],function(c){fb(a,c+"Setter",function(a,c,d,e){a.call(this,c,d,e);b[d]=c})})};d.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;e.innerHTML=
	this.textStr=a;d.htmlUpdateTransform()};g&&h(d,d.element.style);d.xSetter=d.ySetter=d.alignSetter=d.rotationSetter=function(a,b){b==="align"&&(b="textAlign");d[b]=a;d.htmlUpdateTransform()};d.attr({text:a,x:B(b),y:B(c)}).css({position:"absolute",fontFamily:this.style.fontFamily,fontSize:this.style.fontSize});e.style.whiteSpace="nowrap";d.css=d.htmlCss;if(g)d.add=function(a){var b,c=f.box.parentNode,g=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)g.push(a),a=a.parentGroup;o(g.reverse(),function(a){var d,
	e=K(a.element,"class");e&&(e={className:e});b=a.div=a.div||$(Ka,e,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",opacity:a.opacity},b||c);d=b.style;s(a,{translateXSetter:function(b,c){d.left=b+"px";a[c]=b;a.doTransform=!0},translateYSetter:function(b,c){d.top=b+"px";a[c]=b;a.doTransform=!0}});h(a,d)})}}else b=c;b.appendChild(e);d.added=!0;d.alignOnAdd&&d.htmlUpdateTransform();return d};return d}});var M;if(!ca&&!ia){M={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],
	d=["position: ","absolute",";"],e=b===Ka;(b==="shape"||e)&&d.push("left:0;top:0;width:1px;height:1px;");d.push("visibility: ",e?"hidden":"visible");c.push(' style="',d.join(""),'"/>');if(b)c=e||b==="span"||b==="img"?c.join(""):a.prepVML(c),this.element=$(c);this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box,e=a&&a.inverted,d=a?a.element||a:d;if(a)this.parentGroup=a;e&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();
	if(this.onAdd)this.onAdd();return this},updateTransform:P.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=U(a*ha),c=aa(a*ha);L(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",b,", M12=",-c,", M21=",c,", M22=",b,", sizingMethod='auto expand')"].join(""):"none"})},getSpanCorrection:function(a,b,c,d,e){var f=d?U(d*ha):1,g=d?aa(d*ha):0,h=p(this.elemHeight,this.element.offsetHeight),i;this.xCorr=f<0&&-a;this.yCorr=g<0&&-h;i=f*g<0;this.xCorr+=g*b*(i?
	1-c:c);this.yCorr-=f*b*(d?i?c:1-c:1);e&&e!=="left"&&(this.xCorr-=a*c*(f<0?-1:1),d&&(this.yCorr-=h*c*(g<0?-1:1)),L(this.element,{textAlign:e}))},pathToVML:function(a){for(var b=a.length,c=[];b--;)if(ma(a[b]))c[b]=B(a[b]*10)-5;else if(a[b]==="Z")c[b]="x";else if(c[b]=a[b],a.isArc&&(a[b]==="wa"||a[b]==="at"))c[b+5]===c[b+7]&&(c[b+7]+=a[b+7]>a[b+5]?1:-1),c[b+6]===c[b+8]&&(c[b+8]+=a[b+8]>a[b+6]?1:-1);return c.join(" ")||"x"},clip:function(a){var b=this,c;a?(c=a.members,na(c,b),c.push(b),b.destroyClip=
	function(){na(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:lb?"inherit":"rect(auto)"});return b.css(a)},css:P.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Sa(a)},destroy:function(){this.destroyClip&&this.destroyClip();return P.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=C.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=F(a[c-2])-10*b;return a.join(" ")},
	shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,k,j=f.path,l,m,n,q;j&&typeof j.value!=="string"&&(j="x");m=j;if(a){n=p(a.width,3);q=(a.opacity||0.15)/n;for(e=1;e<=3;e++){l=n*2+1-2*e;c&&(m=this.cutOffPath(j.value,l+0.5));k=['<shape isShadow="true" strokeweight="',l,'" filled="false" path="',m,'" coordsize="10 10" style="',f.style.cssText,'" />'];h=$(g.prepVML(k),null,{left:F(i.left)+p(a.offsetX,1),top:F(i.top)+p(a.offsetY,1)});if(c)h.cutOff=l+1;k=['<stroke color="',a.color||
	"black",'" opacity="',q*e,'"/>'];$(g.prepVML(k),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this},updateShadows:Aa,setAttr:function(a,b){lb?this.element[a]=b:this.element.setAttribute(a,b)},classSetter:function(a){this.element.className=a},dashstyleSetter:function(a,b,c){(c.getElementsByTagName("stroke")[0]||$(this.renderer.prepVML(["<stroke/>"]),null,null,c))[b]=a||"solid";this[b]=a},dSetter:function(a,b,c){var d=this.shadows,a=a||[];this.d=
	a.join&&a.join(" ");c.path=a=this.pathToVML(a);if(d)for(c=d.length;c--;)d[c].path=d[c].cutOff?this.cutOffPath(a,d[c].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,c){var d=c.nodeName;if(d==="SPAN")c.style.color=a;else if(d!=="IMG")c.filled=a!=="none",this.setAttr("fillcolor",this.renderer.color(a,c,b,this))},"fill-opacitySetter":function(a,b,c){$(this.renderer.prepVML(["<",b.split("-")[0],' opacity="',a,'"/>']),null,null,c)},opacitySetter:Aa,rotationSetter:function(a,b,c){c=c.style;this[b]=
	c[b]=a;c.left=-B(aa(a*ha)+1)+"px";c.top=B(U(a*ha))+"px"},strokeSetter:function(a,b,c){this.setAttr("strokecolor",this.renderer.color(a,c,b,this))},"stroke-widthSetter":function(a,b,c){c.stroked=!!a;this[b]=a;ma(a)&&(a+="px");this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,c){a==="inherit"&&(a="visible");this.shadows&&o(this.shadows,function(c){c.style[b]=a});c.nodeName==="DIV"&&(a=a==="hidden"?"-999em":0,lb||(c.style[b]=a?"visible":"hidden"),
	b="top");c.style[b]=a},xSetter:function(a,b,c){this[b]=a;b==="x"?b="left":b==="y"&&(b="top");this.updateClipping?(this[b]=a,this.updateClipping()):c.style[b]=a},zIndexSetter:function(a,b,c){c.style[b]=a}};M["stroke-opacitySetter"]=M["fill-opacitySetter"];w.VMLElement=M=oa(P,M);M.prototype.ySetter=M.prototype.widthSetter=M.prototype.heightSetter=M.prototype.xSetter;var Bb={Element:M,isIE8:za.indexOf("MSIE 8.0")>-1,init:function(a,b,c,d){var e;this.alignedObjects=[];d=this.createElement(Ka).css(s(this.getStyle(d),
	{position:"relative"}));e=d.element;a.appendChild(d.element);this.isVML=!0;this.box=e;this.boxWrapper=d;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(b,c,!1);if(!A.namespaces.hcv){A.namespaces.add("hcv","urn:schemas-microsoft-com:vml");try{A.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}catch(f){A.styleSheets[0].cssText+="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}}},
	isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=X(a);return s(e,{members:[],count:0,left:(f?a.x:a)+1,top:(f?a.y:b)+1,width:(f?a.width:c)-1,height:(f?a.height:d)-1,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-(c==="shape"?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+B(a?e:d)+"px,"+B(a?f:b)+"px,"+B(a?b:f)+"px,"+B(a?d:e)+"px)"};!a&&lb&&c==="DIV"&&s(d,{width:b+"px",height:f+"px"});return d},
	updateClipping:function(){o(e.members,function(a){a.element&&a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,k="none";a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern");if(i){var j,l,m=a.linearGradient||a.radialGradient,n,q,v,y,p,x="",a=a.stops,u,r=[],t=function(){h=['<fill colors="'+r.join(",")+'" opacity="',v,'" o:opacity2="',q,'" type="',i,'" ',x,'focus="100%" method="any" />'];$(e.prepVML(h),null,null,b)};n=a[0];u=a[a.length-1];n[0]>0&&a.unshift([0,
	n[1]]);u[0]<1&&a.push([1,u[1]]);o(a,function(a,b){g.test(a[1])?(f=ja(a[1]),j=f.get("rgb"),l=f.get("a")):(j=a[1],l=1);r.push(a[0]*100+"% "+j);b?(v=l,y=j):(q=l,p=j)});if(c==="fill")if(i==="gradient")c=m.x1||m[0]||0,a=m.y1||m[1]||0,n=m.x2||m[2]||0,m=m.y2||m[3]||0,x='angle="'+(90-W.atan((m-a)/(n-c))*180/qa)+'"',t();else{var k=m.r,Y=k*2,s=k*2,w=m.cx,B=m.cy,z=b.radialReference,A,k=function(){z&&(A=d.getBBox(),w+=(z[0]-A.x)/A.width-0.5,B+=(z[1]-A.y)/A.height-0.5,Y*=z[2]/A.width,s*=z[2]/A.height);x='src="'+
	S.global.VMLRadialGradientURL+'" size="'+Y+","+s+'" origin="0.5,0.5" position="'+w+","+B+'" color2="'+p+'" ';t()};d.added?k():d.onAdd=k;k=y}else k=j}else if(g.test(a)&&b.tagName!=="IMG")f=ja(a),d[c+"-opacitySetter"](f.get("a"),c,b),k=f.get("rgb");else{k=b.getElementsByTagName(c);if(k.length)k[0].opacity=1,k[0].type="solid";k=a}return k},prepVML:function(a){var b=this.isIE8,a=a.join("");b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):
	a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","<hcv:");return a},text:Ca.prototype.html,path:function(a){var b={coordsize:"10 10"};Da(a)?b.d=a:X(a)&&s(b,a);return this.createElement("shape").attr(b)},circle:function(a,b,c){var d=this.symbol("circle");if(X(a))c=a.r,b=a.y,a=a.x;d.isCircle=!0;d.r=c;return d.attr({x:a,y:b})},g:function(a){var b;a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a});return this.createElement(Ka).attr(b)},image:function(a,
	b,c,d,e){var f=this.createElement("img").attr({src:a});arguments.length>1&&f.attr({x:b,y:c,width:d,height:e});return f},createElement:function(a){return a==="rect"?this.symbol(a):Ca.prototype.createElement.call(this,a)},invertChild:function(a,b){var c=this,d=b.style,e=a.tagName==="IMG"&&a.style;L(a,{flip:"x",left:F(d.width)-(e?F(e.top):1),top:F(d.height)-(e?F(e.left):1),rotation:-90});o(a.childNodes,function(b){c.invertChild(b,a)})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||
	d,c=e.innerR,d=U(f),i=aa(f),k=U(g),j=aa(g);if(g-f===0)return["x"];f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*k,b+h*j];e.open&&!c&&f.push("e","M",a,b);f.push("at",a-c,b-c,a+c,b+c,a+c*k,b+c*j,a+c*d,b+c*i,"x","e");f.isArc=!0;return f},circle:function(a,b,c,d,e){e&&(c=d=2*e.r);e&&e.isCircle&&(a-=c/2,b-=d/2);return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){return Ca.prototype.symbols[!r(e)||!e.r?"square":"callout"].call(0,a,b,c,d,e)}}};w.VMLRenderer=M=function(){this.init.apply(this,
	arguments)};M.prototype=D(Ca.prototype,Bb);cb=M}Ca.prototype.measureSpanWidth=function(a,b){var c=A.createElement("span"),d;d=A.createTextNode(a);c.appendChild(d);L(c,b);this.box.appendChild(c);d=c.offsetWidth;Sa(c);return d};var Nb;if(ia)w.CanVGRenderer=M=function(){Ga="http://www.w3.org/1999/xhtml"},M.prototype.symbols={},Nb=function(){function a(){var a=b.length,d;for(d=0;d<a;d++)b[d]();b=[]}var b=[];return{push:function(c,d){if(b.length===0){var e=A.getElementsByTagName("head")[0],f=A.createElement("script");
	f.type="text/javascript";f.src=d;f.onload=a;e.appendChild(f)}b.push(c)}}}(),cb=M;Va.prototype={addLabel:function(){var a=this.axis,b=a.options,c=a.chart,d=a.categories,e=a.names,f=this.pos,g=b.labels,h=a.tickPositions,i=f===h[0],k=f===h[h.length-1],e=d?p(d[f],e[f],f):f,d=this.label,h=h.info,j;a.isDatetimeAxis&&h&&(j=b.dateTimeLabelFormats[h.higherRanks[f]||h.unitName]);this.isFirst=i;this.isLast=k;b=a.labelFormatter.call({axis:a,chart:c,isFirst:i,isLast:k,dateTimeLabelFormat:j,value:a.isLog?da(a.lin2log(e)):
	e});r(d)?d&&d.attr({text:b}):(this.labelLength=(this.label=d=r(b)&&g.enabled?c.renderer.text(b,0,0,g.useHTML).css(D(g.style)).add(a.labelGroup):null)&&d.getBBox().width,this.rotation=0)},getLabelSize:function(){return this.label?this.label.getBBox()[this.axis.horiz?"height":"width"]:0},handleOverflow:function(a){var b=this.axis,c=a.x,d=b.chart.chartWidth,e=b.chart.spacing,f=p(b.labelLeft,E(b.pos,e[3])),e=p(b.labelRight,t(b.pos+b.len,d-e[1])),g=this.label,h=this.rotation,i={left:0,center:0.5,right:1}[b.labelAlign],
	k=g.getBBox().width,j=b.getSlotWidth(),l=j,m=1,n,q={};if(h)h<0&&c-i*k<f?n=B(c/U(h*ha)-f):h>0&&c+i*k>e&&(n=B((d-c)/U(h*ha)));else if(d=c+(1-i)*k,c-i*k<f?l=a.x+l*(1-i)-f:d>e&&(l=e-a.x+l*i,m=-1),l=E(j,l),l<j&&b.labelAlign==="center"&&(a.x+=m*(j-l-i*(j-E(k,l)))),k>l||b.autoRotation&&g.styles.width)n=l;if(n){q.width=n;if(!b.options.labels.style.textOverflow)q.textOverflow="ellipsis";g.css(q)}},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+
	c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,b,c,d,e,f,g,h){var i=this.axis,k=i.transA,j=i.reversed,l=i.staggerLines,m=i.tickRotCorr||{x:0,y:0},n=e.y;r(n)||(n=i.side===0?c.rotation?-8:-c.getBBox().height:i.side===2?m.y+8:U(c.rotation*ha)*(m.y-c.getBBox(!1,0).height/2));a=a+e.x+m.x-(f&&d?f*k*(j?-1:1):0);b=b+n-(f&&!d?f*k*(j?
	1:-1):0);l&&(c=g/(h||1)%l,i.opposite&&(c=l-c-1),b+=c*(i.labelOffset/l));return{x:a,y:B(b)}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine(["M",a,b,"L",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,b,c){var d=this.axis,e=d.options,f=d.chart.renderer,g=d.horiz,h=this.type,i=this.label,k=this.pos,j=e.labels,l=this.gridLine,m=h?h+"Grid":"grid",n=h?h+"Tick":"tick",q=e[m+"LineWidth"],v=e[m+"LineColor"],y=e[m+"LineDashStyle"],m=d.tickSize(n),n=e[n+"Color"],o=this.mark,x=j.step,u=!0,r=d.tickmarkOffset,
	t=this.getPosition(g,k,r,b),Y=t.x,t=t.y,s=g&&Y===d.pos+d.len||!g&&t===d.pos?-1:1,c=p(c,1);this.isActive=!0;if(q){k=d.getPlotLinePath(k+r,q*s,b,!0);if(l===z){l={stroke:v,"stroke-width":q};if(y)l.dashstyle=y;if(!h)l.zIndex=1;if(b)l.opacity=0;this.gridLine=l=q?f.path(k).attr(l).add(d.gridGroup):null}if(!b&&l&&k)l[this.isNew?"attr":"animate"]({d:k,opacity:c})}if(m)d.opposite&&(m[0]=-m[0]),h=this.getMarkPath(Y,t,m[0],m[1]*s,g,f),o?o.animate({d:h,opacity:c}):this.mark=f.path(h).attr({stroke:n,"stroke-width":m[1],
	opacity:c}).add(d.axisGroup);if(i&&!isNaN(Y))i.xy=t=this.getLabelPosition(Y,t,i,g,j,r,a,x),this.isFirst&&!this.isLast&&!p(e.showFirstLabel,1)||this.isLast&&!this.isFirst&&!p(e.showLastLabel,1)?u=!1:g&&!d.isRadial&&!j.step&&!j.rotation&&!b&&c!==0&&this.handleOverflow(t),x&&a%x&&(u=!1),u&&!isNaN(t.y)?(t.opacity=c,i[this.isNew?"attr":"animate"](t),this.isNew=!1):i.attr("y",-9999)},destroy:function(){Ra(this,this.axis)}};w.PlotLineOrBand=function(a,b){this.axis=a;if(b)this.options=b,this.id=b.id};w.PlotLineOrBand.prototype=
	{render:function(){var a=this,b=a.axis,c=b.horiz,d=a.options,e=d.label,f=a.label,g=d.width,h=d.to,i=d.from,k=r(i)&&r(h),j=d.value,l=d.dashStyle,m=a.svgElem,n=[],q,v=d.color,y=p(d.zIndex,0),o=d.events,x={},u=b.chart.renderer,n=b.log2lin;b.isLog&&(i=n(i),h=n(h),j=n(j));if(g){if(n=b.getPlotLinePath(j,g),x={stroke:v,"stroke-width":g},l)x.dashstyle=l}else if(k){n=b.getPlotBandPath(i,h,d);if(v)x.fill=v;if(d.borderWidth)x.stroke=d.borderColor,x["stroke-width"]=d.borderWidth}else return;x.zIndex=y;if(m)if(n)m.show(),
	m.animate({d:n});else{if(m.hide(),f)a.label=f=f.destroy()}else if(n&&n.length&&(a.svgElem=m=u.path(n).attr(x).add(),o))for(q in d=function(b){m.on(b,function(c){o[b].apply(a,[c])})},o)d(q);e&&r(e.text)&&n&&n.length&&b.width>0&&b.height>0&&!n.flat?(e=D({align:c&&k&&"center",x:c?!k&&4:10,verticalAlign:!c&&k&&"middle",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},e),this.renderLabel(e,n,k,y)):f&&f.hide();return a},renderLabel:function(a,b,c,d){var e=this.label,f=this.axis.chart.renderer;if(!e)e={align:a.textAlign||
	a.align,rotation:a.rotation},e.zIndex=d,this.label=e=f.text(a.text,0,0,a.useHTML).attr(e).css(a.style).add();d=[b[1],b[4],c?b[6]:b[1]];b=[b[2],b[5],c?b[7]:b[2]];c=Qa(d);f=Qa(b);e.align(a,!1,{x:c,y:f,width:Fa(d)-c,height:Fa(b)-f});e.show()},destroy:function(){na(this.axis.plotLinesAndBands,this);delete this.axis;Ra(this)}};var fa=w.Axis=function(){this.init.apply(this,arguments)};fa.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",
	day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#D8D8D8",labels:{enabled:!0,style:{color:"#606060",cursor:"default",fontSize:"11px"},x:0},lineColor:"#C0D0E0",lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",
	style:{color:"#707070"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return w.numberFormat(this.total,-1)},style:D(ba.line.dataLabels.style,{color:"#000000"})}},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],
	x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},init:function(a,b){var c=b.isX;this.chart=a;this.horiz=a.inverted?!c:c;this.coll=(this.isXAxis=c)?"xAxis":"yAxis";this.opposite=b.opposite;this.side=b.side||(this.horiz?this.opposite?0:2:this.opposite?1:3);this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.reversed=d.reversed;this.visible=d.visible!==
	!1;this.zoomEnabled=d.zoomEnabled!==!1;this.categories=d.categories||e==="category";this.names=this.names||[];this.isLog=e==="logarithmic";this.isDatetimeAxis=e==="datetime";this.isLinked=r(d.linkedTo);this.ticks={};this.labelEdge=[];this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.stacksTouched=0;this.min=this.max=null;this.crosshair=
	p(d.crosshair,ta(a.options.tooltip.crosshairs)[c?0:1],!1);var f,d=this.options.events;ra(this,a.axes)===-1&&(c&&!this.isColorAxis?a.axes.splice(a.xAxis.length,0,this):a.axes.push(this),a[this.coll].push(this));this.series=this.series||[];if(a.inverted&&c&&this.reversed===z)this.reversed=!0;this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)N(this,f,d[f]);if(this.isLog)this.val2lin=this.log2lin,this.lin2val=this.lin2log},setOptions:function(a){this.options=D(this.defaultOptions,
	this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],D(S[this.coll],a))},defaultLabelFormatter:function(){var a=this.axis,b=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=S.lang.numericSymbols,f=e&&e.length,g,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ja(h,this);else if(c)g=b;else if(d)g=Pa(d,b);else if(f&&a>=1E3)for(;f--&&g===z;)c=Math.pow(1E3,f+1),a>=c&&b*10%
	c===0&&e[f]!==null&&(g=w.numberFormat(b/c,-1)+e[f]);g===z&&(g=Q(b)>=1E4?w.numberFormat(b,-1):w.numberFormat(b,-1,z,""));return g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();o(a.series,function(c){if(c.visible||!b.options.chart.ignoreHiddenSeries){var d=c.options,e=d.threshold,f;a.hasVisibleSeries=!0;a.isLog&&e<=0&&(e=null);if(a.isXAxis){if(d=c.xData,d.length)a.dataMin=E(p(a.dataMin,
	d[0]),Qa(d)),a.dataMax=t(p(a.dataMax,d[0]),Fa(d))}else{c.getExtremes();f=c.dataMax;c=c.dataMin;if(r(c)&&r(f))a.dataMin=E(p(a.dataMin,c),c),a.dataMax=t(p(a.dataMax,f),f);if(r(e))a.threshold=e;if(!d.softThreshold||a.isLog)a.softThreshold=!1}}})},translate:function(a,b,c,d,e,f){var g=this.linkedParent||this,h=1,i=0,k=d?g.oldTransA:g.transA,d=d?g.oldMin:g.min,j=g.minPixelPadding,e=(g.isOrdinal||g.isBroken||g.isLog&&e)&&g.lin2val;if(!k)k=g.transA;if(c)h*=-1,i=g.len;g.reversed&&(h*=-1,i-=h*(g.sector||g.len));
	b?(a=a*h+i,a-=j,a=a/k+d,e&&(a=g.lin2val(a))):(e&&(a=g.val2lin(a)),f==="between"&&(f=0.5),a=h*(a-d)*k+i+h*j+(ma(f)?k*f*g.pointRange:0));return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,e){var f=this.chart,g=this.left,h=this.top,i,k,j=c&&f.oldChartHeight||f.chartHeight,l=c&&f.oldChartWidth||f.chartWidth,m;i=this.transB;var n=function(a,
	b,c){if(a<b||a>c)d?a=E(t(b,a),c):m=!0;return a},e=p(e,this.translate(a,null,null,c)),a=c=B(e+i);i=k=B(j-e-i);isNaN(e)?m=!0:this.horiz?(i=h,k=j-this.bottom,a=c=n(a,g,g+this.width)):(a=g,c=l-this.right,i=k=n(i,h,h+this.height));return m&&!d?null:f.renderer.crispLine(["M",a,i,"L",c,k],b||1)},getLinearTickPositions:function(a,b,c){var d,e=da(T(b/a)*a),f=da(ua(c/a)*a),g=[];if(b===c&&ma(b))return[b];for(b=e;b<=f;){g.push(b);b=da(b+a);if(b===d)break;d=b}return g},getMinorTickPositions:function(){var a=this.options,
	b=this.tickPositions,c=this.minorTickInterval,d=[],e,f=this.pointRangePadding||0;e=this.min-f;var f=this.max+f,g=f-e;if(g&&g/c<this.len/3)if(this.isLog){f=b.length;for(e=1;e<f;e++)d=d.concat(this.getLogTickPositions(c,b[e-1],b[e],!0))}else if(this.isDatetimeAxis&&a.minorTickInterval==="auto")d=d.concat(this.getTimeTicks(this.normalizeTimeTickInterval(c),e,f,a.startOfWeek));else for(b=e+(b[0]-e)%c;b<=f;b+=c)d.push(b);d.length!==0&&this.trimTicks(d,a.startOnTick,a.endOnTick);return d},adjustForMinRange:function(){var a=
	this.options,b=this.min,c=this.max,d,e=this.dataMax-this.dataMin>=this.minRange,f,g,h,i,k,j;if(this.isXAxis&&this.minRange===z&&!this.isLog)r(a.min)||r(a.max)?this.minRange=null:(o(this.series,function(a){i=a.xData;for(g=k=a.xIncrement?1:i.length-1;g>0;g--)if(h=i[g]-i[g-1],f===z||h<f)f=h}),this.minRange=E(f*5,this.dataMax-this.dataMin));if(c-b<this.minRange){j=this.minRange;d=(j-c+b)/2;d=[b-d,p(a.min,b-d)];if(e)d[2]=this.dataMin;b=Fa(d);c=[b+j,p(a.max,b+j)];if(e)c[2]=this.dataMax;c=Qa(c);c-b<j&&(d[0]=
	c-j,d[1]=p(a.min,c-j),b=Fa(d))}this.min=b;this.max=c},getClosest:function(){var a;o(this.series,function(b){var c=b.closestPointRange;!b.noSharedTooltip&&r(c)&&(a=r(a)?E(a,c):c)});return a},setAxisTranslation:function(a){var b=this,c=b.max-b.min,d=b.axisPointRange||0,e,f=0,g=0,h=b.linkedParent,i=!!b.categories,k=b.transA,j=b.isXAxis;if(j||i||d)if(h?(f=h.minPointOffset,g=h.pointRangePadding):(e=b.getClosest(),o(b.series,function(a){var c=i?1:j?p(a.options.pointRange,e,0):b.axisPointRange||0,a=a.options.pointPlacement;
	d=t(d,c);b.single||(f=t(f,xa(a)?0:c/2),g=t(g,a==="on"?0:c))})),h=b.ordinalSlope&&e?b.ordinalSlope/e:1,b.minPointOffset=f*=h,b.pointRangePadding=g*=h,b.pointRange=E(d,c),j)b.closestPointRange=e;if(a)b.oldTransA=k;b.translationSlope=b.transA=k=b.len/(c+g||1);b.transB=b.horiz?b.left:b.bottom;b.minPixelPadding=k*f},minFromRange:function(){return this.max-this.range},setTickInterval:function(a){var b=this,c=b.chart,d=b.options,e=b.isLog,f=b.log2lin,g=b.isDatetimeAxis,h=b.isXAxis,i=b.isLinked,k=d.maxPadding,
	j=d.minPadding,l=d.tickInterval,m=d.tickPixelInterval,n=b.categories,q=b.threshold,v=b.softThreshold,y,sa,x,u;!g&&!n&&!i&&this.getTickAmount();x=p(b.userMin,d.min);u=p(b.userMax,d.max);i?(b.linkedParent=c[b.coll][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=p(c.min,c.dataMin),b.max=p(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&Z(11,1)):(!v&&r(q)&&(b.dataMin>=q?(y=q,j=0):b.dataMax<=q&&(sa=q,k=0)),b.min=p(x,y,b.dataMin),b.max=p(u,sa,b.dataMax));if(e)!a&&E(b.min,p(b.dataMin,b.min))<=0&&
	Z(10,1),b.min=da(f(b.min),15),b.max=da(f(b.max),15);if(b.range&&r(b.max))b.userMin=b.min=x=t(b.min,b.minFromRange()),b.userMax=u=b.max,b.range=null;b.beforePadding&&b.beforePadding();b.adjustForMinRange();if(!n&&!b.axisPointRange&&!b.usePercentage&&!i&&r(b.min)&&r(b.max)&&(f=b.max-b.min))!r(x)&&j&&(b.min-=f*j),!r(u)&&k&&(b.max+=f*k);if(ma(d.floor))b.min=t(b.min,d.floor);if(ma(d.ceiling))b.max=E(b.max,d.ceiling);if(v&&r(b.dataMin))if(q=q||0,!r(x)&&b.min<q&&b.dataMin>=q)b.min=q;else if(!r(u)&&b.max>
	q&&b.dataMax<=q)b.max=q;b.tickInterval=b.min===b.max||b.min===void 0||b.max===void 0?1:i&&!l&&m===b.linkedParent.options.tickPixelInterval?l=b.linkedParent.tickInterval:p(l,this.tickAmount?(b.max-b.min)/t(this.tickAmount-1,1):void 0,n?1:(b.max-b.min)*m/t(b.len,m));h&&!a&&o(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();if(b.postProcessTickInterval)b.tickInterval=b.postProcessTickInterval(b.tickInterval);
	if(b.pointRange&&!l)b.tickInterval=t(b.pointRange,b.tickInterval);a=p(d.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);if(!l&&b.tickInterval<a)b.tickInterval=a;if(!g&&!e&&!l)b.tickInterval=tb(b.tickInterval,null,sb(b.tickInterval),p(d.allowDecimals,!(b.tickInterval>0.5&&b.tickInterval<5&&b.max>1E3&&b.max<9999)),!!this.tickAmount);if(!this.tickAmount&&this.len)b.tickInterval=b.unsquish();this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions,d=a.tickPositioner,
	e=a.startOnTick,f=a.endOnTick,g;this.tickmarkOffset=this.categories&&a.tickmarkPlacement==="between"&&this.tickInterval===1?0.5:0;this.minorTickInterval=a.minorTickInterval==="auto"&&this.tickInterval?this.tickInterval/5:a.minorTickInterval;this.tickPositions=b=c&&c.slice();if(!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,
	this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b=[b[0],b.pop()]),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max]))))this.tickPositions=b=d;if(!this.isLinked)this.trimTicks(b,e,f),this.min===this.max&&r(this.min)&&!this.tickAmount&&(g=!0,this.min-=0.5,this.max+=0.5),this.single=g,!c&&!d&&this.adjustTickAmount()},trimTicks:function(a,b,c){var d=a[0],e=a[a.length-1],f=this.minPointOffset||0;if(b)this.min=d;else for(;this.min-f>a[0];)a.shift();
	if(c)this.max=e;else for(;this.max+f<a[a.length-1];)a.pop();a.length===0&&r(d)&&a.push((e+d)/2)},alignToOthers:function(){var a={},b,c=this.options;this.chart.options.chart.alignTicks!==!1&&c.alignTicks!==!1&&o(this.chart[this.coll],function(c){var e=c.options,e=[c.horiz?e.left:e.top,e.width,e.height,e.pane].join(",");c.series.length&&(a[e]?b=!0:a[e]=1)});return b},getTickAmount:function(){var a=this.options,b=a.tickAmount,c=a.tickPixelInterval;!r(a.tickInterval)&&this.len<c&&!this.isRadial&&!this.isLog&&
	a.startOnTick&&a.endOnTick&&(b=2);!b&&this.alignToOthers()&&(b=ua(this.len/c)+1);if(b<4)this.finalTickAmt=b,b=5;this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,e=b&&b.length;if(e<c){for(;b.length<c;)b.push(da(b[b.length-1]+a));this.transA*=(e-1)/(c-1);this.max=b[b.length-1]}else e>c&&(this.tickInterval*=2,this.setTickPositions());if(r(d)){for(a=c=b.length;a--;)(d===3&&a%2===1||d<=2&&a>0&&a<c-1)&&b.splice(a,1);this.finalTickAmt=
	z}},setScale:function(){var a,b;this.oldMin=this.min;this.oldMax=this.max;this.oldAxisLength=this.len;this.setAxisSize();b=this.len!==this.oldAxisLength;o(this.series,function(b){if(b.isDirtyData||b.isDirty||b.xAxis.isDirty)a=!0});if(b||a||this.isLinked||this.forceRedraw||this.userMin!==this.oldUserMin||this.userMax!==this.oldUserMax||this.alignToOthers()){if(this.resetStacks&&this.resetStacks(),this.forceRedraw=!1,this.getSeriesExtremes(),this.setTickInterval(),this.oldUserMin=this.userMin,this.oldUserMax=
	this.userMax,!this.isDirty)this.isDirty=b||this.min!==this.oldMin||this.max!==this.oldMax}else this.cleanStacks&&this.cleanStacks()},setExtremes:function(a,b,c,d,e){var f=this,g=f.chart,c=p(c,!0);o(f.series,function(a){delete a.kdTree});e=s(e,{min:a,max:b});H(f,"setExtremes",e,function(){f.userMin=a;f.userMax=b;f.eventArgs=e;c&&g.redraw(d)})},zoom:function(a,b){var c=this.dataMin,d=this.dataMax,e=this.options,f=E(c,p(e.min,c)),e=t(d,p(e.max,d));this.allowZoomOutside||(r(c)&&a<=f&&(a=f),r(d)&&b>=e&&
	(b=e));this.displayBtn=a!==z||b!==z;this.setExtremes(a,b,!1,z,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=this.horiz,e=p(b.width,a.plotWidth-c+(b.offsetRight||0)),f=p(b.height,a.plotHeight),g=p(b.top,a.plotTop),b=p(b.left,a.plotLeft+c),c=/%$/;c.test(f)&&(f=Math.round(parseFloat(f)/100*a.plotHeight));c.test(g)&&(g=Math.round(parseFloat(g)/100*a.plotHeight+a.plotTop));this.left=b;this.top=g;this.width=e;this.height=f;this.bottom=a.chartHeight-
	f-g;this.right=a.chartWidth-e-b;this.len=t(d?e:f,0);this.pos=d?b:g},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?da(b(this.min)):this.min,max:a?da(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=this.lin2log,d=b?c(this.min):this.min,b=b?c(this.max):this.max;a===null?a=b<0?b:d:d>a?a=d:b<a&&(a=b);return this.translate(a,0,1,0,1)},autoLabelAlign:function(a){a=(p(a,0)-this.side*
	90+720)%360;return a>15&&a<165?"right":a>195&&a<345?"left":"center"},tickSize:function(a){var b=this.options,c=b[a+"Length"],d=p(b[a+"Width"],a==="tick"&&this.isXAxis?1:0);if(d&&c)return b[a+"Position"]==="inside"&&(c=-c),[c,d]},labelMetrics:function(){return this.chart.renderer.fontMetrics(this.options.labels.style.fontSize,this.ticks[0]&&this.ticks[0].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,e=this.len/(((this.categories?1:0)+this.max-this.min)/
	c),f,g=a.rotation,h=this.labelMetrics(),i,k=Number.MAX_VALUE,j,l=function(a){a/=e||1;a=a>1?ua(a):1;return a*c};b?(j=!a.staggerLines&&!a.step&&(r(g)?[g]:e<p(a.autoRotationLimit,80)&&a.autoRotation))&&o(j,function(a){var b;if(a===g||a&&a>=-90&&a<=90)i=l(Q(h.h/aa(ha*a))),b=i+Q(a/360),b<k&&(k=b,f=a,d=i)}):a.step||(d=l(h.h));this.autoRotation=j;this.labelRotation=p(f,g);return d},getSlotWidth:function(){var a=this.chart,b=this.horiz,c=this.options.labels,d=Math.max(this.tickPositions.length-(this.categories?
	0:1),1),e=a.margin[3];return b&&(c.step||0)<2&&!c.rotation&&(this.staggerLines||1)*a.plotWidth/d||!b&&(e&&e-a.spacing[3]||a.chartWidth*0.33)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,e=this.options.labels,f=this.horiz,g=this.getSlotWidth(),h=t(1,B(g-2*(e.padding||5))),i={},k=this.labelMetrics(),j=e.style.textOverflow,l,m=0,n,q;if(!xa(e.rotation))i.rotation=e.rotation||0;if(this.autoRotation)o(c,function(a){if((a=d[a])&&a.labelLength>m)m=a.labelLength}),
	m>h&&m>k.h?i.rotation=this.labelRotation:this.labelRotation=0;else if(g&&(l={width:h+"px"},!j)){l.textOverflow="clip";for(n=c.length;!f&&n--;)if(q=c[n],h=d[q].label)if(h.styles.textOverflow==="ellipsis"?h.css({textOverflow:"clip"}):d[q].labelLength>g&&h.css({width:g+"px"}),h.getBBox().height>this.len/c.length-(k.h-k.f))h.specCss={textOverflow:"ellipsis"}}if(i.rotation&&(l={width:(m>a.chartHeight*0.5?a.chartHeight*0.33:a.chartHeight)+"px"},!j))l.textOverflow="ellipsis";if(this.labelAlign=e.align||
	this.autoLabelAlign(this.labelRotation))i.align=this.labelAlign;o(c,function(a){var b=(a=d[a])&&a.label;if(b)b.attr(i),l&&b.css(D(l,b.specCss)),delete b.specCss,a.rotation=i.rotation});this.tickRotCorr=b.rotCorr(k.b,this.labelRotation||0,this.side!==0)},hasData:function(){return this.hasVisibleSeries||r(this.min)&&r(this.max)&&!!this.tickPositions},getOffset:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,k,j,l=0,
	m,n=0,q=d.title,v=d.labels,y=0,sa=a.opposite,x=b.axisOffset,b=b.clipOffset,u=[-1,1,1,-1][h],s,z=a.axisParent,Y=this.tickSize("tick");k=a.hasData();a.showAxis=j=k||p(d.showEmpty,!0);a.staggerLines=a.horiz&&v.staggerLines;if(!a.axisGroup)a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(z),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(z),a.labelGroup=c.g("axis-labels").attr({zIndex:v.zIndex||7}).addClass("highcharts-"+a.coll.toLowerCase()+"-labels").add(z);if(k||a.isLinked){if(o(e,
	function(b){f[b]?f[b].addLabel():f[b]=new Va(a,b)}),a.renderUnsquish(),v.reserveSpace!==!1&&(h===0||h===2||{1:"left",3:"right"}[h]===a.labelAlign||a.labelAlign==="center")&&o(e,function(a){y=t(f[a].getLabelSize(),y)}),a.staggerLines)y*=a.staggerLines,a.labelOffset=y*(a.opposite?-1:1)}else for(s in f)f[s].destroy(),delete f[s];if(q&&q.text&&q.enabled!==!1){if(!a.axisTitle)a.axisTitle=c.text(q.text,0,0,q.useHTML).attr({zIndex:7,rotation:q.rotation||0,align:q.textAlign||{low:sa?"right":"left",middle:"center",
	high:sa?"left":"right"}[q.align]}).addClass("highcharts-"+this.coll.toLowerCase()+"-title").css(q.style).add(a.axisGroup),a.axisTitle.isNew=!0;if(j)l=a.axisTitle.getBBox()[g?"height":"width"],m=q.offset,n=r(m)?0:p(q.margin,g?5:10);a.axisTitle[j?"show":"hide"](!0)}a.offset=u*p(d.offset,x[h]);a.tickRotCorr=a.tickRotCorr||{x:0,y:0};c=h===0?-a.labelMetrics().h:h===2?a.tickRotCorr.y:0;n=Math.abs(y)+n;y&&(n-=c,n+=u*(g?p(v.y,a.tickRotCorr.y+u*8):v.x));a.axisTitleMargin=p(m,n);x[h]=t(x[h],a.axisTitleMargin+
	l+u*a.offset,n,k&&e.length&&Y?Y[0]:0);d=d.offset?0:T(d.lineWidth/2)*2;b[i]=t(b[i],d)},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d,d=b.chartHeight-this.bottom-(c?this.height:0)+d;c&&(a*=-1);return b.renderer.crispLine(["M",e?this.left:f,e?d:this.top,"L",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,
	h=this.offset,i=e.x||0,k=e.y||0,j=F(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(this.side===2?j:0);return{x:a?d+i:b+(g?this.width:0)+h+i,y:a?b+k-(g?this.height:0)+h:d+k}},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.isLog,f=a.lin2log,g=a.isLinked,h=a.tickPositions,i=a.axisTitle,k=a.ticks,j=a.minorTicks,l=a.alternateBands,m=d.stackLabels,n=d.alternateGridColor,q=a.tickmarkOffset,v=
	d.lineWidth,p,sa=b.hasRendered&&r(a.oldMin)&&!isNaN(a.oldMin),x=a.showAxis,u=$a(c.globalAnimation),t,s;a.labelEdge.length=0;a.overlap=!1;o([k,j,l],function(a){for(var b in a)a[b].isActive=!1});if(a.hasData()||g){a.minorTickInterval&&!a.categories&&o(a.getMinorTickPositions(),function(b){j[b]||(j[b]=new Va(a,b,"minor"));sa&&j[b].isNew&&j[b].render(null,!0);j[b].render(null,!1,1)});if(h.length&&(o(h,function(b,c){if(!g||b>=a.min&&b<=a.max)k[b]||(k[b]=new Va(a,b)),sa&&k[b].isNew&&k[b].render(c,!0,0.1),
	k[b].render(c)}),q&&(a.min===0||a.single)))k[-1]||(k[-1]=new Va(a,-1,null,!0)),k[-1].render(-1);n&&o(h,function(c,d){s=h[d+1]!==z?h[d+1]+q:a.max-q;if(d%2===0&&c<a.max&&s<=a.max+(b.polar?-q:q))l[c]||(l[c]=new w.PlotLineOrBand(a)),t=c+q,l[c].options={from:e?f(t):t,to:e?f(s):s,color:n},l[c].render(),l[c].isActive=!0});if(!a._addedPlotLB)o((d.plotLines||[]).concat(d.plotBands||[]),function(b){a.addPlotBandOrLine(b)}),a._addedPlotLB=!0}o([k,j,l],function(a){var c,d,e=[],f=u.duration;for(c in a)if(!a[c].isActive)a[c].render(c,
	!1,0),a[c].isActive=!1,e.push(c);Oa(function(){for(d=e.length;d--;)a[e[d]]&&!a[e[d]].isActive&&(a[e[d]].destroy(),delete a[e[d]])},a===l||!b.hasRendered||!f?0:f)});if(v)p=a.getLinePath(v),a.axisLine?a.axisLine.animate({d:p}):a.axisLine=c.path(p).attr({stroke:d.lineColor,"stroke-width":v,zIndex:7}).add(a.axisGroup),a.axisLine[x?"show":"hide"](!0);if(i&&x)i[i.isNew?"attr":"animate"](a.getTitlePosition()),i.isNew=!1;m&&m.enabled&&a.renderStackTotals();a.isDirty=!1},redraw:function(){this.visible&&(this.render(),
	o(this.plotLinesAndBands,function(a){a.render()}));o(this.series,function(a){a.isDirty=!0})},destroy:function(a){var b=this,c=b.stacks,d,e=b.plotLinesAndBands;a||V(b);for(d in c)Ra(c[d]),c[d]=null;o([b.ticks,b.minorTicks,b.alternateBands],function(a){Ra(a)});for(a=e.length;a--;)e[a].destroy();o("stackTotalGroup,axisLine,axisTitle,axisGroup,cross,gridGroup,labelGroup".split(","),function(a){b[a]&&(b[a]=b[a].destroy())});this.cross&&this.cross.destroy()},drawCrosshair:function(a,b){var c,d=this.crosshair,
	e,f;if(!this.crosshair||(r(b)||!p(d.snap,!0))===!1)this.hideCrosshair();else if(p(d.snap,!0)?r(b)&&(c=this.isXAxis?b.plotX:this.len-b.plotY):c=this.horiz?a.chartX-this.pos:this.len-a.chartY+this.pos,c=this.isRadial?this.getPlotLinePath(this.isXAxis?b.x:p(b.stackY,b.y))||null:this.getPlotLinePath(null,null,null,null,c)||null,c===null)this.hideCrosshair();else if(e=this.categories&&!this.isRadial,f=p(d.width,e?this.transA:1),this.cross)this.cross.attr({d:c,visibility:"visible","stroke-width":f});else{e=
	{"stroke-width":f,stroke:d.color||(e?"rgba(155,200,255,0.2)":"#C0C0C0"),zIndex:p(d.zIndex,2)};if(d.dashStyle)e.dashstyle=d.dashStyle;this.cross=this.chart.renderer.path(c).attr(e).add()}},hideCrosshair:function(){this.cross&&this.cross.hide()}};s(fa.prototype,{getPlotBandPath:function(a,b){var c=this.getPlotLinePath(b,null,null,!0),d=this.getPlotLinePath(a,null,null,!0);d&&c?(d.flat=d.toString()===c.toString(),d.push(c[4],c[5],c[1],c[2])):d=null;return d},addPlotBand:function(a){return this.addPlotBandOrLine(a,
	"plotBands")},addPlotLine:function(a){return this.addPlotBandOrLine(a,"plotLines")},addPlotBandOrLine:function(a,b){var c=(new w.PlotLineOrBand(this,a)).render(),d=this.userOptions;c&&(b&&(d[b]=d[b]||[],d[b].push(a)),this.plotLinesAndBands.push(c));return c},removePlotBandOrLine:function(a){for(var b=this.plotLinesAndBands,c=this.options,d=this.userOptions,e=b.length;e--;)b[e].id===a&&b[e].destroy();o([c.plotLines||[],d.plotLines||[],c.plotBands||[],d.plotBands||[]],function(b){for(e=b.length;e--;)b[e].id===
	a&&na(b,b[e])})}});fa.prototype.getTimeTicks=function(a,b,c,d){var e=[],f={},g=S.global.useUTC,h,i=new pa(b-Ya(b)),k=a.unitRange,j=a.count;if(r(b)){i[Fb](k>=G.second?0:j*T(i.getMilliseconds()/j));if(k>=G.second)i[Gb](k>=G.minute?0:j*T(i.getSeconds()/j));if(k>=G.minute)i[Hb](k>=G.hour?0:j*T(i[ub]()/j));if(k>=G.hour)i[Ib](k>=G.day?0:j*T(i[vb]()/j));if(k>=G.day)i[kb](k>=G.month?1:j*T(i[Ua]()/j));k>=G.month&&(i[xb](k>=G.year?0:j*T(i[ab]()/j)),h=i[bb]());k>=G.year&&(h-=h%j,i[yb](h));if(k===G.week)i[kb](i[Ua]()-
	i[wb]()+p(d,1));b=1;if(rb||Za)i=i.getTime(),i=new pa(i+Ya(i));h=i[bb]();for(var d=i.getTime(),l=i[ab](),m=i[Ua](),n=!g||!!Za,q=(G.day+(g?Ya(i):i.getTimezoneOffset()*6E4))%G.day;d<c;)e.push(d),k===G.year?d=jb(h+b*j,0):k===G.month?d=jb(h,l+b*j):n&&(k===G.day||k===G.week)?d=jb(h,l,m+b*j*(k===G.day?1:7)):d+=k*j,b++;e.push(d);o(Ma(e,function(a){return k<=G.hour&&a%G.day===q}),function(a){f[a]="day"})}e.info=s(a,{higherRanks:f,totalRange:k*j});return e};fa.prototype.normalizeTimeTickInterval=function(a,
	b){var c=b||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]],d=c[c.length-1],e=G[d[0]],f=d[1],g;for(g=0;g<c.length;g++)if(d=c[g],e=G[d[0]],f=d[1],c[g+1]&&a<=(e*f[f.length-1]+G[c[g+1][0]])/2)break;e===G.year&&a<5*e&&(f=[1,2,5]);c=tb(a/e,f,d[0]==="year"?t(sb(a/e),1):1);return{unitRange:e,count:c,unitName:d[0]}};fa.prototype.getLogTickPositions=function(a,
	b,c,d){var e=this.options,f=this.len,g=this.lin2log,h=this.log2lin,i=[];if(!d)this._minorAutoInterval=null;if(a>=0.5)a=B(a),i=this.getLinearTickPositions(a,b,c);else if(a>=0.08)for(var f=T(b),k,j,l,m,n,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];f<c+1&&!n;f++){j=e.length;for(k=0;k<j&&!n;k++)l=h(g(f)*e[k]),l>b&&(!d||m<=c)&&m!==z&&i.push(m),m>c&&(n=!0),m=l}else if(b=g(b),c=g(c),a=e[d?"minorTickInterval":"tickInterval"],a=p(a==="auto"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/
	(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=tb(a,null,sb(a)),i=Ba(this.getLinearTickPositions(a,b,c),h),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return i};fa.prototype.log2lin=function(a){return W.log(a)/W.LN10};fa.prototype.lin2log=function(a){return W.pow(10,a)};var Ob=w.Tooltip=function(){this.init.apply(this,arguments)};Ob.prototype={init:function(a,b){var c=b.borderWidth,d=b.style,e=F(d.padding);this.chart=a;this.options=b;this.crosshairs=[];this.now={x:0,y:0};this.isHidden=
	!0;this.label=a.renderer.label("",0,0,b.shape||"callout",null,null,b.useHTML,null,"tooltip").attr({padding:e,fill:b.backgroundColor,"stroke-width":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).add().attr({y:-9999});ia||this.label.shadow(b.shadow);this.shared=b.shared},destroy:function(){if(this.label)this.label=this.label.destroy();clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==!1&&!e.isHidden&&(Q(a-f.x)>1||
	Q(b-f.y)>1),h=e.followPointer||e.len>1;s(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:h?z:g?(2*f.anchorX+c)/3:c,anchorY:h?z:g?(f.anchorY+d)/2:d});e.label.attr(f);if(g)clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(a){var b=this;clearTimeout(this.hideTimer);a=p(a,this.options.hideDelay,500);if(!this.isHidden)this.hideTimer=Oa(function(){b.label[a?"fadeOut":"hide"]();b.isHidden=!0},a)},getAnchor:function(a,b){var c,d=this.chart,e=d.inverted,
	f=d.plotTop,g=d.plotLeft,h=0,i=0,k,j,a=ta(a);c=a[0].tooltipPos;this.followPointer&&b&&(b.chartX===z&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]);c||(o(a,function(a){k=a.series.yAxis;j=a.series.xAxis;h+=a.plotX+(!e&&j?j.left-g:0);i+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&k?k.top-f:0)}),h/=a.length,i/=a.length,c=[e?d.plotWidth-i:h,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-h:i]);return Ba(c,B)},getPosition:function(a,b,c){var d=this.chart,e=this.distance,
	f={},g=c.h||0,h,i=["y",d.chartHeight,b,c.plotY+d.plotTop,d.plotTop,d.plotTop+d.plotHeight],k=["x",d.chartWidth,a,c.plotX+d.plotLeft,d.plotLeft,d.plotLeft+d.plotWidth],j=!this.followPointer&&p(c.ttBelow,!d.inverted===!!c.negative),l=function(a,b,c,d,h,i){var k=c<d-e,m=d+e+c<b,l=d-e-c;d+=e;if(j&&m)f[a]=d;else if(!j&&k)f[a]=l;else if(k)f[a]=E(i-c,l-g<0?l:l-g);else if(m)f[a]=t(h,d+g+c>b?d:d+g);else return!1},m=function(a,b,c,d){var g;d<e||d>b-e?g=!1:f[a]=d<c/2?1:d>b-c/2?b-c-2:d-c/2;return g},n=function(a){var b=
	i;i=k;k=b;h=a},q=function(){l.apply(0,i)!==!1?m.apply(0,k)===!1&&!h&&(n(!0),q()):h?f.x=f.y=0:(n(!0),q())};(d.inverted||this.len>1)&&n();q();return f},defaultFormatter:function(a){var b=this.points||ta(this),c;c=[a.tooltipFooterHeaderFormatter(b[0])];c=c.concat(a.bodyFormatter(b));c.push(a.tooltipFooterHeaderFormatter(b[0],!0));return c.join("")},refresh:function(a,b){var c=this.chart,d=this.label,e=this.options,f,g,h,i={},k,j=[];k=e.formatter||this.defaultFormatter;var i=c.hoverPoints,l,m=this.shared;
	clearTimeout(this.hideTimer);this.followPointer=ta(a)[0].series.tooltipOptions.followPointer;h=this.getAnchor(a,b);f=h[0];g=h[1];m&&(!a.series||!a.series.noSharedTooltip)?(c.hoverPoints=a,i&&o(i,function(a){a.setState()}),o(a,function(a){a.setState("hover");j.push(a.getLabelConfig())}),i={x:a[0].category,y:a[0].y},i.points=j,this.len=j.length,a=a[0]):i=a.getLabelConfig();k=k.call(i,this);i=a.series;this.distance=p(i.tooltipOptions.distance,16);k===!1?this.hide():(this.isHidden&&(Na(d),d.attr("opacity",
	1).show()),d.attr({text:k}),l=e.borderColor||a.color||i.color||"#606060",d.attr({stroke:l}),this.updatePosition({plotX:f,plotY:g,negative:a.negative,ttBelow:a.ttBelow,h:h[2]||0}),this.isHidden=!1);H(c,"tooltipRefresh",{text:k,x:f+c.plotLeft,y:g+c.plotTop,borderColor:l})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(B(c.x),B(c.y||0),a.plotX+b.plotLeft,a.plotY+b.plotTop)},getXDateFormat:function(a,b,c){var d,
	b=b.dateTimeLabelFormats,e=c&&c.closestPointRange,f,g={millisecond:15,second:12,minute:9,hour:6,day:3},h,i="millisecond";if(e){h=Pa("%m-%d %H:%M:%S.%L",a.x);for(f in G){if(e===G.week&&+Pa("%w",a.x)===c.options.startOfWeek&&h.substr(6)==="00:00:00.000"){f="week";break}if(G[f]>e){f=i;break}if(g[f]&&h.substr(g[f])!=="01-01 00:00:00.000".substr(g[f]))break;f!=="week"&&(i=f)}f&&(d=b[f])}else d=b.day;return d||b.year},tooltipFooterHeaderFormatter:function(a,b){var c=b?"footer":"header",d=a.series,e=d.tooltipOptions,
	f=e.xDateFormat,g=d.xAxis,h=g&&g.options.type==="datetime"&&ma(a.key),c=e[c+"Format"];h&&!f&&(f=this.getXDateFormat(a,e,g));h&&f&&(c=c.replace("{point.key}","{point.key:"+f+"}"));return Ja(c,{point:a,series:d})},bodyFormatter:function(a){return Ba(a,function(a){var c=a.series.tooltipOptions;return(c.pointFormatter||a.point.tooltipFormatter).call(a.point,c.pointFormat)})}};var ga;db=A&&A.documentElement.ontouchstart!==z;var Xa=w.Pointer=function(a,b){this.init(a,b)};Xa.prototype={init:function(a,b){var c=
	b.chart,d=c.events,e=ia?"":c.zoomType,c=a.inverted,f;this.options=b;this.chart=a;this.zoomX=f=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=f&&!c||e&&c;this.zoomVert=e&&!c||f&&c;this.hasZoom=f||e;this.runChartClick=d&&!!d.click;this.pinchDown=[];this.lastValidTouch={};if(w.Tooltip&&b.tooltip.enabled)a.tooltip=new Ob(a,b.tooltip),this.followTouchMove=p(b.tooltip.followTouchMove,!0);this.setDOMEvents()},normalize:function(a,b){var c,d,a=a||C.event;if(!a.target)a.target=a.srcElement;d=a.touches?
	a.touches.length?a.touches.item(0):a.changedTouches[0]:a;if(!b)this.chartPosition=b=Ab(this.chart.container);d.pageX===z?(c=t(a.x,a.clientX-b.left),d=a.y):(c=d.pageX-b.left,d=d.pageY-b.top);return s(a,{chartX:B(c),chartY:B(d)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};o(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},runPointActions:function(a){var b=this.chart,c=b.series,d=b.tooltip,e=d?d.shared:!1,f=b.hoverPoint,
	g=b.hoverSeries,h,i=[Number.MAX_VALUE,Number.MAX_VALUE],k,j,l=[],m=[],n;if(!e&&!g)for(h=0;h<c.length;h++)if(c[h].directTouch||!c[h].options.stickyTracking)c=[];g&&(e?g.noSharedTooltip:g.directTouch)&&f?m=[f]:(o(c,function(b){k=b.noSharedTooltip&&e;j=!e&&b.directTouch;b.visible&&!k&&!j&&p(b.options.enableMouseTracking,!0)&&(n=b.searchPoint(a,!k&&b.kdDimensions===1))&&l.push(n)}),o(l,function(a){a&&o(["dist","distX"],function(b,c){if(typeof a[b]==="number"){var d=a[b]===i[c]&&a.series.group.zIndex>=
	m[c].series.group.zIndex;if(a[b]<i[c]||d)i[c]=a[b],m[c]=a}})}));if(e)for(h=l.length;h--;)(l[h].clientX!==m[1].clientX||l[h].series.noSharedTooltip)&&l.splice(h,1);if(m[0]&&(m[0]!==this.prevKDPoint||d&&d.isHidden))if(e&&!m[0].series.noSharedTooltip)l.length&&d&&d.refresh(l,a),o(l,function(b){b.onMouseOver(a,b!==(g&&g.directTouch&&f||m[0]))}),this.prevKDPoint=m[1];else{d&&d.refresh(m[0],a);if(!g||!g.directTouch)m[0].onMouseOver(a);this.prevKDPoint=m[0]}else c=g&&g.tooltipOptions.followPointer,d&&c&&
	!d.isHidden&&(c=d.getAnchor([{}],a),d.updatePosition({plotX:c[0],plotY:c[1]}));if(!this._onDocumentMouseMove)this._onDocumentMouseMove=function(a){if(O[ga])O[ga].pointer.onDocumentMouseMove(a)},N(A,"mousemove",this._onDocumentMouseMove);o(e?l:[p(m[1],f)],function(c){o(b.axes,function(b){(!c||c.series[b.coll]===b)&&b.drawCrosshair(a,c)})})},reset:function(a,b){var c=this.chart,d=c.hoverSeries,e=c.hoverPoint,f=c.hoverPoints,g=c.tooltip,h=g&&g.shared?f:e;a&&h&&o(ta(h),function(b){b.series.isCartesian&&
	b.plotX===void 0&&(a=!1)});if(a)g&&h&&(g.refresh(h),e&&(e.setState(e.state,!0),o(c.axes,function(a){p(a.crosshair&&a.crosshair.snap,!0)?a.drawCrosshair(null,e):a.hideCrosshair()})));else{if(e)e.onMouseOut();f&&o(f,function(a){a.setState()});if(d)d.onMouseOut();g&&g.hide(b);if(this._onDocumentMouseMove)V(A,"mousemove",this._onDocumentMouseMove),this._onDocumentMouseMove=null;o(c.axes,function(a){a.hideCrosshair()});this.hoverX=c.hoverPoints=c.hoverPoint=null}},scaleGroups:function(a,b){var c=this.chart,
	d;o(c.series,function(e){d=a||e.getPlotBox();e.xAxis&&e.xAxis.zoomEnabled&&(e.group.attr(d),e.markerGroup&&(e.markerGroup.attr(d),e.markerGroup.clip(b?c.clipRect:null)),e.dataLabelsGroup&&e.dataLabelsGroup.attr(d))});c.clipRect.attr(b||c.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,f=this.zoomHor,g=this.zoomVert,
	h=b.plotLeft,i=b.plotTop,k=b.plotWidth,j=b.plotHeight,l,m=this.selectionMarker,n=this.mouseDownX,q=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];if(!m||!m.touch)if(d<h?d=h:d>h+k&&(d=h+k),e<i?e=i:e>i+j&&(e=i+j),this.hasDragged=Math.sqrt(Math.pow(n-d,2)+Math.pow(q-e,2)),this.hasDragged>10){l=b.isInsidePlot(n-h,q-i);if(b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&l&&!v&&!m)this.selectionMarker=m=b.renderer.rect(h,i,f?1:k,g?1:j,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add();
	m&&f&&(d-=n,m.attr({width:Q(d),x:(d>0?0:d)+n}));m&&g&&(d=e-q,m.attr({height:Q(d),y:(d>0?0:d)+q}));l&&!m&&c.panning&&b.pan(a,c.panning)}},drop:function(a){var b=this,c=this.chart,d=this.hasPinched;if(this.selectionMarker){var e={originalEvent:a,xAxis:[],yAxis:[]},f=this.selectionMarker,g=f.attr?f.attr("x"):f.x,h=f.attr?f.attr("y"):f.y,i=f.attr?f.attr("width"):f.width,k=f.attr?f.attr("height"):f.height,j;if(this.hasDragged||d)o(c.axes,function(c){if(c.zoomEnabled&&r(c.min)&&(d||b[{xAxis:"zoomX",yAxis:"zoomY"}[c.coll]])){var f=
	c.horiz,n=a.type==="touchend"?c.minPixelPadding:0,q=c.toValue((f?g:h)+n),f=c.toValue((f?g+i:h+k)-n);e[c.coll].push({axis:c,min:E(q,f),max:t(q,f)});j=!0}}),j&&H(c,"selection",e,function(a){c.zoom(s(a,d?{animation:!1}:null))});this.selectionMarker=this.selectionMarker.destroy();d&&this.scaleGroups()}if(c)L(c.container,{cursor:c._cursor}),c.cancelClick=this.hasDragged>10,c.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[]},onContainerMouseDown:function(a){a=this.normalize(a);a.preventDefault&&
	a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(a){O[ga]&&O[ga].pointer.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,a=this.normalize(a,c);c&&!this.inClass(a.target,"highcharts-tracker")&&!b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&this.reset()},onContainerMouseLeave:function(a){var b=O[ga];if(b&&(a.relatedTarget||a.toElement))b.pointer.reset(),b.pointer.chartPosition=null},onContainerMouseMove:function(a){var b=this.chart;if(!r(ga)||
	!O[ga]||!O[ga].mouseIsDown)ga=b.index;a=this.normalize(a);a.returnValue=!1;b.mouseIsDown==="mousedown"&&this.drag(a);(this.inClass(a.target,"highcharts-tracker")||b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=K(a,"class")){if(c.indexOf(b)!==-1)return!0;if(c.indexOf("highcharts-container")!==-1)return!1}a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries,a=a.relatedTarget||a.toElement;
	if(b&&a&&!b.options.stickyTracking&&!this.inClass(a,"highcharts-tooltip")&&!this.inClass(a,"highcharts-series-"+b.index))b.onMouseOut()},onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,a=this.normalize(a);b.cancelClick||(c&&this.inClass(a.target,"highcharts-tracker")?(H(c.series,"click",s(a,{point:c})),b.hoverPoint&&c.firePointEvent("click",a)):(s(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&H(b,"click",a)))},setDOMEvents:function(){var a=
	this,b=a.chart.container;b.onmousedown=function(b){a.onContainerMouseDown(b)};b.onmousemove=function(b){a.onContainerMouseMove(b)};b.onclick=function(b){a.onContainerClick(b)};N(b,"mouseleave",a.onContainerMouseLeave);eb===1&&N(A,"mouseup",a.onDocumentMouseUp);if(db)b.ontouchstart=function(b){a.onContainerTouchStart(b)},b.ontouchmove=function(b){a.onContainerTouchMove(b)},eb===1&&N(A,"touchend",a.onDocumentTouchEnd)},destroy:function(){var a;V(this.chart.container,"mouseleave",this.onContainerMouseLeave);
	eb||(V(A,"mouseup",this.onDocumentMouseUp),V(A,"touchend",this.onDocumentTouchEnd));clearInterval(this.tooltipTimeout);for(a in this)this[a]=null}};s(w.Pointer.prototype,{pinchTranslate:function(a,b,c,d,e,f){(this.zoomHor||this.pinchHor)&&this.pinchTranslateDirection(!0,a,b,c,d,e,f);(this.zoomVert||this.pinchVert)&&this.pinchTranslateDirection(!1,a,b,c,d,e,f)},pinchTranslateDirection:function(a,b,c,d,e,f,g,h){var i=this.chart,k=a?"x":"y",j=a?"X":"Y",l="chart"+j,m=a?"width":"height",n=i["plot"+(a?
	"Left":"Top")],q,v,p=h||1,o=i.inverted,x=i.bounds[a?"h":"v"],u=b.length===1,t=b[0][l],r=c[0][l],s=!u&&b[1][l],z=!u&&c[1][l],w,c=function(){!u&&Q(t-s)>20&&(p=h||Q(r-z)/Q(t-s));v=(n-r)/p+t;q=i["plot"+(a?"Width":"Height")]/p};c();b=v;b<x.min?(b=x.min,w=!0):b+q>x.max&&(b=x.max-q,w=!0);w?(r-=0.8*(r-g[k][0]),u||(z-=0.8*(z-g[k][1])),c()):g[k]=[r,z];o||(f[k]=v-n,f[m]=q);f=o?1/p:p;e[m]=q;e[k]=b;d[o?a?"scaleY":"scaleX":"scale"+j]=p;d["translate"+j]=f*n+(r-f*t)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,
	e=a.touches,f=e.length,g=b.lastValidTouch,h=b.hasZoom,i=b.selectionMarker,k={},j=f===1&&(b.inClass(a.target,"highcharts-tracker")&&c.runTrackerClick||b.runChartClick),l={};if(f>1)b.initiated=!0;h&&b.initiated&&!j&&a.preventDefault();Ba(e,function(a){return b.normalize(a)});if(a.type==="touchstart")o(e,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),g.x=[d[0].chartX,d[1]&&d[1].chartX],g.y=[d[0].chartY,d[1]&&d[1].chartY],o(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"],
	d=a.minPixelPadding,e=a.toPixels(p(a.options.min,a.dataMin)),f=a.toPixels(p(a.options.max,a.dataMax)),g=E(e,f),e=t(e,f);b.min=E(a.pos,g-d);b.max=t(a.pos+a.len,e+d)}}),b.res=!0;else if(d.length){if(!i)b.selectionMarker=i=s({destroy:Aa,touch:!0},c.plotBox);b.pinchTranslate(d,e,k,i,l,g);b.hasPinched=h;b.scaleGroups(k,l);if(!h&&b.followTouchMove&&f===1)this.runPointActions(b.normalize(a));else if(b.res)b.res=!1,this.reset(!1,0)}},touch:function(a,b){var c=this.chart,d;ga=c.index;if(a.touches.length===
	1)if(a=this.normalize(a),c.isInsidePlot(a.chartX-c.plotLeft,a.chartY-c.plotTop)&&!c.openMenu){b&&this.runPointActions(a);if(a.type==="touchmove")c=this.pinchDown,d=Math.sqrt(Math.pow(c[0].chartX-a.chartX,2)+Math.pow(c[0].chartY-a.chartY,2))>=4;p(d,!0)&&this.pinch(a)}else b&&this.reset();else a.touches.length===2&&this.pinch(a)},onContainerTouchStart:function(a){this.touch(a,!0)},onContainerTouchMove:function(a){this.touch(a)},onDocumentTouchEnd:function(a){O[ga]&&O[ga].pointer.drop(a)}});if(C.PointerEvent||
	C.MSPointerEvent){var va={},Cb=!!C.PointerEvent,Rb=function(){var a,b=[];b.item=function(a){return this[a]};for(a in va)va.hasOwnProperty(a)&&b.push({pageX:va[a].pageX,pageY:va[a].pageY,target:va[a].target});return b},Db=function(a,b,c,d){if((a.pointerType==="touch"||a.pointerType===a.MSPOINTER_TYPE_TOUCH)&&O[ga])d(a),d=O[ga].pointer,d[b]({type:c,target:a.currentTarget,preventDefault:Aa,touches:Rb()})};s(Xa.prototype,{onContainerPointerDown:function(a){Db(a,"onContainerTouchStart","touchstart",function(a){va[a.pointerId]=
	{pageX:a.pageX,pageY:a.pageY,target:a.currentTarget}})},onContainerPointerMove:function(a){Db(a,"onContainerTouchMove","touchmove",function(a){va[a.pointerId]={pageX:a.pageX,pageY:a.pageY};if(!va[a.pointerId].target)va[a.pointerId].target=a.currentTarget})},onDocumentPointerUp:function(a){Db(a,"onDocumentTouchEnd","touchend",function(a){delete va[a.pointerId]})},batchMSEvents:function(a){a(this.chart.container,Cb?"pointerdown":"MSPointerDown",this.onContainerPointerDown);a(this.chart.container,Cb?
	"pointermove":"MSPointerMove",this.onContainerPointerMove);a(A,Cb?"pointerup":"MSPointerUp",this.onDocumentPointerUp)}});fb(Xa.prototype,"init",function(a,b,c){a.call(this,b,c);this.hasZoom&&L(b.container,{"-ms-touch-action":"none","touch-action":"none"})});fb(Xa.prototype,"setDOMEvents",function(a){a.apply(this);(this.hasZoom||this.followTouchMove)&&this.batchMSEvents(N)});fb(Xa.prototype,"destroy",function(a){this.batchMSEvents(V);a.call(this)})}var pb=w.Legend=function(a,b){this.init(a,b)};pb.prototype=
	{init:function(a,b){var c=this,d=b.itemStyle,e=b.itemMarginTop||0;this.options=b;if(b.enabled)c.itemStyle=d,c.itemHiddenStyle=D(d,b.itemHiddenStyle),c.itemMarginTop=e,c.padding=d=p(b.padding,8),c.initialItemX=d,c.initialItemY=d-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.symbolWidth=p(b.symbolWidth,16),c.pages=[],c.render(),N(c.chart,"endResize",function(){c.positionCheckboxes()})},colorizeItem:function(a,b){var c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,
	c=b?c.itemStyle.color:g,h=b?a.legendColor||a.color||"#CCC":g,g=a.options&&a.options.marker,i={fill:h},k;d&&d.css({fill:c,color:c});e&&e.attr({stroke:h});if(f){if(g&&f.isMarker)for(k in i.stroke=h,g=a.convertAttribs(g),g)d=g[k],d!==z&&(i[k]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;(a=a.legendGroup)&&a.element&&a.translate(b?e:this.legendWidth-e-2*c-4,d);if(f)f.x=e,f.y=d},destroyItem:function(a){var b=a.checkbox;
	o(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())});b&&Sa(a.checkbox)},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},positionCheckboxes:function(a){var b=this.group.alignAttr,c,d=this.clipHeight||this.legendHeight,e=this.titleHeight;if(b)c=b.translateY,o(this.allItems,function(f){var g=f.checkbox,h;g&&(h=c+e+g.y+(a||0)+3,L(g,{left:b.translateX+f.checkboxOffset+g.x-20+"px",top:h+"px",display:h>
	c-6&&h<c+d-6?"":"none"}))})},renderTitle:function(){var a=this.padding,b=this.options.title,c=0;if(b.text){if(!this.title)this.title=this.chart.renderer.label(b.text,a-3,a-4,null,null,null,null,null,"legend-title").attr({zIndex:1}).css(b.style).add(this.group);a=this.title.getBBox();c=a.height;this.offsetWidth=a.width;this.contentGroup.attr({translateY:c})}this.titleHeight=c},setText:function(a){var b=this.options;a.legendItem.attr({text:b.labelFormat?Ja(b.labelFormat,a):b.labelFormatter.call(a)})},
	renderItem:function(a){var b=this.chart,c=b.renderer,d=this.options,e=d.layout==="horizontal",f=this.symbolWidth,g=d.symbolPadding,h=this.itemStyle,i=this.itemHiddenStyle,k=this.padding,j=e?p(d.itemDistance,20):0,l=!d.rtl,m=d.width,n=d.itemMarginBottom||0,q=this.itemMarginTop,v=this.initialItemX,o=a.legendItem,r=a.series&&a.series.drawLegendSymbol?a.series:a,x=r.options,x=this.createCheckboxForItem&&x&&x.showCheckbox,u=d.useHTML;if(!o){a.legendGroup=c.g("legend-item").attr({zIndex:1}).add(this.scrollGroup);
	a.legendItem=o=c.text("",l?f+g:-g,this.baseline||0,u).css(D(a.visible?h:i)).attr({align:l?"left":"right",zIndex:2}).add(a.legendGroup);if(!this.baseline)this.fontMetrics=c.fontMetrics(h.fontSize,o),this.baseline=this.fontMetrics.f+3+q,o.attr("y",this.baseline);r.drawLegendSymbol(this,a);this.setItemEvents&&this.setItemEvents(a,o,u,h,i);x&&this.createCheckboxForItem(a)}this.colorizeItem(a,a.visible);this.setText(a);c=o.getBBox();f=a.checkboxOffset=d.itemWidth||a.legendItemWidth||f+g+c.width+j+(x?20:
	0);this.itemHeight=g=B(a.legendItemHeight||c.height);if(e&&this.itemX-v+f>(m||b.chartWidth-2*k-v-d.x))this.itemX=v,this.itemY+=q+this.lastLineHeight+n,this.lastLineHeight=0;this.maxItemWidth=t(this.maxItemWidth,f);this.lastItemY=q+this.itemY+n;this.lastLineHeight=t(g,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=f:(this.itemY+=q+g+n,this.lastLineHeight=g);this.offsetWidth=m||t((e?this.itemX-v-j:f)+k,this.offsetWidth)},getAllItems:function(){var a=[];o(this.chart.series,
	function(b){var c=b.options;if(p(c.showInLegend,!r(c.linkedTo)?z:!1,!0))a=a.concat(b.legendItems||(c.legendType==="point"?b.data:b))});return a},adjustMargins:function(a,b){var c=this.chart,d=this.options,e=d.align.charAt(0)+d.verticalAlign.charAt(0)+d.layout.charAt(0);this.display&&!d.floating&&o([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(f,g){f.test(e)&&!r(a[g])&&(c[nb[g]]=t(c[nb[g]],c.legend[(g+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][g]*d[g%2?"x":"y"]+p(d.margin,
	12)+b[g]))})},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.group,e,f,g,h,i=a.box,k=a.options,j=a.padding,l=k.borderWidth,m=k.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup);a.renderTitle();e=a.getAllItems();hb(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});
	k.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;a.lastLineHeight=0;o(e,function(b){a.renderItem(b)});g=(k.width||a.offsetWidth)+j;h=a.lastItemY+a.lastLineHeight+a.titleHeight;h=a.handleOverflow(h);h+=j;if(l||m){if(i){if(g>0&&h>0)i[i.isNew?"attr":"animate"](i.crisp({width:g,height:h})),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,k.borderRadius,l||0).attr({stroke:k.borderColor,"stroke-width":l||0,fill:m||"none"}).add(d).shadow(k.shadow),i.isNew=!0;i[f?"show":"hide"]()}a.legendWidth=g;a.legendHeight=
	h;o(e,function(b){a.positionItem(b)});f&&d.align(s({width:g,height:h},k),!0,"spacingBox");b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+(e.verticalAlign==="top"?-f:f)-this.padding,g=e.maxHeight,h,i=this.clipRect,k=e.navigation,j=p(k.animation,!0),l=k.arrowSize||12,m=this.nav,n=this.pages,q=this.padding,v,y=this.allItems,r=function(a){i.attr({height:a});if(b.contentGroup.div)b.contentGroup.div.style.clip=
	"rect("+q+"px,9999px,"+(q+a)+"px,0)"};e.layout==="horizontal"&&(f/=2);g&&(f=E(f,g));n.length=0;if(a>f&&k.enabled!==!1){this.clipHeight=h=t(f-20-this.titleHeight-q,0);this.currentPage=p(this.currentPage,1);this.fullHeight=a;o(y,function(a,b){var c=a._legendItemPos[1],d=B(a.legendItem.getBBox().height),e=n.length;if(!e||c-n[e-1]>h&&(v||c)!==n[e-1])n.push(v||c),e++;b===y.length-1&&c+d-n[e-1]>h&&n.push(c);c!==v&&(v=c)});if(!i)i=b.clipRect=d.clipRect(0,q,9999,0),b.contentGroup.clip(i);r(h);if(!m)this.nav=
	m=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,l,l).on("click",function(){b.scroll(-1,j)}).add(m),this.pager=d.text("",15,10).css(k.style).add(m),this.down=d.symbol("triangle-down",0,0,l,l).on("click",function(){b.scroll(1,j)}).add(m);b.scroll(0);a=f}else if(m)r(c.chartHeight),m.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pages,d=c.length,e=this.currentPage+a,f=this.clipHeight,g=this.options.navigation,h=g.activeColor,
	g=g.inactiveColor,i=this.pager,k=this.padding;e>d&&(e=d);if(e>0)b!==z&&Ta(b,this.chart),this.nav.attr({translateX:k,translateY:f+this.padding+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:e===1?g:h}).css({cursor:e===1?"default":"pointer"}),i.attr({text:e+"/"+d}),this.down.attr({x:18+this.pager.getBBox().width,fill:e===d?g:h}).css({cursor:e===d?"default":"pointer"}),c=-c[e-1]+this.initialItemY,this.scrollGroup.animate({translateY:c}),this.currentPage=e,this.positionCheckboxes(c)}};M=
	w.LegendSymbolMixin={drawRectangle:function(a,b){var c=a.options.symbolHeight||a.fontMetrics.f;b.legendSymbol=this.chart.renderer.rect(0,a.baseline-c+1,a.symbolWidth,c,a.options.symbolRadius||0).attr({zIndex:3}).add(b.legendGroup)},drawLineMarker:function(a){var b=this.options,c=b.marker,d=a.symbolWidth,e=this.chart.renderer,f=this.legendGroup,a=a.baseline-B(a.fontMetrics.b*0.3),g;if(b.lineWidth){g={"stroke-width":b.lineWidth};if(b.dashStyle)g.dashstyle=b.dashStyle;this.legendLine=e.path(["M",0,a,
	"L",d,a]).attr(g).add(f)}if(c&&c.enabled!==!1)b=c.radius,this.legendSymbol=c=e.symbol(this.symbol,d/2-b,a-b,2*b,2*b,c).add(f),c.isMarker=!0}};(/Trident\/7\.0/.test(za)||La)&&fb(pb.prototype,"positionItem",function(a,b){var c=this,d=function(){b._legendItemPos&&a.call(c,b)};d();setTimeout(d)});var gb=w.Chart=function(){this.getArgs.apply(this,arguments)};w.chart=function(a,b,c){return new gb(a,b,c)};gb.prototype={callbacks:[],getArgs:function(){var a=[].slice.call(arguments);if(xa(a[0])||a[0].nodeName)this.renderTo=
	a.shift();this.init(a[0],a[1])},init:function(a,b){var c,d=a.series;a.series=null;c=D(S,a);c.series=a.series=d;this.userOptions=a;d=c.chart;this.margin=this.splashArray("margin",d);this.spacing=this.splashArray("spacing",d);var e=d.events;this.bounds={h:{},v:{}};this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f=this,g;f.index=O.length;O.push(f);eb++;d.reflow!==!1&&N(f,"load",function(){f.initReflow()});if(e)for(g in e)N(f,g,e[g]);
	f.xAxis=[];f.yAxis=[];f.animation=ia?!1:p(d.animation,!0);f.pointCount=f.colorCounter=f.symbolCounter=0;f.firstRender()},initSeries:function(a){var b=this.options.chart;(b=I[a.type||b.type||b.defaultSeriesType])||Z(17,!0);b=new b;b.init(this,a);return b},isInsidePlot:function(a,b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},redraw:function(a){var b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,g,h,i=this.hasCartesianSeries,k=this.isDirtyBox,
	j=c.length,l=j,m=this.renderer,n=m.isHidden(),q=[];Ta(a,this);n&&this.cloneRenderTo();for(this.layOutTitles();l--;)if(a=c[l],a.options.stacking&&(g=!0,a.isDirty)){h=!0;break}if(h)for(l=j;l--;)if(a=c[l],a.options.stacking)a.isDirty=!0;o(c,function(a){a.isDirty&&a.options.legendType==="point"&&(a.updateTotals&&a.updateTotals(),f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend=!1;g&&this.getStacks();if(i&&!this.isResizing)this.maxTicks=null,o(b,function(a){a.setScale()});this.getMargins();
	i&&(o(b,function(a){a.isDirty&&(k=!0)}),o(b,function(a){var b=a.min+","+a.max;if(a.extKey!==b)a.extKey=b,q.push(function(){H(a,"afterSetExtremes",s(a.eventArgs,a.getExtremes()));delete a.eventArgs});(k||g)&&a.redraw()}));k&&this.drawChartBox();o(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()});d&&d.reset(!0);m.draw();H(this,"redraw");n&&this.cloneRenderTo(!0);o(q,function(a){a.call()})},get:function(a){var b=this.axes,c=this.series,d,e;for(d=0;d<b.length;d++)if(b[d].options.id===
	a)return b[d];for(d=0;d<c.length;d++)if(c[d].options.id===a)return c[d];for(d=0;d<c.length;d++){e=c[d].points||[];for(b=0;b<e.length;b++)if(e[b].id===a)return e[b]}return null},getAxes:function(){var a=this,b=this.options,c=b.xAxis=ta(b.xAxis||{}),b=b.yAxis=ta(b.yAxis||{});o(c,function(a,b){a.index=b;a.isX=!0});o(b,function(a,b){a.index=b});c=c.concat(b);o(c,function(b){new fa(a,b)})},getSelectedPoints:function(){var a=[];o(this.series,function(b){a=a.concat(Ma(b.points||[],function(a){return a.selected}))});
	return a},getSelectedSeries:function(){return Ma(this.series,function(a){return a.selected})},setTitle:function(a,b,c){var g;var d=this,e=d.options,f;f=e.title=D(e.title,a);g=e.subtitle=D(e.subtitle,b),e=g;o([["title",a,f],["subtitle",b,e]],function(a){var b=a[0],c=d[b],e=a[1],a=a[2];c&&e&&(d[b]=c=c.destroy());a&&a.text&&!c&&(d[b]=d.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":"highcharts-"+b,zIndex:a.zIndex||4}).css(a.style).add())});d.layOutTitles(c)},layOutTitles:function(a){var b=
	0,c=this.title,d=this.subtitle,e=this.options,f=e.title,e=e.subtitle,g=this.renderer,h=this.spacingBox.width-44;if(c&&(c.css({width:(f.width||h)+"px"}).align(s({y:g.fontMetrics(f.style.fontSize,c).b-3},f),!1,"spacingBox"),!f.floating&&!f.verticalAlign))b=c.getBBox().height;d&&(d.css({width:(e.width||h)+"px"}).align(s({y:b+(f.margin-13)+g.fontMetrics(e.style.fontSize,c).b},e),!1,"spacingBox"),!e.floating&&!e.verticalAlign&&(b=ua(b+d.getBBox().height)));c=this.titleOffset!==b;this.titleOffset=b;if(!this.isDirtyBox&&
	c)this.isDirtyBox=c,this.hasRendered&&p(a,!0)&&this.isDirtyBox&&this.redraw()},getChartSize:function(){var a=this.options.chart,b=a.width,a=a.height,c=this.renderToClone||this.renderTo;if(!r(b))this.containerWidth=ka(c,"width");if(!r(a))this.containerHeight=ka(c,"height");this.chartWidth=t(0,b||this.containerWidth||600);this.chartHeight=t(0,p(a,this.containerHeight>19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),
	Sa(b),delete this.renderToClone):(c&&c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),L(b,{position:"absolute",top:"-9999px",display:"block"}),b.style.setProperty&&b.style.setProperty("display","block","important"),A.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options,c=b.chart,d,e;a=this.renderTo;var f="highcharts-"+zb++;if(!a)this.renderTo=a=c.renderTo;if(xa(a))this.renderTo=a=A.getElementById(a);a||Z(13,
	!0);d=F(K(a,"data-highcharts-chart"));!isNaN(d)&&O[d]&&O[d].hasRendered&&O[d].destroy();K(a,"data-highcharts-chart",this.index);a.innerHTML="";!c.skipClone&&!a.offsetWidth&&this.cloneRenderTo();this.getChartSize();d=this.chartWidth;e=this.chartHeight;this.container=a=$(Ka,{className:"highcharts-container"+(c.className?" "+c.className:""),id:f},s({position:"relative",overflow:"hidden",width:d+"px",height:e+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},
	c.style),this.renderToClone||a);this._cursor=a.style.cursor;this.renderer=new (w[c.renderer]||cb)(a,d,e,c.style,c.forExport,b.exporting&&b.exporting.allowHTML);ia&&this.renderer.create(this,a,d,e);this.renderer.chartIndex=this.index},getMargins:function(a){var b=this.spacing,c=this.margin,d=this.titleOffset;this.resetMargins();if(d&&!r(c[0]))this.plotTop=t(this.plotTop,d+this.options.title.margin+b[0]);this.legend.adjustMargins(c,b);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);
	this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);a||this.getAxisMargins()},getAxisMargins:function(){var a=this,b=a.axisOffset=[0,0,0,0],c=a.margin;a.hasCartesianSeries&&o(a.axes,function(a){a.visible&&a.getOffset()});o(nb,function(d,e){r(c[e])||(a[d]+=b[e])});a.setChartSize()},reflow:function(a){var b=this,c=b.options.chart,d=b.renderTo,e=c.width||ka(d,"width"),f=c.height||ka(d,"height"),c=a?a.target:C;if(!b.hasUserSize&&!b.isPrinting&&e&&f&&(c===C||c===A)){if(e!==b.containerWidth||f!==b.containerHeight)clearTimeout(b.reflowTimeout),
	b.reflowTimeout=Oa(function(){if(b.container)b.setSize(e,f,!1),b.hasUserSize=null},a?100:0);b.containerWidth=e;b.containerHeight=f}},initReflow:function(){var a=this,b=function(b){a.reflow(b)};N(C,"resize",b);N(a,"destroy",function(){V(C,"resize",b)})},setSize:function(a,b,c){var d=this,e,f,g=d.renderer;d.isResizing+=1;Ta(c,d);d.oldChartHeight=d.chartHeight;d.oldChartWidth=d.chartWidth;if(r(a))d.chartWidth=e=t(0,B(a)),d.hasUserSize=!!e;if(r(b))d.chartHeight=f=t(0,B(b));a=g.globalAnimation;(a?Wa:L)(d.container,
	{width:e+"px",height:f+"px"},a);d.setChartSize(!0);g.setSize(e,f,c);d.maxTicks=null;o(d.axes,function(a){a.isDirty=!0;a.setScale()});o(d.series,function(a){a.isDirty=!0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.layOutTitles();d.getMargins();d.redraw(c);d.oldChartHeight=null;H(d,"resize");Oa(function(){d&&H(d,"endResize",null,function(){d.isResizing-=1})},$a(a).duration)},setChartSize:function(a){var b=this.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=this.spacing,
	h=this.clipOffset,i,k,j,l;this.plotLeft=i=B(this.plotLeft);this.plotTop=k=B(this.plotTop);this.plotWidth=j=t(0,B(d-i-this.marginRight));this.plotHeight=l=t(0,B(e-k-this.marginBottom));this.plotSizeX=b?l:j;this.plotSizeY=b?j:l;this.plotBorderWidth=f.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:g[3],y:g[0],width:d-g[3]-g[1],height:e-g[0]-g[2]};this.plotBox=c.plotBox={x:i,y:k,width:j,height:l};d=2*T(this.plotBorderWidth/2);b=ua(t(d,h[3])/2);c=ua(t(d,h[0])/2);this.clipBox={x:b,y:c,width:T(this.plotSizeX-
	t(d,h[1])/2-b),height:t(0,T(this.plotSizeY-t(d,h[2])/2-c))};a||o(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this;o(nb,function(b,c){a[b]=p(a.margin[c],a.spacing[c])});a.axisOffset=[0,0,0,0];a.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,k=a.backgroundColor,j=a.plotBackgroundColor,
	l=a.plotBackgroundImage,m=a.plotBorderWidth||0,n,q=this.plotLeft,p=this.plotTop,o=this.plotWidth,r=this.plotHeight,x=this.plotBox,u=this.clipRect,t=this.clipBox;n=i+(a.shadow?8:0);if(i||k)if(e)e.animate(e.crisp({width:c-n,height:d-n}));else{e={fill:k||"none"};if(i)e.stroke=a.borderColor,e["stroke-width"]=i;this.chartBackground=b.rect(n/2,n/2,c-n,d-n,a.borderRadius,i).attr(e).addClass("highcharts-background").add().shadow(a.shadow)}if(j)f?f.animate(x):this.plotBackground=b.rect(q,p,o,r,0).attr({fill:j}).add().shadow(a.plotShadow);
	if(l)h?h.animate(x):this.plotBGImage=b.image(l,q,p,o,r).add();u?u.animate({width:t.width,height:t.height}):this.clipRect=b.clipRect(t);if(m)g?(g.strokeWidth=-m,g.animate(g.crisp({x:q,y:p,width:o,height:r}))):this.plotBorder=b.rect(q,p,o,r,0,-m).attr({stroke:a.plotBorderColor,"stroke-width":m,fill:"none",zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,e,f;o(["inverted","angular","polar"],function(g){c=I[b.type||b.defaultSeriesType];f=
	a[g]||b[g]||c&&c.prototype[g];for(e=d&&d.length;!f&&e--;)(c=I[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},linkSeries:function(){var a=this,b=a.series;o(b,function(a){a.linkedSeries.length=0});o(b,function(b){var d=b.options.linkedTo;if(xa(d)&&(d=d===":previous"?a.series[b.index-1]:a.get(d)))d.linkedSeries.push(b),b.linkedParent=d,b.visible=p(b.options.visible,d.options.visible,b.visible)})},renderSeries:function(){o(this.series,function(a){a.translate();a.render()})},renderLabels:function(){var a=
	this,b=a.options.labels;b.items&&o(b.items,function(c){var d=s(b.style,c.style),e=F(d.left)+a.plotLeft,f=F(d.top)+a.plotTop+12;delete d.left;delete d.top;a.renderer.text(c.html,e,f).attr({zIndex:2}).css(d).add()})},render:function(){var a=this.axes,b=this.renderer,c=this.options,d,e,f,g;this.setTitle();this.legend=new pb(this,c.legend);this.getStacks&&this.getStacks();this.getMargins(!0);this.setChartSize();d=this.plotWidth;e=this.plotHeight-=21;o(a,function(a){a.setScale()});this.getAxisMargins();
	f=d/this.plotWidth>1.1;g=e/this.plotHeight>1.05;if(f||g)this.maxTicks=null,o(a,function(a){(a.horiz&&f||!a.horiz&&g)&&a.setTickInterval(!0)}),this.getMargins();this.drawChartBox();this.hasCartesianSeries&&o(a,function(a){a.visible&&a.render()});if(!this.seriesGroup)this.seriesGroup=b.g("series-group").attr({zIndex:3}).add();this.renderSeries();this.renderLabels();this.showCredits(c.credits);this.hasRendered=!0},showCredits:function(a){if(a.enabled&&!this.credits)this.credits=this.renderer.text(a.text,
	0,0).on("click",function(){if(a.href)C.location.href=a.href}).attr({align:a.position.align,zIndex:8}).css(a.style).add().align(a.position)},destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;H(a,"destroy");O[a.index]=z;eb--;a.renderTo.removeAttribute("data-highcharts-chart");V(a);for(e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();o("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),
	function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML="",V(d),f&&Sa(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!ca&&C==C.top&&A.readyState!=="complete"||ia&&!C.canvg?(ia?Nb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):A.attachEvent("onreadystatechange",function(){A.detachEvent("onreadystatechange",a.firstRender);A.readyState==="complete"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options;if(a.isReadyToRender()){a.getContainer();
	H(a,"init");a.resetMargins();a.setChartSize();a.propFromSeries();a.getAxes();o(b.series||[],function(b){a.initSeries(b)});a.linkSeries();H(a,"beforeRender");if(w.Pointer)a.pointer=new Xa(a,b);a.render();a.renderer.draw();if(!a.renderer.imgCount&&a.onload)a.onload();a.cloneRenderTo(!0)}},onload:function(){var a=this;o([this.callback].concat(this.callbacks),function(b){b&&a.index!==void 0&&b.apply(a,[a])});H(a,"load");this.onload=null},splashArray:function(a,b){var c=b[a],c=X(c)?c:[c,c,c,c];return[p(b[a+
	"Top"],c[0]),p(b[a+"Right"],c[1]),p(b[a+"Bottom"],c[2]),p(b[a+"Left"],c[3])]}};var Bb=w.CenteredSeriesMixin={getCenter:function(){var a=this.options,b=this.chart,c=2*(a.slicedOffset||0),d=b.plotWidth-2*c,b=b.plotHeight-2*c,e=a.center,e=[p(e[0],"50%"),p(e[1],"50%"),a.size||"100%",a.innerSize||0],f=E(d,b),g,h;for(g=0;g<4;++g)h=e[g],a=g<2||g===2&&/%$/.test(h),e[g]=(/%$/.test(h)?[d,b,f,e[2]][g]*parseFloat(h)/100:parseFloat(h))+(a?c:0);e[3]>e[2]&&(e[3]=e[2]);return e}},Ia=function(){};Ia.prototype={init:function(a,
	b,c){this.series=a;this.color=a.color;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++],a.colorCounter===b.length))a.colorCounter=0;a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=c.options.pointValKey||c.pointValKey,a=Ia.prototype.optionsToObject.call(this,a);s(this,a);this.options=this.options?s(this.options,a):a;if(d)this.y=this[d];this.isNull=this.y===null;
	if(this.x===void 0&&c)this.x=b===void 0?c.autoIncrement():b;return this},optionsToObject:function(a){var b={},c=this.series,d=c.options.keys,e=d||c.pointArrayMap||["y"],f=e.length,g=0,h=0;if(typeof a==="number"||a===null)b[e[0]]=a;else if(Da(a)){if(!d&&a.length>f){c=typeof a[0];if(c==="string")b.name=a[0];else if(c==="number")b.x=a[0];g++}for(;h<f;){if(!d||a[g]!==void 0)b[e[h]]=a[g];g++;h++}}else if(typeof a==="object"){b=a;if(a.dataLabels)c._hasPointLabels=!0;if(a.marker)c._hasPointMarkers=!0}return b},
	destroy:function(){var a=this.series.chart,b=a.hoverPoints,c;a.pointCount--;if(b&&(this.setState(),na(b,this),!b.length))a.hoverPoints=null;if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)V(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(c in this)this[c]=null},destroyElements:function(){for(var a=["graphic","dataLabel","dataLabelUpper","connector","shadowGroup"],b,c=6;c--;)b=a[c],this[b]&&(this[b]=this[b].destroy())},getLabelConfig:function(){return{x:this.category,
	y:this.y,color:this.color,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var b=this.series,c=b.tooltipOptions,d=p(c.valueDecimals,""),e=c.valuePrefix||"",f=c.valueSuffix||"";o(b.pointArrayMap||["y"],function(b){b="{point."+b;if(e||f)a=a.replace(b+"}",e+b+"}"+f);a=a.replace(b+"}",b+":,."+d+"f}")});return Ja(a,{point:this,series:this.series})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;
	(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();a==="click"&&e.allowPointSelect&&(c=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});H(this,a,b,c)},visible:!0};var R=w.Series=function(){};R.prototype={isCartesian:!0,type:"line",pointClass:Ia,sorted:!0,requireSorting:!0,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x",
	"y"],init:function(a,b){var c=this,d,e,f=a.series,g=function(a,b){return p(a.options.index,a._i)-p(b.options.index,b._i)};c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();s(c,{name:b.name,state:"",pointAttr:{},visible:b.visible!==!1,selected:b.selected===!0});if(ia)b.animation=!1;e=b.events;for(d in e)N(c,d,e[d]);if(e&&e.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor();c.getSymbol();o(c.parallelArrays,function(a){c[a+"Data"]=
	[]});c.setData(b.data,!1);if(c.isCartesian)a.hasCartesianSeries=!0;f.push(c);c._i=f.length-1;hb(f,g);this.yAxis&&hb(this.yAxis.series,g);o(f,function(a,b){a.index=b;a.name=a.name||"Series "+(b+1)})},bindAxes:function(){var a=this,b=a.options,c=a.chart,d;o(a.axisTypes||[],function(e){o(c[e],function(c){d=c.options;if(b[e]===d.index||b[e]!==z&&b[e]===d.id||b[e]===z&&d.index===0)c.series.push(a),a[e]=c,c.isDirty=!0});!a[e]&&a.optionalAxis!==e&&Z(18,!0)})},updateParallelArrays:function(a,b){var c=a.series,
	d=arguments;o(c.parallelArrays,typeof b==="number"?function(d){var f=d==="y"&&c.toYData?c.toYData(a):a[d];c[d+"Data"][b]=f}:function(a){Array.prototype[b].apply(c[a+"Data"],Array.prototype.slice.call(d,2))})},autoIncrement:function(){var a=this.options,b=this.xIncrement,c,d=a.pointIntervalUnit,b=p(b,a.pointStart,0);this.pointInterval=c=p(this.pointInterval,a.pointInterval,1);d&&(a=new pa(b),d==="day"?a=+a[kb](a[Ua]()+c):d==="month"?a=+a[xb](a[ab]()+c):d==="year"&&(a=+a[yb](a[bb]()+c)),c=a-b);this.xIncrement=
	b+c;return b},setOptions:function(a){var b=this.chart,c=b.options.plotOptions,b=b.userOptions||{},d=b.plotOptions||{},e=c[this.type];this.userOptions=a;c=D(e,c.series,a);this.tooltipOptions=D(S.tooltip,S.plotOptions[this.type].tooltip,b.tooltip,d.series&&d.series.tooltip,d[this.type]&&d[this.type].tooltip,a.tooltip);e.marker===null&&delete c.marker;this.zoneAxis=c.zoneAxis;a=this.zones=(c.zones||[]).slice();if((c.negativeColor||c.negativeFillColor)&&!c.zones)a.push({value:c[this.zoneAxis+"Threshold"]||
	c.threshold||0,color:c.negativeColor,fillColor:c.negativeFillColor});a.length&&r(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return c},getCyclic:function(a,b,c){var d=this.userOptions,e="_"+a+"Index",f=a+"Counter";b||(r(d[e])?b=d[e]:(d[e]=b=this.chart[f]%c.length,this.chart[f]+=1),b=c[b]);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||ba[this.type].color,this.chart.options.colors)},getSymbol:function(){var a=
	this.options.marker;this.getCyclic("symbol",a.symbol,this.chart.options.symbols);if(/^url/.test(this.symbol))a.radius=0},drawLegendSymbol:M.drawLineMarker,setData:function(a,b,c,d){var e=this,f=e.points,g=f&&f.length||0,h,i=e.options,k=e.chart,j=null,l=e.xAxis,m=l&&!!l.categories,n=i.turboThreshold,q=this.xData,v=this.yData,y=(h=e.pointArrayMap)&&h.length,a=a||[];h=a.length;b=p(b,!0);if(d!==!1&&h&&g===h&&!e.cropped&&!e.hasGroupedData&&e.visible)o(a,function(a,b){f[b].update&&a!==i.data[b]&&f[b].update(a,
	!1,null,!1)});else{e.xIncrement=null;e.colorCounter=0;o(this.parallelArrays,function(a){e[a+"Data"].length=0});if(n&&h>n){for(c=0;j===null&&c<h;)j=a[c],c++;if(ma(j)){m=p(i.pointStart,0);j=p(i.pointInterval,1);for(c=0;c<h;c++)q[c]=m,v[c]=a[c],m+=j;e.xIncrement=m}else if(Da(j))if(y)for(c=0;c<h;c++)j=a[c],q[c]=j[0],v[c]=j.slice(1,y+1);else for(c=0;c<h;c++)j=a[c],q[c]=j[0],v[c]=j[1];else Z(12)}else for(c=0;c<h;c++)if(a[c]!==z&&(j={series:e},e.pointClass.prototype.applyOptions.apply(j,[a[c]]),e.updateParallelArrays(j,
	c),m&&r(j.name)))l.names[j.x]=j.name;xa(v[0])&&Z(14,!0);e.data=[];e.options.data=e.userOptions.data=a;for(c=g;c--;)f[c]&&f[c].destroy&&f[c].destroy();if(l)l.minRange=l.userMinRange;e.isDirty=e.isDirtyData=k.isDirtyBox=!0;c=!1}i.legendType==="point"&&(this.processData(),this.generatePoints());b&&k.redraw(c)},processData:function(a){var b=this.xData,c=this.yData,d=b.length,e;e=0;var f,g,h=this.xAxis,i,k=this.options;i=k.cropThreshold;var j=this.getExtremesFromAll||k.getExtremesFromAll,l=this.isCartesian,
	k=h&&h.val2lin,m=h&&h.isLog,n,q;if(l&&!this.isDirty&&!h.isDirty&&!this.yAxis.isDirty&&!a)return!1;if(h)a=h.getExtremes(),n=a.min,q=a.max;if(l&&this.sorted&&!j&&(!i||d>i||this.forceCrop))if(b[d-1]<n||b[0]>q)b=[],c=[];else if(b[0]<n||b[d-1]>q)e=this.cropData(this.xData,this.yData,n,q),b=e.xData,c=e.yData,e=e.start,f=!0;for(i=b.length||1;--i;)d=m?k(b[i])-k(b[i-1]):b[i]-b[i-1],d>0&&(g===z||d<g)?g=d:d<0&&this.requireSorting&&Z(15);this.cropped=f;this.cropStart=e;this.processedXData=b;this.processedYData=
	c;this.closestPointRange=g},cropData:function(a,b,c,d){var e=a.length,f=0,g=e,h=p(this.cropShoulder,1),i;for(i=0;i<e;i++)if(a[i]>=c){f=t(0,i-h);break}for(c=i;c<e;c++)if(a[c]>d){g=c+h;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,k=this.hasGroupedData,j,l=[],m;if(!b&&!k)b=[],b.length=a.length,b=this.data=b;for(m=0;m<g;m++)i=
	h+m,k?(l[m]=(new f).init(this,[d[m]].concat(ta(e[m]))),l[m].dataGroup=this.groupMap[m]):(b[i]?j=b[i]:a[i]!==z&&(b[i]=j=(new f).init(this,a[i],d[m])),l[m]=j),l[m].index=i;if(b&&(g!==(c=b.length)||k))for(m=0;m<c;m++)if(m===h&&!k&&(m+=g),b[m])b[m].destroyElements(),b[m].plotX=z;this.data=b;this.points=l},getExtremes:function(a){var b=this.yAxis,c=this.processedXData,d,e=[],f=0;d=this.xAxis.getExtremes();var g=d.min,h=d.max,i,k,j,l,a=a||this.stackedYData||this.processedYData;d=a.length;for(l=0;l<d;l++)if(k=
	c[l],j=a[l],i=j!==null&&j!==z&&(!b.isLog||j.length||j>0),k=this.getExtremesFromAll||this.options.getExtremesFromAll||this.cropped||(c[l+1]||k)>=g&&(c[l-1]||k)<=h,i&&k)if(i=j.length)for(;i--;)j[i]!==null&&(e[f++]=j[i]);else e[f++]=j;this.dataMin=Qa(e);this.dataMax=Fa(e)},translate:function(){this.processedXData||this.processData();this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,h=!!this.modifyValue,i=a.pointPlacement,k=i===
	"between"||ma(i),j=a.threshold,l=a.startFromThreshold?j:0,m,n,q,o,y=Number.MAX_VALUE,a=0;a<g;a++){var s=f[a],x=s.x,u=s.y;n=s.low;var w=b&&e.stacks[(this.negStacks&&u<(l?0:j)?"-":"")+this.stackKey];if(e.isLog&&u!==null&&u<=0)s.y=u=null,Z(10);s.plotX=m=E(t(-1E5,c.translate(x,0,0,0,1,i,this.type==="flags")),1E5);if(b&&this.visible&&!s.isNull&&w&&w[x])o=this.getStackIndicator(o,x,this.index),w=w[x],u=w.points[o.key],n=u[0],u=u[1],n===l&&(n=p(j,e.min)),e.isLog&&n<=0&&(n=null),s.total=s.stackTotal=w.total,
	s.percentage=w.total&&s.y/w.total*100,s.stackY=u,w.setOffset(this.pointXOffset||0,this.barW||0);s.yBottom=r(n)?e.translate(n,0,1,0,1):null;h&&(u=this.modifyValue(u,s));s.plotY=n=typeof u==="number"&&u!==Infinity?E(t(-1E5,e.translate(u,0,1,0,1)),1E5):z;s.isInside=n!==z&&n>=0&&n<=e.len&&m>=0&&m<=c.len;s.clientX=k?c.translate(x,0,0,0,1):m;s.negative=s.y<(j||0);s.category=d&&d[s.x]!==z?d[s.x]:s.x;s.isNull||(q!==void 0&&(y=E(y,Q(m-q))),q=m)}this.closestPointRangePx=y},getValidPoints:function(a,b){var c=
	this.chart;return Ma(a||this.points||[],function(a){return b&&!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,e=b.inverted,f=this.clipBox,g=f||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,g.height,c.xAxis,c.yAxis].join(","),i=b[h],k=b[h+"m"];if(!i){if(a)g.width=0,b[h+"m"]=k=d.clipRect(-99,e?-b.plotLeft:-b.plotTop,99,e?b.chartWidth:b.chartHeight);b[h]=i=d.clipRect(g)}a&&(i.count+=1);if(c.clip!==
	!1)this.group.clip(a||f?i:b.clipRect),this.markerGroup.clip(k),this.sharedClipKey=h;a||(i.count-=1,i.count<=0&&h&&b[h]&&(f||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=this.options.animation,d;if(c&&!X(c))c=ba[this.type].animation;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99},c),this.animate=null)},afterAnimate:function(){this.setClip();H(this,"afterAnimate")},
	drawPoints:function(){var a,b=this.points,c=this.chart,d,e,f,g,h,i,k,j,l=this.options.marker,m=this.pointAttr[""],n,q,o,y=this.markerGroup,r=p(l.enabled,this.xAxis.isRadial,this.closestPointRangePx>2*l.radius);if(l.enabled!==!1||this._hasPointMarkers)for(f=b.length;f--;)if(g=b[f],d=T(g.plotX),e=g.plotY,j=g.graphic,n=g.marker||{},q=!!g.marker,a=r&&n.enabled===z||n.enabled,o=g.isInside,a&&e!==z&&!isNaN(e)&&g.y!==null)if(a=g.pointAttr[g.selected?"select":""]||m,h=a.r,i=p(n.symbol,this.symbol),k=i.indexOf("url")===
	0,j)j[o?"show":"hide"](!0).attr(a).animate(s({x:d-h,y:e-h},j.symbolName?{width:2*h,height:2*h}:{}));else{if(o&&(h>0||k))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h,q?n:l).attr(a).add(y)}else if(j)g.graphic=j.destroy()},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=p(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=a.options,c=ba[a.type].marker?b.marker:b,d=c.states,e=d.hover,f,g=a.color,h=a.options.negativeColor;
	f={stroke:g,fill:g};var i=a.points||[],k,j,l=[],m=a.pointAttrToOptions;k=a.hasPointSpecificOptions;var n=c.lineColor,q=c.fillColor;j=b.turboThreshold;var v=a.zones,y=a.zoneAxis||"y",t;b.marker?(e.radius=e.radius||c.radius+e.radiusPlus,e.lineWidth=e.lineWidth||c.lineWidth+e.lineWidthPlus):(e.color=e.color||ja(e.color||g).brighten(e.brightness).get(),e.negativeColor=e.negativeColor||ja(e.negativeColor||h).brighten(e.brightness).get());l[""]=a.convertAttribs(c,f);o(["hover","select"],function(b){l[b]=
	a.convertAttribs(d[b],l[""])});a.pointAttr=l;g=i.length;if(!j||g<j||k)for(;g--;){j=i[g];if((c=j.options&&j.options.marker||j.options)&&c.enabled===!1)c.radius=0;if(v.length){k=0;for(f=v[k];j[y]>=f.value;)f=v[++k];j.color=j.fillColor=p(f.color,a.color)}k=b.colorByPoint||j.color;if(j.options)for(t in m)r(c[m[t]])&&(k=!0);if(k){c=c||{};k=[];d=c.states||{};f=d.hover=d.hover||{};if(!b.marker||j.negative&&!f.fillColor&&!e.fillColor)f[a.pointAttrToOptions.fill]=f.color||!j.options.color&&e[j.negative&&h?
	"negativeColor":"color"]||ja(j.color).brighten(f.brightness||e.brightness).get();f={color:j.color};if(!q)f.fillColor=j.color;if(!n)f.lineColor=j.color;c.hasOwnProperty("color")&&!c.color&&delete c.color;k[""]=a.convertAttribs(s(f,c),l[""]);k.hover=a.convertAttribs(d.hover,l.hover,k[""]);k.select=a.convertAttribs(d.select,l.select,k[""])}else k=l;j.pointAttr=k}},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(za),d,e=a.data||[],f,g,h;H(a,"destroy");V(a);o(a.axisTypes||[],function(b){if(h=
	a[b])na(h.series,a),h.isDirty=h.forceRedraw=!0});a.legendItem&&a.chart.legend.destroyItem(a);for(d=e.length;d--;)(f=e[d])&&f.destroy&&f.destroy();a.points=null;clearTimeout(a.animationTimeout);for(g in a)a[g]instanceof P&&!a[g].survive&&(d=c&&g==="group"?"hide":"destroy",a[g][d]());if(b.hoverSeries===a)b.hoverSeries=null;na(b.series,a);for(g in a)delete a[g]},getGraphPath:function(a,b,c){var d=this,e=d.options,f=e.step,g,h=[],i,a=a||d.points;(g=a.reversed)&&a.reverse();(f={right:1,center:2}[f]||f&&
	3)&&g&&(f=4-f);e.connectNulls&&!b&&!c&&(a=this.getValidPoints(a));o(a,function(g,j){var l=g.plotX,m=g.plotY,n=a[j-1];if((g.leftCliff||n&&n.rightCliff)&&!c)i=!0;g.isNull&&!r(b)&&j>0?i=!e.connectNulls:g.isNull&&!b?i=!0:(j===0||i?n=["M",g.plotX,g.plotY]:d.getPointSpline?n=d.getPointSpline(a,g,j):f?(n=f===1?["L",n.plotX,m]:f===2?["L",(n.plotX+l)/2,n.plotY,"L",(n.plotX+l)/2,m]:["L",l,n.plotY],n.push("L",l,m)):n=["L",l,m],h.push.apply(h,n),i=!1)});return d.graphPath=h},drawGraph:function(){var a=this,b=
	this.options,c=[["graph",b.lineColor||this.color,b.dashStyle]],d=b.lineWidth,e=b.linecap!=="square",f=(this.gappedPath||this.getGraphPath).call(this),g=this.fillGraph&&this.color||"none";o(this.zones,function(d,e){c.push(["zoneGraph"+e,d.color||a.color,d.dashStyle||b.dashStyle])});o(c,function(c,i){var k=c[0],j=a[k];if(j)j.animate({d:f});else if((d||g)&&f.length)j={stroke:c[1],"stroke-width":d,fill:g,zIndex:1},c[2]?j.dashstyle=c[2]:e&&(j["stroke-linecap"]=j["stroke-linejoin"]="round"),a[k]=a.chart.renderer.path(f).attr(j).add(a.group).shadow(i<
	2&&b.shadow)})},applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,f,g=this.clips||[],h,i=this.graph,k=this.area,j=t(b.chartWidth,b.chartHeight),l=this[(this.zoneAxis||"y")+"Axis"],m,n=l.reversed,q=b.inverted,v=l.horiz,y,r,x,u=!1;if(d.length&&(i||k)&&l.min!==z)i&&i.hide(),k&&k.hide(),m=l.getExtremes(),o(d,function(d,o){e=n?v?b.plotWidth:0:v?0:l.toPixels(m.min);e=E(t(p(f,e),0),j);f=E(t(B(l.toPixels(p(d.value,m.max),!0)),0),j);u&&(e=f=l.toPixels(m.max));y=Math.abs(e-f);r=E(e,
	f);x=t(e,f);if(l.isXAxis){if(h={x:q?x:r,y:0,width:y,height:j},!v)h.x=b.plotHeight-h.x}else if(h={x:0,y:q?x:r,width:j,height:y},v)h.y=b.plotWidth-h.y;b.inverted&&c.isVML&&(h=l.isXAxis?{x:0,y:n?r:x,height:h.width,width:b.chartWidth}:{x:h.y-b.plotLeft-b.spacingBox.x,y:0,width:h.height,height:b.chartHeight});g[o]?g[o].animate(h):(g[o]=c.clipRect(h),i&&a["zoneGraph"+o].clip(g[o]),k&&a["zoneArea"+o].clip(g[o]));u=d.value>m.max}),this.clips=g},invertGroups:function(){function a(){var a={width:b.yAxis.len,
	height:b.xAxis.len};o(["group","markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;if(b.xAxis)N(c,"resize",a),N(b,"destroy",function(){V(c,"resize",a)}),a(),b.invertGroups=a},plotGroup:function(a,b,c,d,e){var f=this[a],g=!f;g&&(this[a]=f=this.chart.renderer.g(b).attr({zIndex:d||0.1}).add(e),f.addClass("highcharts-series-"+this.index));f.attr({visibility:c})[g?"attr":"animate"](this.getPlotBox());return f},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;if(a.inverted)b=
	c,c=this.xAxis;return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&$a(d.animation).duration,f=a.visible?"inherit":"hidden",g=d.zIndex,h=a.hasRendered,i=b.seriesGroup;c=a.plotGroup("group","series",f,g,i);a.markerGroup=a.plotGroup("markerGroup","markers",f,g,i);e&&a.animate(!0);a.getAttribs();c.inverted=a.isCartesian?b.inverted:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());o(a.points,
	function(a){a.redraw&&a.redraw()});a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&a.options.enableMouseTracking!==!1&&a.drawTracker();b.inverted&&a.invertGroups();d.clip!==!1&&!a.sharedClipKey&&!h&&c.clip(b.clipRect);e&&a.animate();if(!h)a.animationTimeout=Oa(function(){a.afterAnimate()},e);a.isDirty=a.isDirtyData=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.isDirty,d=this.group,e=this.xAxis,f=this.yAxis;d&&(a.inverted&&d.attr({width:a.plotWidth,
	height:a.plotHeight}),d.animate({translateX:p(e&&e.left,a.plotLeft),translateY:p(f&&f.top,a.plotTop)}));this.translate();this.render();b&&H(this,"updatedData");(c||b)&&delete this.kdTree},kdDimensions:1,kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,e,f){var g,h;if(h=c&&c.length)return g=
	b.kdAxisArray[e%f],c.sort(function(a,b){return a[g]-b[g]}),h=Math.floor(h/2),{point:c[h],left:a(c.slice(0,h),e+1,f),right:a(c.slice(h+1),e+1,f)}}var b=this,c=b.kdDimensions;delete b.kdTree;Oa(function(){b.kdTree=a(b.getValidPoints(null,!b.directTouch),c,c)},b.options.kdNow?0:1)},searchKDTree:function(a,b){function c(a,b,k,j){var l=b.point,m=d.kdAxisArray[k%j],n,q,o=l;q=r(a[e])&&r(l[e])?Math.pow(a[e]-l[e],2):null;n=r(a[f])&&r(l[f])?Math.pow(a[f]-l[f],2):null;n=(q||0)+(n||0);l.dist=r(n)?Math.sqrt(n):
	Number.MAX_VALUE;l.distX=r(q)?Math.sqrt(q):Number.MAX_VALUE;m=a[m]-l[m];n=m<0?"left":"right";q=m<0?"right":"left";b[n]&&(n=c(a,b[n],k+1,j),o=n[g]<o[g]?n:l);b[q]&&Math.sqrt(m*m)<o[g]&&(a=c(a,b[q],k+1,j),o=a[g]<o[g]?a:o);return o}var d=this,e=this.kdAxisArray[0],f=this.kdAxisArray[1],g=b?"distX":"dist";this.kdTree||this.buildKDTree();if(this.kdTree)return c(a,this.kdTree,this.kdDimensions,this.kdDimensions)}};Jb.prototype={destroy:function(){Ra(this,this.axis)},render:function(a){var b=this.options,
	c=b.format,c=c?Ja(c,this):b.formatter.call(this);this.label?this.label.attr({text:c,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(c,null,null,b.useHTML).css(b.style).attr({align:this.textAlign,rotation:b.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=c.reversed,f=this.isNegative&&!f||!this.isNegative&&f,g=c.translate(c.usePercentage?100:this.total,0,0,0,1),c=c.translate(0),c=Q(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,
	f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};if(e=this.label)e.align(this.alignOptions,null,f),f=e.alignAttr,e[this.options.crop===!1||d.isInsidePlot(f.x,f.y)?"show":"hide"](!0)}};gb.prototype.getStacks=function(){var a=this;o(a.yAxis,function(a){if(a.stacks&&a.hasVisibleSeries)a.oldStacks=a.stacks});o(a.series,function(b){if(b.options.stacking&&(b.visible===!0||a.options.chart.ignoreHiddenSeries===!1))b.stackKey=b.type+p(b.options.stack,"")})};fa.prototype.buildStacks=function(){var a=
	this.series,b,c=p(this.options.reversedStacks,!0),d=a.length,e;if(!this.isXAxis){this.usePercentage=!1;for(e=d;e--;)a[c?e:d-e-1].setStackedPoints();for(e=d;e--;)b=a[c?e:d-e-1],b.setStackCliffs&&b.setStackCliffs();if(this.usePercentage)for(e=0;e<d;e++)a[e].setPercentStacks()}};fa.prototype.renderStackTotals=function(){var a=this.chart,b=a.renderer,c=this.stacks,d,e,f=this.stackTotalGroup;if(!f)this.stackTotalGroup=f=b.g("stack-labels").attr({visibility:"visible",zIndex:6}).add();f.translate(a.plotLeft,
	a.plotTop);for(d in c)for(e in a=c[d],a)a[e].render(f)};fa.prototype.resetStacks=function(){var a=this.stacks,b,c;if(!this.isXAxis)for(b in a)for(c in a[b])a[b][c].touched<this.stacksTouched?(a[b][c].destroy(),delete a[b][c]):(a[b][c].total=null,a[b][c].cum=0)};fa.prototype.cleanStacks=function(){var a,b,c;if(!this.isXAxis){if(this.oldStacks)a=this.stacks=this.oldStacks;for(b in a)for(c in a[b])a[b][c].cum=a[b][c].total}};R.prototype.setStackedPoints=function(){if(this.options.stacking&&!(this.visible!==
	!0&&this.chart.options.chart.ignoreHiddenSeries!==!1)){var a=this.processedXData,b=this.processedYData,c=[],d=b.length,e=this.options,f=e.threshold,g=e.startFromThreshold?f:0,h=e.stack,e=e.stacking,i=this.stackKey,k="-"+i,j=this.negStacks,l=this.yAxis,m=l.stacks,n=l.oldStacks,q,o,y,r,x,u,s;l.stacksTouched+=1;for(x=0;x<d;x++){u=a[x];s=b[x];q=this.getStackIndicator(q,u,this.index);r=q.key;y=(o=j&&s<(g?0:f))?k:i;m[y]||(m[y]={});if(!m[y][u])n[y]&&n[y][u]?(m[y][u]=n[y][u],m[y][u].total=null):m[y][u]=new Jb(l,
	l.options.stackLabels,o,u,h);y=m[y][u];if(s!==null)y.points[r]=y.points[this.index]=[p(y.cum,g)],y.touched=l.stacksTouched,q.index>0&&this.singleStacks===!1&&(y.points[r][0]=y.points[this.index+","+u+",0"][0]);e==="percent"?(o=o?i:k,j&&m[o]&&m[o][u]?(o=m[o][u],y.total=o.total=t(o.total,y.total)+Q(s)||0):y.total=da(y.total+(Q(s)||0))):y.total=da(y.total+(s||0));y.cum=p(y.cum,g)+(s||0);if(s!==null)y.points[r].push(y.cum),c[x]=y.cum}if(e==="percent")l.usePercentage=!0;this.stackedYData=c;l.oldStacks=
	{}}};R.prototype.setPercentStacks=function(){var a=this,b=a.stackKey,c=a.yAxis.stacks,d=a.processedXData,e;o([b,"-"+b],function(b){var f;for(var g=d.length,h,i;g--;)if(h=d[g],e=a.getStackIndicator(e,h,a.index),f=(i=c[b]&&c[b][h])&&i.points[e.key],h=f)i=i.total?100/i.total:0,h[0]=da(h[0]*i),h[1]=da(h[1]*i),a.stackedYData[g]=h[1]})};R.prototype.getStackIndicator=function(a,b,c){!r(a)||a.x!==b?a={x:b,index:0}:a.index++;a.key=[c,b,a.index].join(",");return a};s(gb.prototype,{addSeries:function(a,b,c){var d,
	e=this;a&&(b=p(b,!0),H(e,"addSeries",{options:a},function(){d=e.initSeries(a);e.isDirtyLegend=!0;e.linkSeries();b&&e.redraw(c)}));return d},addAxis:function(a,b,c,d){var e=b?"xAxis":"yAxis",f=this.options,a=D(a,{index:this[e].length,isX:b});new fa(this,a);f[e]=ta(f[e]||{});f[e].push(a);p(c,!0)&&this.redraw(d)},showLoading:function(a){var b=this,c=b.options,d=b.loadingDiv,e=c.loading,f=function(){d&&L(d,{left:b.plotLeft+"px",top:b.plotTop+"px",width:b.plotWidth+"px",height:b.plotHeight+"px"})};if(!d)b.loadingDiv=
	d=$(Ka,{className:"highcharts-loading"},s(e.style,{zIndex:10,display:"none"}),b.container),b.loadingSpan=$("span",null,e.labelStyle,d),N(b,"redraw",f);b.loadingSpan.innerHTML=a||c.lang.loading;if(!b.loadingShown)L(d,{opacity:0,display:""}),Wa(d,{opacity:e.style.opacity},{duration:e.showDuration||0}),b.loadingShown=!0;f()},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&Wa(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){L(b,{display:"none"})}});this.loadingShown=
	!1}});s(Ia.prototype,{update:function(a,b,c,d){function e(){f.applyOptions(a);if(f.y===null&&h)f.graphic=h.destroy();if(X(a)&&!Da(a))f.redraw=function(){if(h&&h.element&&a&&a.marker&&a.marker.symbol)f.graphic=h.destroy();if(a&&a.dataLabels&&f.dataLabel)f.dataLabel=f.dataLabel.destroy();f.redraw=null};i=f.index;g.updateParallelArrays(f,i);if(l&&f.name)l[f.x]=f.name;j.data[i]=X(j.data[i])&&!Da(j.data[i])?f.options:a;g.isDirty=g.isDirtyData=!0;if(!g.fixedBox&&g.hasCartesianSeries)k.isDirtyBox=!0;if(j.legendType===
	"point")k.isDirtyLegend=!0;b&&k.redraw(c)}var f=this,g=f.series,h=f.graphic,i,k=g.chart,j=g.options,l=g.xAxis&&g.xAxis.names,b=p(b,!0);d===!1?e():f.firePointEvent("update",{options:a},e)},remove:function(a,b){this.series.removePoint(ra(this,this.series.data),a,b)}});s(R.prototype,{addPoint:function(a,b,c,d){var e=this,f=e.options,g=e.data,h=e.graph,i=e.area,k=e.chart,j=e.xAxis&&e.xAxis.names,l=h&&h.shift||0,m=["graph","area"],h=f.data,n,q=e.xData;Ta(d,k);if(c){for(d=e.zones.length;d--;)m.push("zoneGraph"+
	d,"zoneArea"+d);o(m,function(a){if(e[a])e[a].shift=l+(f.step?2:1)})}if(i)i.isArea=!0;b=p(b,!0);i={series:e};e.pointClass.prototype.applyOptions.apply(i,[a]);m=i.x;d=q.length;if(e.requireSorting&&m<q[d-1])for(n=!0;d&&q[d-1]>m;)d--;e.updateParallelArrays(i,"splice",d,0,0);e.updateParallelArrays(i,d);if(j&&i.name)j[m]=i.name;h.splice(d,0,a);n&&(e.data.splice(d,0,null),e.processData());f.legendType==="point"&&e.generatePoints();c&&(g[0]&&g[0].remove?g[0].remove(!1):(g.shift(),e.updateParallelArrays(i,
	"shift"),h.shift()));e.isDirty=!0;e.isDirtyData=!0;b&&(e.getAttribs(),k.redraw())},removePoint:function(a,b,c){var d=this,e=d.data,f=e[a],g=d.points,h=d.chart,i=function(){g&&g.length===e.length&&g.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(f||{series:d},"splice",a,1);f&&f.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&h.redraw()};Ta(c,h);b=p(b,!0);f?f.firePointEvent("remove",null,i):i()},remove:function(a,b){var c=this,d=c.chart;H(c,"remove",null,function(){c.destroy();
	d.isDirtyLegend=d.isDirtyBox=!0;d.linkSeries();p(a,!0)&&d.redraw(b)})},update:function(a,b){var c=this,d=this.chart,e=this.userOptions,f=this.type,g=I[f].prototype,h=["group","markerGroup","dataLabelsGroup"],i;if(a.type&&a.type!==f||a.zIndex!==void 0)h.length=0;o(h,function(a){h[a]=c[a];delete c[a]});a=D(e,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1);for(i in g)this[i]=z;s(this,I[a.type||f].prototype);o(h,function(a){c[a]=h[a]});this.init(d,
	a);d.linkSeries();p(b,!0)&&d.redraw(!1)}});s(fa.prototype,{update:function(a,b){var c=this.chart,a=c.options[this.coll][this.options.index]=D(this.userOptions,a);this.destroy(!0);this._addedPlotLB=this.chart._labelPanes=z;this.init(c,s(a,{events:z}));c.isDirtyBox=!0;p(b,!0)&&c.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,d=this.series,e=d.length;e--;)d[e]&&d[e].remove(!1);na(b.axes,this);na(b[c],this);b.options[c].splice(this.options.index,1);o(b[c],function(a,b){a.options.index=
	b});this.destroy();b.isDirtyBox=!0;p(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}});var wa=oa(R);I.line=wa;ba.area=D(ea,{softThreshold:!1,threshold:0});var la=oa(R,{type:"area",singleStacks:!1,getStackPoints:function(){var a=[],b=[],c=this.xAxis,d=this.yAxis,e=d.stacks[this.stackKey],f={},g=this.points,h=this.index,i=d.series,k=i.length,j,l=p(d.options.reversedStacks,!0)?1:-1,m,n;if(this.options.stacking){for(m=0;m<
	g.length;m++)f[g[m].x]=g[m];for(n in e)e[n].total!==null&&b.push(n);b.sort(function(a,b){return a-b});j=Ba(i,function(){return this.visible});o(b,function(g,i){var n=0,p,r;if(f[g]&&!f[g].isNull)a.push(f[g]),o([-1,1],function(a){var c=a===1?"rightNull":"leftNull",d=0,n=e[b[i+a]];if(n)for(m=h;m>=0&&m<k;)p=n.points[m],p||(m===h?f[g][c]=!0:j[m]&&(r=e[g].points[m])&&(d-=r[1]-r[0])),m+=l;f[g][a===1?"rightCliff":"leftCliff"]=d});else{for(m=h;m>=0&&m<k;){if(p=e[g].points[m]){n=p[1];break}m+=l}n=d.toPixels(n,
	!0);a.push({isNull:!0,plotX:c.toPixels(g,!0),plotY:n,yBottom:n})}})}return a},getGraphPath:function(a){var b=R.prototype.getGraphPath,c=this.options,d=c.stacking,e=this.yAxis,f,g,h=[],i=[],k=this.index,j,l=e.stacks[this.stackKey],m=c.threshold,n=e.getThreshold(c.threshold),q,c=c.connectNulls||d==="percent",o=function(b,c,f){var g=a[b],b=d&&l[g.x].points[k],q=g[f+"Null"]||0,f=g[f+"Cliff"]||0,o,p,g=!0;f||q?(o=(q?b[0]:b[1])+f,p=b[0]+f,g=!!q):!d&&a[c]&&a[c].isNull&&(o=p=m);o!==void 0&&(i.push({plotX:j,
	plotY:o===null?n:e.getThreshold(o),isNull:g}),h.push({plotX:j,plotY:p===null?n:e.getThreshold(p)}))},a=a||this.points;d&&(a=this.getStackPoints());for(f=0;f<a.length;f++)if(g=a[f].isNull,j=p(a[f].rectPlotX,a[f].plotX),q=p(a[f].yBottom,n),!g||c){c||o(f,f-1,"left");if(!g||d||!c)i.push(a[f]),h.push({x:f,plotX:j,plotY:q});c||o(f,f+1,"right")}f=b.call(this,i,!0,!0);h.reversed=!0;g=b.call(this,h,!0,!0);g.length&&(g[0]="L");f=f.concat(g);b=b.call(this,i,!1,c);this.areaPath=f;return b},drawGraph:function(){this.areaPath=
	[];R.prototype.drawGraph.apply(this);var a=this,b=this.areaPath,c=this.options,d=[["area",this.color,c.fillColor]];o(this.zones,function(b,f){d.push(["zoneArea"+f,b.color||a.color,b.fillColor||c.fillColor])});o(d,function(d){var f=d[0],g=a[f];g?g.animate({d:b}):(g={fill:d[2]||d[1],zIndex:0},d[2]||(g["fill-opacity"]=p(c.fillOpacity,0.75)),a[f]=a.chart.renderer.path(b).attr(g).add(a.group))})},drawLegendSymbol:M.drawRectangle});I.area=la;ba.spline=D(ea);wa=oa(R,{type:"spline",getPointSpline:function(a,
	b,c){var d=b.plotX,e=b.plotY,f=a[c-1],c=a[c+1],g,h,i,k;if(f&&!f.isNull&&c&&!c.isNull){a=f.plotY;i=c.plotX;var c=c.plotY,j=0;g=(1.5*d+f.plotX)/2.5;h=(1.5*e+a)/2.5;i=(1.5*d+i)/2.5;k=(1.5*e+c)/2.5;i!==g&&(j=(k-h)*(i-d)/(i-g)+e-k);h+=j;k+=j;h>a&&h>e?(h=t(a,e),k=2*e-h):h<a&&h<e&&(h=E(a,e),k=2*e-h);k>c&&k>e?(k=t(c,e),h=2*e-k):k<c&&k<e&&(k=E(c,e),h=2*e-k);b.rightContX=i;b.rightContY=k}b=["C",p(f.rightContX,f.plotX),p(f.rightContY,f.plotY),p(g,d),p(h,e),d,e];f.rightContX=f.rightContY=null;return b}});I.spline=
	wa;ba.areaspline=D(ba.area);la=la.prototype;wa=oa(wa,{type:"areaspline",getStackPoints:la.getStackPoints,getGraphPath:la.getGraphPath,setStackCliffs:la.setStackCliffs,drawGraph:la.drawGraph,drawLegendSymbol:M.drawRectangle});I.areaspline=wa;ba.column=D(ea,{borderColor:"#FFFFFF",borderRadius:0,groupPadding:0.2,marker:null,pointPadding:0.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{brightness:0.1,shadow:!1,halo:!1},select:{color:"#C0C0C0",borderColor:"#000000",shadow:!1}},dataLabels:{align:null,
	verticalAlign:null,y:null},softThreshold:!1,startFromThreshold:!0,stickyTracking:!1,tooltip:{distance:6},threshold:0});wa=oa(R,{type:"column",pointAttrToOptions:{stroke:"borderColor",fill:"color",r:"borderRadius"},cropShoulder:0,directTouch:!0,trackerGroups:["group","dataLabelsGroup"],negStacks:!0,init:function(){R.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&o(b.series,function(b){if(b.type===a.type)b.isDirty=!0})},getColumnMetrics:function(){var a=this,b=a.options,c=
	a.xAxis,d=a.yAxis,e=c.reversed,f,g={},h=0;b.grouping===!1?h=1:o(a.chart.series,function(b){var c=b.options,e=b.yAxis,i;if(b.type===a.type&&b.visible&&d.len===e.len&&d.pos===e.pos)c.stacking?(f=b.stackKey,g[f]===z&&(g[f]=h++),i=g[f]):c.grouping!==!1&&(i=h++),b.columnIndex=i});var i=E(Q(c.transA)*(c.ordinalSlope||b.pointRange||c.closestPointRange||c.tickInterval||1),c.len),k=i*b.groupPadding,j=(i-2*k)/h,b=E(b.maxPointWidth||c.len,p(b.pointWidth,j*(1-2*b.pointPadding)));a.columnMetrics={width:b,offset:(j-
	b)/2+(k+((a.columnIndex||0)+(e?1:0))*j-i/2)*(e?-1:1)};return a.columnMetrics},crispCol:function(a,b,c,d){var e=this.chart,f=this.borderWidth,g=-(f%2?0.5:0),f=f%2?0.5:1;e.inverted&&e.renderer.isVML&&(f+=1);c=Math.round(a+c)+g;a=Math.round(a)+g;c-=a;d=Math.round(b+d)+f;g=Q(b)<=0.5&&d>0.5;b=Math.round(b)+f;d-=b;g&&d&&(b-=1,d+=1);return{x:a,y:b,width:c,height:d}},translate:function(){var a=this,b=a.chart,c=a.options,d=a.borderWidth=p(c.borderWidth,a.closestPointRange*a.xAxis.transA<2?0:1),e=a.yAxis,f=
	a.translatedThreshold=e.getThreshold(c.threshold),g=p(c.minPointLength,5),h=a.getColumnMetrics(),i=h.width,k=a.barW=t(i,1+2*d),j=a.pointXOffset=h.offset;b.inverted&&(f-=0.5);c.pointPadding&&(k=ua(k));R.prototype.translate.apply(a);o(a.points,function(c){var d=E(p(c.yBottom,f),9E4),h=999+Q(d),h=E(t(-h,c.plotY),e.len+h),o=c.plotX+j,r=k,s=E(h,d),w,x=t(h,d)-s;Q(x)<g&&g&&(x=g,w=!e.reversed&&!c.negative||e.reversed&&c.negative,s=Q(s-f)>g?d-g:f-(w?g:0));c.barX=o;c.pointWidth=i;c.tooltipPos=b.inverted?[e.len+
	e.pos-b.plotLeft-h,a.xAxis.len-o-r/2,x]:[o+r/2,h+e.pos-b.plotTop,x];c.shapeType="rect";c.shapeArgs=a.crispCol(o,s,r,x)})},getSymbol:Aa,drawLegendSymbol:M.drawRectangle,drawGraph:Aa,drawPoints:function(){var a=this,b=this.chart,c=a.options,d=b.renderer,e=c.animationLimit||250,f,g;o(a.points,function(h){var i=h.plotY,k=h.graphic;if(i!==z&&!isNaN(i)&&h.y!==null)f=h.shapeArgs,i=r(a.borderWidth)?{"stroke-width":a.borderWidth}:{},g=h.pointAttr[h.selected?"select":""]||a.pointAttr[""],k?(Na(k),k.attr(i).attr(g)[b.pointCount<
	e?"animate":"attr"](D(f))):h.graphic=d[h.shapeType](f).attr(i).attr(g).add(h.group||a.group).shadow(c.shadow,null,c.stacking&&!c.borderRadius);else if(k)h.graphic=k.destroy()})},animate:function(a){var b=this,c=this.yAxis,d=b.options,e=this.chart.inverted,f={};if(ca)a?(f.scaleY=0.001,a=E(c.pos+c.len,t(c.pos,c.toPixels(d.threshold))),e?f.translateX=a-c.len:f.translateY=a,b.group.attr(f)):(f[e?"translateX":"translateY"]=c.pos,b.group.animate(f,s($a(b.options.animation),{step:function(a,c){b.group.attr({scaleY:c.pos})}})),
	b.animate=null)},remove:function(){var a=this,b=a.chart;b.hasRendered&&o(b.series,function(b){if(b.type===a.type)b.isDirty=!0});R.prototype.remove.apply(a,arguments)}});I.column=wa;ba.bar=D(ba.column);la=oa(wa,{type:"bar",inverted:!0});I.bar=la;ba.scatter=D(ea,{lineWidth:0,marker:{enabled:!0},tooltip:{headerFormat:'<span style="color:{point.color}">\u25cf</span> <span style="font-size: 10px;"> {series.name}</span><br/>',pointFormat:"x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>"}});la=oa(R,{type:"scatter",
	sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","markerGroup","dataLabelsGroup"],takeOrdinalPosition:!1,kdDimensions:2,drawGraph:function(){this.options.lineWidth&&R.prototype.drawGraph.call(this)}});I.scatter=la;ba.pie=D(ea,{borderColor:"#FFFFFF",borderWidth:1,center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.y===null?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,
	slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}});ea={type:"pie",isCartesian:!1,pointClass:oa(Ia,{init:function(){Ia.prototype.init.apply(this,arguments);var a=this,b;a.name=p(a.name,"Slice");b=function(b){a.slice(b.type==="select")};N(a,"select",b);N(a,"unselect",b);return a},setVisible:function(a,b){var c=this,d=c.series,e=d.chart,f=d.options.ignoreHiddenPoint,b=p(b,f);if(a!==c.visible){c.visible=c.options.visible=a=a===z?!c.visible:a;d.options.data[ra(c,
	d.data)]=c.options;o(["graphic","dataLabel","connector","shadowGroup"],function(b){if(c[b])c[b][a?"show":"hide"](!0)});c.legendItem&&e.legend.colorizeItem(c,a);!a&&c.state==="hover"&&c.setState("");if(f)d.isDirty=!0;b&&e.redraw()}},slice:function(a,b,c){var d=this.series;Ta(c,d.chart);p(b,!0);this.sliced=this.options.sliced=a=r(a)?a:!this.sliced;d.options.data[ra(this,d.data)]=this.options;a=a?this.slicedTranslation:{translateX:0,translateY:0};this.graphic.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)},
	haloPath:function(a){var b=this.shapeArgs,c=this.series.chart;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.plotLeft+b.x,c.plotTop+b.y,b.r+a,b.r+a,{innerR:this.shapeArgs.r,start:b.start,end:b.end})}}),requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},animate:function(a){var b=this,c=b.points,d=b.startAngleRad;if(!a)o(c,function(a){var c=
	a.graphic,g=a.shapeArgs;c&&(c.attr({r:a.startR||b.center[3]/2,start:d,end:d}),c.animate({r:g.r,start:g.start,end:g.end},b.options.animation))}),b.animate=null},updateTotals:function(){var a,b=0,c=this.points,d=c.length,e,f=this.options.ignoreHiddenPoint;for(a=0;a<d;a++)e=c[a],b+=f&&!e.visible?0:e.y;this.total=b;for(a=0;a<d;a++)e=c[a],e.percentage=b>0&&(e.visible||!f)?e.y/b*100:0,e.total=b},generatePoints:function(){R.prototype.generatePoints.call(this);this.updateTotals()},translate:function(a){this.generatePoints();
	var b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f,g,h,i=c.startAngle||0,k=this.startAngleRad=qa/180*(i-90),i=(this.endAngleRad=qa/180*(p(c.endAngle,i+360)-90))-k,j=this.points,l=c.dataLabels.distance,c=c.ignoreHiddenPoint,m,n=j.length,o;if(!a)this.center=a=this.getCenter();this.getX=function(b,c){h=W.asin(E((b-a[1])/(a[2]/2+l),1));return a[0]+(c?-1:1)*U(h)*(a[2]/2+l)};for(m=0;m<n;m++){o=j[m];f=k+b*i;if(!c||o.visible)b+=o.percentage/100;g=k+b*i;o.shapeType="arc";o.shapeArgs={x:a[0],y:a[1],
	r:a[2]/2,innerR:a[3]/2,start:B(f*1E3)/1E3,end:B(g*1E3)/1E3};h=(g+f)/2;h>1.5*qa?h-=2*qa:h<-qa/2&&(h+=2*qa);o.slicedTranslation={translateX:B(U(h)*d),translateY:B(aa(h)*d)};f=U(h)*a[2]/2;g=aa(h)*a[2]/2;o.tooltipPos=[a[0]+f*0.7,a[1]+g*0.7];o.half=h<-qa/2||h>qa/2?1:0;o.angle=h;e=E(e,l/2);o.labelPos=[a[0]+f+U(h)*l,a[1]+g+aa(h)*l,a[0]+f+U(h)*e,a[1]+g+aa(h)*e,a[0]+f,a[1]+g,l<0?"center":o.half?"right":"left",h]}},drawGraph:null,drawPoints:function(){var a=this,b=a.chart.renderer,c,d,e=a.options.shadow,f,
	g,h,i;if(e&&!a.shadowGroup)a.shadowGroup=b.g("shadow").add(a.group);o(a.points,function(k){if(k.y!==null){d=k.graphic;h=k.shapeArgs;f=k.shadowGroup;g=k.pointAttr[k.selected?"select":""];if(!g.stroke)g.stroke=g.fill;if(e&&!f)f=k.shadowGroup=b.g("shadow").add(a.shadowGroup);c=k.sliced?k.slicedTranslation:{translateX:0,translateY:0};f&&f.attr(c);if(d)d.setRadialReference(a.center).attr(g).animate(s(h,c));else{i={"stroke-linejoin":"round"};if(!k.visible)i.visibility="hidden";k.graphic=d=b[k.shapeType](h).setRadialReference(a.center).attr(g).attr(i).attr(c).add(a.group).shadow(e,
	f)}}})},searchPoint:Aa,sortByAngle:function(a,b){a.sort(function(a,d){return a.angle!==void 0&&(d.angle-a.angle)*b})},drawLegendSymbol:M.drawRectangle,getCenter:Bb.getCenter,getSymbol:Aa};ea=oa(R,ea);I.pie=ea;R.prototype.drawDataLabels=function(){var a=this,b=a.options,c=b.cursor,d=b.dataLabels,e=a.points,f,g,h=a.hasRendered||0,i,k,j=p(d.defer,!0),l=a.chart.renderer;if(d.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(d),k=a.plotGroup("dataLabelsGroup","data-labels",j&&!h?"hidden":
	"visible",d.zIndex||6),j&&(k.attr({opacity:+h}),h||N(a,"afterAnimate",function(){a.visible&&k.show();k[b.animation?"animate":"attr"]({opacity:1},{duration:200})})),g=d,o(e,function(e){var h,j=e.dataLabel,o,t,w=e.connector,x=!0,u,B={};f=e.dlOptions||e.options&&e.options.dataLabels;h=p(f&&f.enabled,g.enabled)&&e.y!==null;if(j&&!h)e.dataLabel=j.destroy();else if(h){d=D(g,f);u=d.style;h=d.rotation;o=e.getLabelConfig();i=d.format?Ja(d.format,o):d.formatter.call(o,d);u.color=p(d.color,u.color,a.color,"black");
	if(j)if(r(i))j.attr({text:i}),x=!1;else{if(e.dataLabel=j=j.destroy(),w)e.connector=w.destroy()}else if(r(i)){j={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:h,padding:d.padding,zIndex:1};if(u.color==="contrast")B.color=d.inside||d.distance<0||b.stacking?l.getContrast(e.color||a.color):"#000000";if(c)B.cursor=c;for(t in j)j[t]===z&&delete j[t];j=e.dataLabel=l[h?"text":"label"](i,0,-9999,d.shape,null,null,d.useHTML).attr(j).css(s(u,B)).add(k).shadow(d.shadow)}j&&
	a.alignDataLabel(e,j,d,null,x)}})};R.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=p(a.plotX,-9999),i=p(a.plotY,-9999),k=b.getBBox(),j=f.renderer.fontMetrics(c.style.fontSize).b,l=c.rotation,m=c.align,n=this.visible&&(a.series.forceDL||f.isInsidePlot(h,B(i),g)||d&&f.isInsidePlot(h,g?d.x+1:d.y+d.height-1,g)),o=p(c.overflow,"justify")==="justify";if(n)d=s({x:g?f.plotWidth-i:h,y:B(g?f.plotHeight-h:i),width:0,height:0},d),s(c,{width:k.width,height:k.height}),l?(o=!1,g=f.renderer.rotCorr(j,
	l),g={x:d.x+c.x+d.width/2+g.x,y:d.y+c.y+d.height/2},b[e?"attr":"animate"](g).attr({align:c.align}),h=(l+720)%360,h=h>180&&h<360,m==="left"?g.y-=h?k.height:0:m==="center"?(g.x-=k.width/2,g.y-=k.height/2):m==="right"&&(g.x-=k.width,g.y-=h?0:k.height)):(b.align(c,null,d),g=b.alignAttr),o?this.justifyDataLabel(b,c,g,k,d,e):p(c.crop,!0)&&(n=f.isInsidePlot(g.x,g.y)&&f.isInsidePlot(g.x+k.width,g.y+k.height)),c.shape&&!l&&b.attr({anchorX:a.plotX,anchorY:a.plotY});if(!n)Na(b),b.attr({y:-9999}),b.placed=!1};
	R.prototype.justifyDataLabel=function(a,b,c,d,e,f){var g=this.chart,h=b.align,i=b.verticalAlign,k,j,l=a.box?0:a.padding||0;k=c.x+l;if(k<0)h==="right"?b.align="left":b.x=-k,j=!0;k=c.x+d.width-l;if(k>g.plotWidth)h==="left"?b.align="right":b.x=g.plotWidth-k,j=!0;k=c.y+l;if(k<0)i==="bottom"?b.verticalAlign="top":b.y=-k,j=!0;k=c.y+d.height-l;if(k>g.plotHeight)i==="top"?b.verticalAlign="bottom":b.y=g.plotHeight-k,j=!0;if(j)a.placed=!f,a.align(b,null,e)};if(I.pie)I.pie.prototype.drawDataLabels=function(){var a=
	this,b=a.data,c,d=a.chart,e=a.options.dataLabels,f=p(e.connectorPadding,10),g=p(e.connectorWidth,1),h=d.plotWidth,i=d.plotHeight,k,j,l=p(e.softConnector,!0),m=e.distance,n=a.center,q=n[2]/2,r=n[1],s=m>0,w,x,u,z=[[],[]],A,C,D,F,J,G=[0,0,0,0],L=function(a,b){return b.y-a.y};if(a.visible&&(e.enabled||a._hasPointLabels)){R.prototype.drawDataLabels.apply(a);o(b,function(a){if(a.dataLabel&&a.visible)z[a.half].push(a),a.dataLabel._pos=null});for(F=2;F--;){var H=[],N=[],I=z[F],M=I.length,K;if(M){a.sortByAngle(I,
	F-0.5);for(J=b=0;!b&&I[J];)b=I[J]&&I[J].dataLabel&&(I[J].dataLabel.getBBox().height||21),J++;if(m>0){x=E(r+q+m,d.plotHeight);for(J=t(0,r-q-m);J<=x;J+=b)H.push(J);x=H.length;if(M>x){c=[].concat(I);c.sort(L);for(J=M;J--;)c[J].rank=J;for(J=M;J--;)I[J].rank>=x&&I.splice(J,1);M=I.length}for(J=0;J<M;J++){c=I[J];u=c.labelPos;c=9999;var P,O;for(O=0;O<x;O++)P=Q(H[O]-u[1]),P<c&&(c=P,K=O);if(K<J&&H[J]!==null)K=J;else for(x<M-J+K&&H[J]!==null&&(K=x-M+J);H[K]===null;)K++;N.push({i:K,y:H[K]});H[K]=null}N.sort(L)}for(J=
	0;J<M;J++){c=I[J];u=c.labelPos;w=c.dataLabel;D=c.visible===!1?"hidden":"inherit";c=u[1];if(m>0){if(x=N.pop(),K=x.i,C=x.y,c>C&&H[K+1]!==null||c<C&&H[K-1]!==null)C=E(t(0,c),d.plotHeight)}else C=c;A=e.justify?n[0]+(F?-1:1)*(q+m):a.getX(C===r-q-m||C===r+q+m?c:C,F);w._attr={visibility:D,align:u[6]};w._pos={x:A+e.x+({left:f,right:-f}[u[6]]||0),y:C+e.y-10};w.connX=A;w.connY=C;if(this.options.size===null)x=w.width,A-x<f?G[3]=t(B(x-A+f),G[3]):A+x>h-f&&(G[1]=t(B(A+x-h+f),G[1])),C-b/2<0?G[0]=t(B(-C+b/2),G[0]):
	C+b/2>i&&(G[2]=t(B(C+b/2-i),G[2]))}}}if(Fa(G)===0||this.verifyDataLabelOverflow(G))this.placeDataLabels(),s&&g&&o(this.points,function(b){k=b.connector;u=b.labelPos;if((w=b.dataLabel)&&w._pos&&b.visible)D=w._attr.visibility,A=w.connX,C=w.connY,j=l?["M",A+(u[6]==="left"?5:-5),C,"C",A,C,2*u[2]-u[4],2*u[3]-u[5],u[2],u[3],"L",u[4],u[5]]:["M",A+(u[6]==="left"?5:-5),C,"L",u[2],u[3],"L",u[4],u[5]],k?(k.animate({d:j}),k.attr("visibility",D)):b.connector=k=a.chart.renderer.path(j).attr({"stroke-width":g,stroke:e.connectorColor||
	b.color||"#606060",visibility:D}).add(a.dataLabelsGroup);else if(k)b.connector=k.destroy()})}},I.pie.prototype.placeDataLabels=function(){o(this.points,function(a){var b=a.dataLabel;if(b&&a.visible)(a=b._pos)?(b.attr(b._attr),b[b.moved?"animate":"attr"](a),b.moved=!0):b&&b.attr({y:-9999})})},I.pie.prototype.alignDataLabel=Aa,I.pie.prototype.verifyDataLabelOverflow=function(a){var b=this.center,c=this.options,d=c.center,e=c.minSize||80,f=e,g;d[0]!==null?f=t(b[2]-t(a[1],a[3]),e):(f=t(b[2]-a[1]-a[3],
	e),b[0]+=(a[3]-a[1])/2);d[1]!==null?f=t(E(f,b[2]-t(a[0],a[2])),e):(f=t(E(f,b[2]-a[0]-a[2]),e),b[1]+=(a[0]-a[2])/2);f<b[2]?(b[2]=f,b[3]=Math.min(/%$/.test(c.innerSize||0)?f*parseFloat(c.innerSize||0)/100:parseFloat(c.innerSize||0),f),this.translate(b),this.drawDataLabels&&this.drawDataLabels()):g=!0;return g};if(I.column)I.column.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart.inverted,g=a.series,h=a.dlBox||a.shapeArgs,i=p(a.below,a.plotY>p(this.translatedThreshold,g.yAxis.len)),k=p(c.inside,
	!!this.options.stacking);if(h){d=D(h);if(d.y<0)d.height+=d.y,d.y=0;h=d.y+d.height-g.yAxis.len;h>0&&(d.height-=h);f&&(d={x:g.yAxis.len-d.y-d.height,y:g.xAxis.len-d.x-d.width,width:d.height,height:d.width});if(!k)f?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0)}c.align=p(c.align,!f||k?"center":i?"right":"left");c.verticalAlign=p(c.verticalAlign,f||k?"middle":i?"top":"bottom");R.prototype.alignDataLabel.call(this,a,b,c,d,e)};(function(a){var b=a.Chart,c=a.each,d=a.pick,e=a.addEvent;b.prototype.callbacks.push(function(a){function b(){var e=
	[];c(a.series,function(a){var b=a.options.dataLabels,f=a.dataLabelCollections||["dataLabel"];(b.enabled||a._hasPointLabels)&&!b.allowOverlap&&a.visible&&c(f,function(b){c(a.points,function(a){if(a[b])a[b].labelrank=d(a.labelrank,a.shapeArgs&&a.shapeArgs.height),e.push(a[b])})})});a.hideOverlappingLabels(e)}b();e(a,"redraw",b)});b.prototype.hideOverlappingLabels=function(a){var b=a.length,d,e,k,j,l,m,n,o,p;for(e=0;e<b;e++)if(d=a[e])d.oldOpacity=d.opacity,d.newOpacity=1;a.sort(function(a,b){return(b.labelrank||
	0)-(a.labelrank||0)});for(e=0;e<b;e++){k=a[e];for(d=e+1;d<b;++d)if(j=a[d],k&&j&&k.placed&&j.placed&&k.newOpacity!==0&&j.newOpacity!==0&&(l=k.alignAttr,m=j.alignAttr,n=k.parentGroup,o=j.parentGroup,p=2*(k.box?0:k.padding),l=!(m.x+o.translateX>l.x+n.translateX+(k.width-p)||m.x+o.translateX+(j.width-p)<l.x+n.translateX||m.y+o.translateY>l.y+n.translateY+(k.height-p)||m.y+o.translateY+(j.height-p)<l.y+n.translateY)))(k.labelrank<j.labelrank?k:j).newOpacity=0}c(a,function(a){var b,c;if(a){c=a.newOpacity;
	if(a.oldOpacity!==c&&a.placed)c?a.show(!0):b=function(){a.hide()},a.alignAttr.opacity=c,a[a.isOld?"animate":"attr"](a.alignAttr,null,b);a.isOld=!0}})}})(w);ea=w.TrackerMixin={drawTrackerPoint:function(){var a=this,b=a.chart,c=b.pointer,d=a.options.cursor,e=d&&{cursor:d},f=function(a){for(var c=a.target,d;c&&!d;)d=c.point,c=c.parentNode;if(d!==z&&d!==b.hoverPoint)d.onMouseOver(a)};o(a.points,function(a){if(a.graphic)a.graphic.element.point=a;if(a.dataLabel)a.dataLabel.element.point=a});if(!a._hasTracking)o(a.trackerGroups,
	function(b){if(a[b]&&(a[b].addClass("highcharts-tracker").on("mouseover",f).on("mouseout",function(a){c.onTrackerMouseOut(a)}).css(e),db))a[b].on("touchstart",f)}),a._hasTracking=!0},drawTrackerGraph:function(){var a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.pointer,h=f.renderer,i=f.options.tooltip.snap,k=a.tracker,j=b.cursor,l=j&&{cursor:j},m=function(){if(f.hoverSeries!==a)a.onMouseOver()},n="rgba(192,192,192,"+(ca?1.0E-4:0.002)+")";if(e&&!c)for(j=
	e+1;j--;)d[j]==="M"&&d.splice(j+1,0,d[j+1]-i,d[j+2],"L"),(j&&d[j]==="M"||j===e)&&d.splice(j,0,"L",d[j-2]+i,d[j-1]);k?k.attr({d:d}):(a.tracker=h.path(d).attr({"stroke-linejoin":"round",visibility:a.visible?"visible":"hidden",stroke:n,fill:c?n:"none","stroke-width":b.lineWidth+(c?0:2*i),zIndex:2}).add(a.group),o([a.tracker,a.markerGroup],function(a){a.addClass("highcharts-tracker").on("mouseover",m).on("mouseout",function(a){g.onTrackerMouseOut(a)}).css(l);if(db)a.on("touchstart",m)}))}};if(I.column)wa.prototype.drawTracker=
	ea.drawTrackerPoint;if(I.pie)I.pie.prototype.drawTracker=ea.drawTrackerPoint;if(I.scatter)la.prototype.drawTracker=ea.drawTrackerPoint;s(pb.prototype,{setItemEvents:function(a,b,c,d,e){var f=this;(c?b:a.legendGroup).on("mouseover",function(){a.setState("hover");b.css(f.options.itemHoverStyle)}).on("mouseout",function(){b.css(a.visible?d:e);a.setState()}).on("click",function(b){var c=function(){a.setVisible&&a.setVisible()},b={browserEvent:b};a.firePointEvent?a.firePointEvent("legendItemClick",b,c):
	H(a,"legendItemClick",b,c)})},createCheckboxForItem:function(a){a.checkbox=$("input",{type:"checkbox",checked:a.selected,defaultChecked:a.selected},this.options.itemCheckboxStyle,this.chart.container);N(a.checkbox,"click",function(b){H(a.series||a,"checkboxClick",{checked:b.target.checked,item:a},function(){a.select()})})}});S.legend.itemStyle.cursor="pointer";s(gb.prototype,{showResetZoom:function(){var a=this,b=S.lang,c=a.options.chart.resetZoomButton,d=c.theme,e=d.states,f=c.relativeTo==="chart"?
	null:"plotBox";this.resetZoomButton=a.renderer.button(b.resetZoom,null,null,function(){a.zoomOut()},d,e&&e.hover).attr({align:c.position.align,title:b.resetZoomTitle}).add().align(c.position,!1,f)},zoomOut:function(){var a=this;H(a,"selection",{resetSelection:!0},function(){a.zoom()})},zoom:function(a){var b,c=this.pointer,d=!1,e;!a||a.resetSelection?o(this.axes,function(a){b=a.zoom()}):o(a.xAxis.concat(a.yAxis),function(a){var e=a.axis,h=e.isXAxis;if(c[h?"zoomX":"zoomY"]||c[h?"pinchX":"pinchY"])b=
	e.zoom(a.min,a.max),e.displayBtn&&(d=!0)});e=this.resetZoomButton;if(d&&!e)this.showResetZoom();else if(!d&&X(e))this.resetZoomButton=e.destroy();b&&this.redraw(p(this.options.chart.animation,a&&a.animation,this.pointCount<100))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&o(d,function(a){a.setState()});o(b==="xy"?[1,0]:[1],function(b){var b=c[b?"xAxis":"yAxis"][0],d=b.horiz,h=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",i=c[d],k=(b.pointRange||0)/2,j=b.getExtremes(),l=b.toValue(i-h,
	!0)+k,k=b.toValue(i+b.len-h,!0)-k,i=i>h;if(b.series.length&&(i||l>E(j.dataMin,j.min))&&(!i||k<t(j.dataMax,j.max)))b.setExtremes(l,k,!1,!1,{trigger:"pan"}),e=!0;c[d]=h});e&&c.redraw(!1);L(c.container,{cursor:"move"})}});s(Ia.prototype,{select:function(a,b){var c=this,d=c.series,e=d.chart,a=p(a,!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=c.options.selected=a;d.options.data[ra(c,d.data)]=c.options;c.setState(a&&"select");b||o(e.getSelectedPoints(),function(a){if(a.selected&&
	a!==c)a.selected=a.options.selected=!1,d.options.data[ra(a,d.data)]=a.options,a.setState(""),a.firePointEvent("unselect")})})},onMouseOver:function(a,b){var c=this.series,d=c.chart,e=d.tooltip,f=d.hoverPoint;if(d.hoverSeries!==c)c.onMouseOver();if(f&&f!==this)f.onMouseOut();if(this.series&&(this.firePointEvent("mouseOver"),e&&(!e.shared||c.noSharedTooltip)&&e.refresh(this,a),this.setState("hover"),!b))d.hoverPoint=this},onMouseOut:function(){var a=this.series.chart,b=a.hoverPoints;this.firePointEvent("mouseOut");
	if(!b||ra(this,b)===-1)this.setState(),a.hoverPoint=null},importEvents:function(){if(!this.hasImportedEvents){var a=D(this.series.options.point,this.options).events,b;this.events=a;for(b in a)N(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a,b){var c=T(this.plotX),d=this.plotY,e=this.series,f=e.options.states,g=ba[e.type].marker&&e.options.marker,h=g&&!g.enabled,i=g&&g.states[a],k=i&&i.enabled===!1,j=e.stateMarkerGraphic,l=this.marker||{},m=e.chart,n=e.halo,o,a=a||"";o=this.pointAttr[a]||
	e.pointAttr[a];if(!(a===this.state&&!b||this.selected&&a!=="select"||f[a]&&f[a].enabled===!1||a&&(k||h&&i.enabled===!1)||a&&l.states&&l.states[a]&&l.states[a].enabled===!1)){if(this.graphic)g=g&&this.graphic.symbolName&&o.r,this.graphic.attr(D(o,g?{x:c-g,y:d-g,width:2*g,height:2*g}:{})),j&&j.hide();else{if(a&&i)if(g=i.radius,l=l.symbol||e.symbol,j&&j.currentSymbol!==l&&(j=j.destroy()),j)j[b?"animate":"attr"]({x:c-g,y:d-g});else if(l)e.stateMarkerGraphic=j=m.renderer.symbol(l,c-g,d-g,2*g,2*g).attr(o).add(e.markerGroup),
	j.currentSymbol=l;if(j)j[a&&m.isInsidePlot(c,d,m.inverted)?"show":"hide"](),j.element.point=this}if((c=f[a]&&f[a].halo)&&c.size){if(!n)e.halo=n=m.renderer.path().add(m.seriesGroup);n.attr(s({fill:this.color||e.color,"fill-opacity":c.opacity,zIndex:-1},c.attributes))[b?"animate":"attr"]({d:this.haloPath(c.size)})}else n&&n.attr({d:[]});this.state=a}},haloPath:function(a){var b=this.series,c=b.chart,d=b.getPlotBox(),e=c.inverted,f=Math.floor(this.plotX);return c.renderer.symbols.circle(d.translateX+
	(e?b.yAxis.len-this.plotY:f)-a,d.translateY+(e?b.xAxis.len-f:this.plotY)-a,a*2,a*2)}});s(R.prototype,{onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&H(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;b.hoverSeries=null;if(d)d.onMouseOut();this&&a.events.mouseOut&&H(this,"mouseOut");c&&!a.stickyTracking&&(!c.shared||this.noSharedTooltip)&&
	c.hide();this.setState()},setState:function(a){var b=this.options,c=this.graph,d=b.states,e=b.lineWidth,b=0,a=a||"";if(this.state!==a&&(this.state=a,!(d[a]&&d[a].enabled===!1)&&(a&&(e=d[a].lineWidth||e+(d[a].lineWidthPlus||0)),c&&!c.dashstyle))){a={"stroke-width":e};for(c.attr(a);this["zoneGraph"+b];)this["zoneGraph"+b].attr(a),b+=1}},setVisible:function(a,b){var c=this,d=c.chart,e=c.legendItem,f,g=d.options.chart.ignoreHiddenSeries,h=c.visible;f=(c.visible=a=c.userOptions.visible=a===z?!h:a)?"show":
	"hide";o(["group","dataLabelsGroup","markerGroup","tracker"],function(a){if(c[a])c[a][f]()});if(d.hoverSeries===c||(d.hoverPoint&&d.hoverPoint.series)===c)c.onMouseOut();e&&d.legend.colorizeItem(c,a);c.isDirty=!0;c.options.stacking&&o(d.series,function(a){if(a.options.stacking&&a.visible)a.isDirty=!0});o(c.linkedSeries,function(b){b.setVisible(a,!1)});if(g)d.isDirtyBox=!0;b!==!1&&d.redraw();H(c,f)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=
	a=a===z?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;H(this,a?"select":"unselect")},drawTracker:ea.drawTrackerGraph});s(w,{Color:ja,Point:Ia,Tick:Va,Renderer:cb,SVGElement:P,SVGRenderer:Ca,arrayMin:Qa,arrayMax:Fa,charts:O,correctFloat:da,dateFormat:Pa,error:Z,format:Ja,pathAnim:void 0,getOptions:function(){return S},hasBidiBug:Pb,isTouchDevice:Lb,setOptions:function(a){S=D(!0,S,a);Eb();return S},addEvent:N,removeEvent:V,createElement:$,discardElement:Sa,css:L,each:o,map:Ba,merge:D,splat:ta,
	stableSort:hb,extendClass:oa,pInt:F,svg:ca,canvas:ia,vml:!ca&&!ia,product:"Highcharts",version:"4.2.4"});return w});


/***/ },
/* 319 */
/***/ function(module, exports) {

	/*
	 Highcharts JS v4.2.3 (2016-02-08)

	 (c) 2009-2016 Torstein Honsi

	 License: www.highcharts.com/license
	*/
	(function(m){typeof module==="object"&&module.exports?module.exports=m:m(Highcharts)})(function(m){function J(a,b,c){this.init(a,b,c)}var O=m.arrayMin,P=m.arrayMax,s=m.each,F=m.extend,t=m.merge,Q=m.map,q=m.pick,A=m.pInt,o=m.getOptions().plotOptions,k=m.seriesTypes,u=m.extendClass,K=m.splat,v=m.wrap,L=m.Axis,y=m.Tick,G=m.Point,R=m.Pointer,S=m.CenteredSeriesMixin,B=m.TrackerMixin,w=m.Series,x=Math,E=x.round,C=x.floor,M=x.max,T=m.Color,r=function(){};F(J.prototype,{init:function(a,b,c){var d=this,g=
	d.defaultOptions;d.chart=b;d.options=a=t(g,b.angular?{background:{}}:void 0,a);(a=a.background)&&s([].concat(K(a)).reverse(),function(a){var g=a.backgroundColor,b=c.userOptions,a=t(d.defaultBackgroundOptions,a);if(g)a.backgroundColor=g;a.color=a.backgroundColor;c.options.plotBands.unshift(a);b.plotBands=b.plotBands||[];b.plotBands!==c.options.plotBands&&b.plotBands.unshift(a)})},defaultOptions:{center:["50%","50%"],size:"85%",startAngle:0},defaultBackgroundOptions:{shape:"circle",borderWidth:1,borderColor:"silver",
	backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"#FFF"],[1,"#DDD"]]},from:-Number.MAX_VALUE,innerRadius:0,to:Number.MAX_VALUE,outerRadius:"105%"}});var z=L.prototype,y=y.prototype,U={getOffset:r,redraw:function(){this.isDirty=!1},render:function(){this.isDirty=!1},setScale:r,setCategories:r,setTitle:r},N={isRadial:!0,defaultRadialGaugeOptions:{labels:{align:"center",x:0,y:null},minorGridLineWidth:0,minorTickInterval:"auto",minorTickLength:10,minorTickPosition:"inside",minorTickWidth:1,
	tickLength:10,tickPosition:"inside",tickWidth:2,title:{rotation:0},zIndex:2},defaultRadialXOptions:{gridLineWidth:1,labels:{align:null,distance:15,x:0,y:null},maxPadding:0,minPadding:0,showLastLabel:!1,tickLength:0},defaultRadialYOptions:{gridLineInterpolation:"circle",labels:{align:"right",x:-3,y:-2},showLastLabel:!1,title:{x:4,text:null,rotation:90}},setOptions:function(a){a=this.options=t(this.defaultOptions,this.defaultRadialOptions,a);if(!a.plotBands)a.plotBands=[]},getOffset:function(){z.getOffset.call(this);
	this.chart.axisOffset[this.side]=0;this.center=this.pane.center=S.getCenter.call(this.pane)},getLinePath:function(a,b){var c=this.center,b=q(b,c[2]/2-this.offset);return this.chart.renderer.symbols.arc(this.left+c[0],this.top+c[1],b,b,{start:this.startAngleRad,end:this.endAngleRad,open:!0,innerR:0})},setAxisTranslation:function(){z.setAxisTranslation.call(this);if(this.center)this.transA=this.isCircular?(this.endAngleRad-this.startAngleRad)/(this.max-this.min||1):this.center[2]/2/(this.max-this.min||
	1),this.minPixelPadding=this.isXAxis?this.transA*this.minPointOffset:0},beforeSetTickPositions:function(){this.autoConnect&&(this.max+=this.categories&&1||this.pointRange||this.closestPointRange||0)},setAxisSize:function(){z.setAxisSize.call(this);if(this.isRadial){this.center=this.pane.center=m.CenteredSeriesMixin.getCenter.call(this.pane);if(this.isCircular)this.sector=this.endAngleRad-this.startAngleRad;this.len=this.width=this.height=this.center[2]*q(this.sector,1)/2}},getPosition:function(a,
	b){return this.postTranslate(this.isCircular?this.translate(a):0,q(this.isCircular?b:this.translate(a),this.center[2]/2)-this.offset)},postTranslate:function(a,b){var c=this.chart,d=this.center,a=this.startAngleRad+a;return{x:c.plotLeft+d[0]+Math.cos(a)*b,y:c.plotTop+d[1]+Math.sin(a)*b}},getPlotBandPath:function(a,b,c){var d=this.center,g=this.startAngleRad,e=d[2]/2,j=[q(c.outerRadius,"100%"),c.innerRadius,q(c.thickness,10)],l=/%$/,i,f=this.isCircular;this.options.gridLineInterpolation==="polygon"?
	d=this.getPlotLinePath(a).concat(this.getPlotLinePath(b,!0)):(a=Math.max(a,this.min),b=Math.min(b,this.max),f||(j[0]=this.translate(a),j[1]=this.translate(b)),j=Q(j,function(a){l.test(a)&&(a=A(a,10)*e/100);return a}),c.shape==="circle"||!f?(a=-Math.PI/2,b=Math.PI*1.5,i=!0):(a=g+this.translate(a),b=g+this.translate(b)),d=this.chart.renderer.symbols.arc(this.left+d[0],this.top+d[1],j[0],j[0],{start:Math.min(a,b),end:Math.max(a,b),innerR:q(j[1],j[0]-j[2]),open:i}));return d},getPlotLinePath:function(a,
	b){var c=this,d=c.center,g=c.chart,e=c.getPosition(a),j,l,i;c.isCircular?i=["M",d[0]+g.plotLeft,d[1]+g.plotTop,"L",e.x,e.y]:c.options.gridLineInterpolation==="circle"?(a=c.translate(a))&&(i=c.getLinePath(0,a)):(s(g.xAxis,function(a){a.pane===c.pane&&(j=a)}),i=[],a=c.translate(a),d=j.tickPositions,j.autoConnect&&(d=d.concat([d[0]])),b&&(d=[].concat(d).reverse()),s(d,function(e,b){l=j.getPosition(e,a);i.push(b?"L":"M",l.x,l.y)}));return i},getTitlePosition:function(){var a=this.center,b=this.chart,
	c=this.options.title;return{x:b.plotLeft+a[0]+(c.x||0),y:b.plotTop+a[1]-{high:0.5,middle:0.25,low:0}[c.align]*a[2]+(c.y||0)}}};v(z,"init",function(a,b,c){var h;var d=b.angular,g=b.polar,e=c.isX,j=d&&e,l,i;i=b.options;var f=c.pane||0;if(d){if(F(this,j?U:N),l=!e)this.defaultRadialOptions=this.defaultRadialGaugeOptions}else if(g)F(this,N),this.defaultRadialOptions=(l=e)?this.defaultRadialXOptions:t(this.defaultYAxisOptions,this.defaultRadialYOptions);a.call(this,b,c);if(!j&&(d||g)){a=this.options;if(!b.panes)b.panes=
	[];this.pane=(h=b.panes[f]=b.panes[f]||new J(K(i.pane)[f],b,this),f=h);f=f.options;b.inverted=!1;i.chart.zoomType=null;this.startAngleRad=b=(f.startAngle-90)*Math.PI/180;this.endAngleRad=i=(q(f.endAngle,f.startAngle+360)-90)*Math.PI/180;this.offset=a.offset||0;if((this.isCircular=l)&&c.max===void 0&&i-b===2*Math.PI)this.autoConnect=!0}});v(z,"autoLabelAlign",function(a){if(!this.isRadial)return a.apply(this,[].slice.call(arguments,1))});v(y,"getPosition",function(a,b,c,d,g){var e=this.axis;return e.getPosition?
	e.getPosition(c):a.call(this,b,c,d,g)});v(y,"getLabelPosition",function(a,b,c,d,g,e,j,l,i){var f=this.axis,h=e.y,n=20,k=e.align,m=(f.translate(this.pos)+f.startAngleRad+Math.PI/2)/Math.PI*180%360;f.isRadial?(a=f.getPosition(this.pos,f.center[2]/2+q(e.distance,-25)),e.rotation==="auto"?d.attr({rotation:m}):h===null&&(h=f.chart.renderer.fontMetrics(d.styles.fontSize).b-d.getBBox().height/2),k===null&&(f.isCircular?(this.label.getBBox().width>f.len*f.tickInterval/(f.max-f.min)&&(n=0),k=m>n&&m<180-n?
	"left":m>180+n&&m<360-n?"right":"center"):k="center",d.attr({align:k})),a.x+=e.x,a.y+=h):a=a.call(this,b,c,d,g,e,j,l,i);return a});v(y,"getMarkPath",function(a,b,c,d,g,e,j){var l=this.axis;l.isRadial?(a=l.getPosition(this.pos,l.center[2]/2+d),b=["M",b,c,"L",a.x,a.y]):b=a.call(this,b,c,d,g,e,j);return b});o.arearange=t(o.area,{lineWidth:1,marker:null,threshold:null,tooltip:{pointFormat:'<span style="color:{series.color}">\u25cf</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'},
	trackByArea:!0,dataLabels:{align:null,verticalAlign:null,xLow:0,xHigh:0,yLow:0,yHigh:0},states:{hover:{halo:!1}}});k.arearange=u(k.area,{type:"arearange",pointArrayMap:["low","high"],dataLabelCollections:["dataLabel","dataLabelUpper"],toYData:function(a){return[a.low,a.high]},pointValKey:"low",deferTranslatePolar:!0,highToXY:function(a){var b=this.chart,c=this.xAxis.postTranslate(a.rectPlotX,this.yAxis.len-a.plotHigh);a.plotHighX=c.x-b.plotLeft;a.plotHigh=c.y-b.plotTop},translate:function(){var a=
	this,b=a.yAxis;k.area.prototype.translate.apply(a);s(a.points,function(a){var d=a.low,g=a.high,e=a.plotY;g===null||d===null?a.isNull=!0:(a.plotLow=e,a.plotHigh=b.translate(g,0,1,0,1))});this.chart.polar&&s(this.points,function(b){a.highToXY(b)})},getGraphPath:function(){var a=this.points,b=[],c=[],d=a.length,g=w.prototype.getGraphPath,e,j,l;l=this.options;for(var i=l.step,d=a.length;d--;)e=a[d],!e.isNull&&(!a[d+1]||a[d+1].isNull)&&c.push({plotX:e.plotX,plotY:e.plotLow}),j={plotX:e.plotX,plotY:e.plotHigh,
	isNull:e.isNull},c.push(j),b.push(j),!e.isNull&&(!a[d-1]||a[d-1].isNull)&&c.push({plotX:e.plotX,plotY:e.plotLow});a=g.call(this,a);if(i)i===!0&&(i="left"),l.step={left:"right",center:"center",right:"left"}[i];b=g.call(this,b);c=g.call(this,c);l.step=i;l=[].concat(a,b);!this.chart.polar&&c[0]==="M"&&(c[0]="L");this.areaPath=this.areaPath.concat(a,c);return l},drawDataLabels:function(){var a=this.data,b=a.length,c,d=[],g=w.prototype,e=this.options.dataLabels,j=e.align,l=e.verticalAlign,i=e.inside,f,
	h,n=this.chart.inverted;if(e.enabled||this._hasPointLabels){for(c=b;c--;)if(f=a[c]){h=i?f.plotHigh<f.plotLow:f.plotHigh>f.plotLow;f.y=f.high;f._plotY=f.plotY;f.plotY=f.plotHigh;d[c]=f.dataLabel;f.dataLabel=f.dataLabelUpper;f.below=h;if(n){if(!j)e.align=h?"right":"left"}else if(!l)e.verticalAlign=h?"top":"bottom";e.x=e.xHigh;e.y=e.yHigh}g.drawDataLabels&&g.drawDataLabels.apply(this,arguments);for(c=b;c--;)if(f=a[c]){h=i?f.plotHigh<f.plotLow:f.plotHigh>f.plotLow;f.dataLabelUpper=f.dataLabel;f.dataLabel=
	d[c];f.y=f.low;f.plotY=f._plotY;f.below=!h;if(n){if(!j)e.align=h?"left":"right"}else if(!l)e.verticalAlign=h?"bottom":"top";e.x=e.xLow;e.y=e.yLow}g.drawDataLabels&&g.drawDataLabels.apply(this,arguments)}e.align=j;e.verticalAlign=l},alignDataLabel:function(){k.column.prototype.alignDataLabel.apply(this,arguments)},setStackedPoints:r,getSymbol:r,drawPoints:r});o.areasplinerange=t(o.arearange);k.areasplinerange=u(k.arearange,{type:"areasplinerange",getPointSpline:k.spline.prototype.getPointSpline});
	(function(){var a=k.column.prototype;o.columnrange=t(o.column,o.arearange,{lineWidth:1,pointRange:null});k.columnrange=u(k.arearange,{type:"columnrange",translate:function(){var b=this,c=b.yAxis,d=b.xAxis,g=b.chart,e;a.translate.apply(b);s(b.points,function(a){var l=a.shapeArgs,i=b.options.minPointLength,f,h;a.plotHigh=e=c.translate(a.high,0,1,0,1);a.plotLow=a.plotY;h=e;f=a.plotY-e;Math.abs(f)<i?(i-=f,f+=i,h-=i/2):f<0&&(f*=-1,h-=f);l.height=f;l.y=h;a.tooltipPos=g.inverted?[c.len+c.pos-g.plotLeft-
	h-f/2,d.len+d.pos-g.plotTop-l.x-l.width/2,f]:[d.left-g.plotLeft+l.x+l.width/2,c.pos-g.plotTop+h+f/2,f]})},directTouch:!0,trackerGroups:["group","dataLabelsGroup"],drawGraph:r,crispCol:a.crispCol,pointAttrToOptions:a.pointAttrToOptions,drawPoints:a.drawPoints,drawTracker:a.drawTracker,animate:a.animate,getColumnMetrics:a.getColumnMetrics})})();o.gauge=t(o.line,{dataLabels:{enabled:!0,defer:!1,y:15,borderWidth:1,borderColor:"silver",borderRadius:3,crop:!1,verticalAlign:"top",zIndex:2},dial:{},pivot:{},
	tooltip:{headerFormat:""},showInLegend:!1});B={type:"gauge",pointClass:u(G,{setState:function(a){this.state=a}}),angular:!0,drawGraph:r,fixedBox:!0,forceDL:!0,trackerGroups:["group","dataLabelsGroup"],translate:function(){var a=this.yAxis,b=this.options,c=a.center;this.generatePoints();s(this.points,function(d){var g=t(b.dial,d.dial),e=A(q(g.radius,80))*c[2]/200,j=A(q(g.baseLength,70))*e/100,l=A(q(g.rearLength,10))*e/100,i=g.baseWidth||3,f=g.topWidth||1,h=b.overshoot,n=a.startAngleRad+a.translate(d.y,
	null,null,null,!0);h&&typeof h==="number"?(h=h/180*Math.PI,n=Math.max(a.startAngleRad-h,Math.min(a.endAngleRad+h,n))):b.wrap===!1&&(n=Math.max(a.startAngleRad,Math.min(a.endAngleRad,n)));n=n*180/Math.PI;d.shapeType="path";d.shapeArgs={d:g.path||["M",-l,-i/2,"L",j,-i/2,e,-f/2,e,f/2,j,i/2,-l,i/2,"z"],translateX:c[0],translateY:c[1],rotation:n};d.plotX=c[0];d.plotY=c[1]})},drawPoints:function(){var a=this,b=a.yAxis.center,c=a.pivot,d=a.options,g=d.pivot,e=a.chart.renderer;s(a.points,function(b){var g=
	b.graphic,c=b.shapeArgs,f=c.d,h=t(d.dial,b.dial);g?(g.animate(c),c.d=f):b.graphic=e[b.shapeType](c).attr({stroke:h.borderColor||"none","stroke-width":h.borderWidth||0,fill:h.backgroundColor||"black",rotation:c.rotation,zIndex:1}).add(a.group)});c?c.animate({translateX:b[0],translateY:b[1]}):a.pivot=e.circle(0,0,q(g.radius,5)).attr({"stroke-width":g.borderWidth||0,stroke:g.borderColor||"silver",fill:g.backgroundColor||"black",zIndex:2}).translate(b[0],b[1]).add(a.group)},animate:function(a){var b=
	this;if(!a)s(b.points,function(a){var d=a.graphic;d&&(d.attr({rotation:b.yAxis.startAngleRad*180/Math.PI}),d.animate({rotation:a.shapeArgs.rotation},b.options.animation))}),b.animate=null},render:function(){this.group=this.plotGroup("group","series",this.visible?"visible":"hidden",this.options.zIndex,this.chart.seriesGroup);w.prototype.render.call(this);this.group.clip(this.chart.clipRect)},setData:function(a,b){w.prototype.setData.call(this,a,!1);this.processData();this.generatePoints();q(b,!0)&&
	this.chart.redraw()},drawTracker:B&&B.drawTrackerPoint};k.gauge=u(k.line,B);o.boxplot=t(o.column,{fillColor:"#FFFFFF",lineWidth:1,medianWidth:2,states:{hover:{brightness:-0.3}},threshold:null,tooltip:{pointFormat:'<span style="color:{point.color}">\u25cf</span> <b> {series.name}</b><br/>Maximum: {point.high}<br/>Upper quartile: {point.q3}<br/>Median: {point.median}<br/>Lower quartile: {point.q1}<br/>Minimum: {point.low}<br/>'},whiskerLength:"50%",whiskerWidth:2});k.boxplot=u(k.column,{type:"boxplot",
	pointArrayMap:["low","q1","median","q3","high"],toYData:function(a){return[a.low,a.q1,a.median,a.q3,a.high]},pointValKey:"high",pointAttrToOptions:{fill:"fillColor",stroke:"color","stroke-width":"lineWidth"},drawDataLabels:r,translate:function(){var a=this.yAxis,b=this.pointArrayMap;k.column.prototype.translate.apply(this);s(this.points,function(c){s(b,function(b){c[b]!==null&&(c[b+"Plot"]=a.translate(c[b],0,1,0,1))})})},drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d,g,e,j,l,i,
	f,h,n,k,m,H,I,o,t,r,v,u,w,x,B,A,y=a.doQuartiles!==!1,z,D=a.options.whiskerLength;s(a.points,function(p){n=p.graphic;B=p.shapeArgs;m={};o={};r={};A=p.color||a.color;if(p.plotY!==void 0)if(d=p.pointAttr[p.selected?"selected":""],v=B.width,u=C(B.x),w=u+v,x=E(v/2),g=C(y?p.q1Plot:p.lowPlot),e=C(y?p.q3Plot:p.lowPlot),j=C(p.highPlot),l=C(p.lowPlot),m.stroke=p.stemColor||b.stemColor||A,m["stroke-width"]=q(p.stemWidth,b.stemWidth,b.lineWidth),m.dashstyle=p.stemDashStyle||b.stemDashStyle,o.stroke=p.whiskerColor||
	b.whiskerColor||A,o["stroke-width"]=q(p.whiskerWidth,b.whiskerWidth,b.lineWidth),r.stroke=p.medianColor||b.medianColor||A,r["stroke-width"]=q(p.medianWidth,b.medianWidth,b.lineWidth),f=m["stroke-width"]%2/2,h=u+x+f,k=["M",h,e,"L",h,j,"M",h,g,"L",h,l],y&&(f=d["stroke-width"]%2/2,h=C(h)+f,g=C(g)+f,e=C(e)+f,u+=f,w+=f,H=["M",u,e,"L",u,g,"L",w,g,"L",w,e,"L",u,e,"z"]),D&&(f=o["stroke-width"]%2/2,j+=f,l+=f,z=/%$/.test(D)?x*parseFloat(D)/100:D/2,I=["M",h-z,j,"L",h+z,j,"M",h-z,l,"L",h+z,l]),f=r["stroke-width"]%
	2/2,i=E(p.medianPlot)+f,t=["M",u,i,"L",w,i],n)p.stem.animate({d:k}),D&&p.whiskers.animate({d:I}),y&&p.box.animate({d:H}),p.medianShape.animate({d:t});else{p.graphic=n=c.g().add(a.group);p.stem=c.path(k).attr(m).add(n);if(D)p.whiskers=c.path(I).attr(o).add(n);if(y)p.box=c.path(H).attr(d).add(n);p.medianShape=c.path(t).attr(r).add(n)}})},setStackedPoints:r});o.errorbar=t(o.boxplot,{color:"#000000",grouping:!1,linkedTo:":previous",tooltip:{pointFormat:'<span style="color:{point.color}">\u25cf</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'},
	whiskerWidth:null});k.errorbar=u(k.boxplot,{type:"errorbar",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"high",doQuartiles:!1,drawDataLabels:k.arearange?k.arearange.prototype.drawDataLabels:r,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||k.column.prototype.getColumnMetrics.call(this)}});o.waterfall=t(o.column,{lineWidth:1,lineColor:"#333",dashStyle:"dot",borderColor:"#333",dataLabels:{inside:!0},states:{hover:{lineWidthPlus:0}}});
	k.waterfall=u(k.column,{type:"waterfall",upColorProp:"fill",pointValKey:"y",translate:function(){var a=this.options,b=this.yAxis,c,d,g,e,j,l,i,f,h,n=q(a.minPointLength,5),m=a.threshold,o=a.stacking;k.column.prototype.translate.apply(this);this.minPointLengthOffset=0;i=f=m;d=this.points;for(c=0,a=d.length;c<a;c++){g=d[c];l=this.processedYData[c];e=g.shapeArgs;h=(j=o&&b.stacks[(this.negStacks&&l<m?"-":"")+this.stackKey])?j[g.x].points[this.index+","+c]:[0,l];if(g.isSum)g.y=l;else if(g.isIntermediateSum)g.y=
	l-f;j=M(i,i+g.y)+h[0];e.y=b.translate(j,0,1);if(g.isSum)e.y=b.translate(h[1],0,1),e.height=Math.min(b.translate(h[0],0,1),b.len)-e.y+this.minPointLengthOffset;else if(g.isIntermediateSum)e.y=b.translate(h[1],0,1),e.height=Math.min(b.translate(f,0,1),b.len)-e.y+this.minPointLengthOffset,f=h[1];else{if(i!==0)e.height=l>0?b.translate(i,0,1)-e.y:b.translate(i,0,1)-b.translate(i-l,0,1);i+=l}e.height<0&&(e.y+=e.height,e.height*=-1);g.plotY=e.y=E(e.y)-this.borderWidth%2/2;e.height=M(E(e.height),0.001);g.yBottom=
	e.y+e.height;if(e.height<=n)e.height=n,this.minPointLengthOffset+=n;e.y-=this.minPointLengthOffset;e=g.plotY+(g.negative?e.height:0)-this.minPointLengthOffset;this.chart.inverted?g.tooltipPos[0]=b.len-e:g.tooltipPos[1]=e}},processData:function(a){var b=this.yData,c=this.options.data,d,g=b.length,e,j,l,i,f,h;j=e=l=i=this.options.threshold||0;for(h=0;h<g;h++)f=b[h],d=c&&c[h]?c[h]:{},f==="sum"||d.isSum?b[h]=j:f==="intermediateSum"||d.isIntermediateSum?b[h]=e:(j+=f,e+=f),l=Math.min(j,l),i=Math.max(j,
	i);w.prototype.processData.call(this,a);this.dataMin=l;this.dataMax=i},toYData:function(a){return a.isSum?a.x===0?null:"sum":a.isIntermediateSum?a.x===0?null:"intermediateSum":a.y},getAttribs:function(){k.column.prototype.getAttribs.apply(this,arguments);var a=this,b=a.options,c=b.states,d=b.upColor||a.color,b=m.Color(d).brighten(0.1).get(),g=t(a.pointAttr),e=a.upColorProp;g[""][e]=d;g.hover[e]=c.hover.upColor||b;g.select[e]=c.select.upColor||d;s(a.points,function(e){if(!e.options.color)e.y>0?(e.pointAttr=
	g,e.color=d):e.pointAttr=a.pointAttr})},getGraphPath:function(){var a=this.data,b=a.length,c=E(this.options.lineWidth+this.borderWidth)%2/2,d=[],g,e,j;for(j=1;j<b;j++)e=a[j].shapeArgs,g=a[j-1].shapeArgs,e=["M",g.x+g.width,g.y+c,"L",e.x,g.y+c],a[j-1].y<0&&(e[2]+=g.height,e[5]+=g.height),d=d.concat(e);return d},getExtremes:r,drawGraph:w.prototype.drawGraph});o.polygon=t(o.scatter,{marker:{enabled:!1}});k.polygon=u(k.scatter,{type:"polygon",fillGraph:!0,getSegmentPath:function(a){return w.prototype.getSegmentPath.call(this,
	a).concat("z")},drawGraph:w.prototype.drawGraph,drawLegendSymbol:m.LegendSymbolMixin.drawRectangle});o.bubble=t(o.scatter,{dataLabels:{formatter:function(){return this.point.z},inside:!0,verticalAlign:"middle"},marker:{lineColor:null,lineWidth:1},minSize:8,maxSize:"20%",softThreshold:!1,states:{hover:{halo:{size:5}}},tooltip:{pointFormat:"({point.x}, {point.y}), Size: {point.z}"},turboThreshold:0,zThreshold:0,zoneAxis:"z"});B=u(G,{haloPath:function(){return G.prototype.haloPath.call(this,this.shapeArgs.r+
	this.series.options.states.hover.halo.size)},ttBelow:!1});k.bubble=u(k.scatter,{type:"bubble",pointClass:B,pointArrayMap:["y","z"],parallelArrays:["x","y","z"],trackerGroups:["group","dataLabelsGroup"],bubblePadding:!0,zoneAxis:"z",pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor"},applyOpacity:function(a){var b=this.options.marker,c=q(b.fillOpacity,0.5),a=a||b.fillColor||this.color;c!==1&&(a=T(a).setOpacity(c).get("rgba"));return a},convertAttribs:function(){var a=
	w.prototype.convertAttribs.apply(this,arguments);a.fill=this.applyOpacity(a.fill);return a},getRadii:function(a,b,c,d){var g,e,j,l=this.zData,i=[],f=this.options,h=f.sizeBy!=="width",n=f.zThreshold,k=b-a;for(e=0,g=l.length;e<g;e++)j=l[e],f.sizeByAbsoluteValue&&j!==null&&(j=Math.abs(j-n),b=Math.max(b-n,Math.abs(a-n)),a=0),j===null?j=null:j<a?j=c/2-1:(j=k>0?(j-a)/k:0.5,h&&j>=0&&(j=Math.sqrt(j)),j=x.ceil(c+j*(d-c))/2),i.push(j);this.radii=i},animate:function(a){var b=this.options.animation;if(!a)s(this.points,
	function(a){var d=a.graphic,a=a.shapeArgs;d&&a&&(d.attr("r",1),d.animate({r:a.r},b))}),this.animate=null},translate:function(){var a,b=this.data,c,d,g=this.radii;k.scatter.prototype.translate.call(this);for(a=b.length;a--;)c=b[a],d=g?g[a]:0,typeof d==="number"&&d>=this.minPxSize/2?(c.shapeType="circle",c.shapeArgs={x:c.plotX,y:c.plotY,r:d},c.dlBox={x:c.plotX-d,y:c.plotY-d,width:2*d,height:2*d}):c.shapeArgs=c.plotY=c.dlBox=void 0},drawLegendSymbol:function(a,b){var c=this.chart.renderer,d=c.fontMetrics(a.itemStyle.fontSize).f/
	2;b.legendSymbol=c.circle(d,a.baseline-d,d).attr({zIndex:3}).add(b.legendGroup);b.legendSymbol.isMarker=!0},drawPoints:k.column.prototype.drawPoints,alignDataLabel:k.column.prototype.alignDataLabel,buildKDTree:r,applyZones:r});L.prototype.beforePadding=function(){var a=this,b=this.len,c=this.chart,d=0,g=b,e=this.isXAxis,j=e?"xData":"yData",l=this.min,i={},f=x.min(c.plotWidth,c.plotHeight),h=Number.MAX_VALUE,n=-Number.MAX_VALUE,k=this.max-l,m=b/k,o=[];s(this.series,function(b){var g=b.options;if(b.bubblePadding&&
	(b.visible||!c.options.chart.ignoreHiddenSeries))if(a.allowZoomOutside=!0,o.push(b),e)s(["minSize","maxSize"],function(a){var b=g[a],e=/%$/.test(b),b=A(b);i[a]=e?f*b/100:b}),b.minPxSize=i.minSize,b.maxPxSize=i.maxSize,b=b.zData,b.length&&(h=q(g.zMin,x.min(h,x.max(O(b),g.displayNegative===!1?g.zThreshold:-Number.MAX_VALUE))),n=q(g.zMax,x.max(n,P(b))))});s(o,function(a){var b=a[j],c=b.length,f;e&&a.getRadii(h,n,a.minPxSize,a.maxPxSize);if(k>0)for(;c--;)typeof b[c]==="number"&&(f=a.radii[c],d=Math.min((b[c]-
	l)*m-f,d),g=Math.max((b[c]-l)*m+f,g))});o.length&&k>0&&!this.isLog&&(g-=b,m*=(b+d-g)/b,s([["min","userMin",d],["max","userMax",g]],function(b){q(a.options[b[0]],a[b[1]])===void 0&&(a[b[0]]+=b[2]/m)}))};(function(){function a(a,b){var c=this.chart,d=this.options.animation,i=this.group,f=this.markerGroup,h=this.xAxis.center,n=c.plotLeft,k=c.plotTop;if(c.polar){if(c.renderer.isSVG)d===!0&&(d={}),b?(c={translateX:h[0]+n,translateY:h[1]+k,scaleX:0.001,scaleY:0.001},i.attr(c),f&&f.attr(c)):(c={translateX:n,
	translateY:k,scaleX:1,scaleY:1},i.animate(c,d),f&&f.animate(c,d),this.animate=null)}else a.call(this,b)}var b=w.prototype,c=R.prototype,d;b.searchPointByAngle=function(a){var b=this.chart,c=this.xAxis.pane.center;return this.searchKDTree({clientX:180+Math.atan2(a.chartX-c[0]-b.plotLeft,a.chartY-c[1]-b.plotTop)*(-180/Math.PI)})};v(b,"buildKDTree",function(a){if(this.chart.polar)this.kdByAngle?this.searchPoint=this.searchPointByAngle:this.kdDimensions=2;a.apply(this)});b.toXY=function(a){var b,c=this.chart,
	d=a.plotX;b=a.plotY;a.rectPlotX=d;a.rectPlotY=b;b=this.xAxis.postTranslate(a.plotX,this.yAxis.len-b);a.plotX=a.polarPlotX=b.x-c.plotLeft;a.plotY=a.polarPlotY=b.y-c.plotTop;this.kdByAngle?(c=(d/Math.PI*180+this.xAxis.pane.options.startAngle)%360,c<0&&(c+=360),a.clientX=c):a.clientX=a.plotX};k.spline&&v(k.spline.prototype,"getPointSpline",function(a,b,c,d){var i,f,h,n,k,m,o;if(this.chart.polar){i=c.plotX;f=c.plotY;a=b[d-1];h=b[d+1];this.connectEnds&&(a||(a=b[b.length-2]),h||(h=b[1]));if(a&&h)n=a.plotX,
	k=a.plotY,b=h.plotX,m=h.plotY,n=(1.5*i+n)/2.5,k=(1.5*f+k)/2.5,h=(1.5*i+b)/2.5,o=(1.5*f+m)/2.5,b=Math.sqrt(Math.pow(n-i,2)+Math.pow(k-f,2)),m=Math.sqrt(Math.pow(h-i,2)+Math.pow(o-f,2)),n=Math.atan2(k-f,n-i),k=Math.atan2(o-f,h-i),o=Math.PI/2+(n+k)/2,Math.abs(n-o)>Math.PI/2&&(o-=Math.PI),n=i+Math.cos(o)*b,k=f+Math.sin(o)*b,h=i+Math.cos(Math.PI+o)*m,o=f+Math.sin(Math.PI+o)*m,c.rightContX=h,c.rightContY=o;d?(c=["C",a.rightContX||a.plotX,a.rightContY||a.plotY,n||i,k||f,i,f],a.rightContX=a.rightContY=null):
	c=["M",i,f]}else c=a.call(this,b,c,d);return c});v(b,"translate",function(a){var b=this.chart;a.call(this);if(b.polar&&(this.kdByAngle=b.tooltip&&b.tooltip.shared,!this.preventPostTranslate)){a=this.points;for(b=a.length;b--;)this.toXY(a[b])}});v(b,"getGraphPath",function(a,b){var c=this;if(this.chart.polar){b=b||this.points;if(this.options.connectEnds!==!1&&b[0].y!==null)this.connectEnds=!0,b.splice(b.length,0,b[0]);s(b,function(a){a.polarPlotY===void 0&&c.toXY(a)})}return a.apply(this,[].slice.call(arguments,
	1))});v(b,"animate",a);if(k.column)d=k.column.prototype,v(d,"animate",a),v(d,"translate",function(a){var b=this.xAxis,c=this.yAxis.len,d=b.center,i=b.startAngleRad,f=this.chart.renderer,h,k;this.preventPostTranslate=!0;a.call(this);if(b.isRadial){b=this.points;for(k=b.length;k--;)h=b[k],a=h.barX+i,h.shapeType="path",h.shapeArgs={d:f.symbols.arc(d[0],d[1],c-h.plotY,null,{start:a,end:a+h.pointWidth,innerR:c-q(h.yBottom,c)})},this.toXY(h),h.tooltipPos=[h.plotX,h.plotY],h.ttBelow=h.plotY>d[1]}}),v(d,
	"alignDataLabel",function(a,c,d,l,i,f){if(this.chart.polar){a=c.rectPlotX/Math.PI*180;if(l.align===null)l.align=a>20&&a<160?"left":a>200&&a<340?"right":"center";if(l.verticalAlign===null)l.verticalAlign=a<45||a>315?"bottom":a>135&&a<225?"top":"middle";b.alignDataLabel.call(this,c,d,l,i,f)}else a.call(this,c,d,l,i,f)});v(c,"getCoordinates",function(a,b){var c=this.chart,d={xAxis:[],yAxis:[]};c.polar?s(c.axes,function(a){var f=a.isXAxis,g=a.center,k=b.chartX-g[0]-c.plotLeft,g=b.chartY-g[1]-c.plotTop;
	d[f?"xAxis":"yAxis"].push({axis:a,value:a.translate(f?Math.PI-Math.atan2(k,g):Math.sqrt(Math.pow(k,2)+Math.pow(g,2)),!0)})}):d=a.call(this,b);return d})})()});


/***/ },
/* 320 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

	var React = __webpack_require__(28);

	var sizerStyle = { position: 'absolute', top: 0, left: 0, visibility: 'hidden', height: 0, overflow: 'scroll', whiteSpace: 'pre' };

	var AutosizeInput = React.createClass({
		displayName: 'AutosizeInput',

		propTypes: {
			className: React.PropTypes.string, // className for the outer element
			defaultValue: React.PropTypes.any, // default field value
			inputClassName: React.PropTypes.string, // className for the input element
			inputStyle: React.PropTypes.object, // css styles for the input element
			minWidth: React.PropTypes.oneOfType([// minimum width for input element
			React.PropTypes.number, React.PropTypes.string]),
			onChange: React.PropTypes.func, // onChange handler: function(newValue) {}
			placeholder: React.PropTypes.string, // placeholder text
			placeholderIsMinWidth: React.PropTypes.bool, // don't collapse size to less than the placeholder
			style: React.PropTypes.object, // css styles for the outer element
			value: React.PropTypes.any },
		// field value
		getDefaultProps: function getDefaultProps() {
			return {
				minWidth: 1
			};
		},
		getInitialState: function getInitialState() {
			return {
				inputWidth: this.props.minWidth
			};
		},
		componentDidMount: function componentDidMount() {
			this.copyInputStyles();
			this.updateInputWidth();
		},
		componentDidUpdate: function componentDidUpdate() {
			this.updateInputWidth();
		},
		copyInputStyles: function copyInputStyles() {
			if (!this.isMounted() || !window.getComputedStyle) {
				return;
			}
			var inputStyle = window.getComputedStyle(this.refs.input);
			if (!inputStyle) {
				return;
			}
			var widthNode = this.refs.sizer;
			widthNode.style.fontSize = inputStyle.fontSize;
			widthNode.style.fontFamily = inputStyle.fontFamily;
			widthNode.style.fontWeight = inputStyle.fontWeight;
			widthNode.style.fontStyle = inputStyle.fontStyle;
			widthNode.style.letterSpacing = inputStyle.letterSpacing;
			if (this.props.placeholder) {
				var placeholderNode = this.refs.placeholderSizer;
				placeholderNode.style.fontSize = inputStyle.fontSize;
				placeholderNode.style.fontFamily = inputStyle.fontFamily;
				placeholderNode.style.fontWeight = inputStyle.fontWeight;
				placeholderNode.style.fontStyle = inputStyle.fontStyle;
				placeholderNode.style.letterSpacing = inputStyle.letterSpacing;
			}
		},
		updateInputWidth: function updateInputWidth() {
			if (!this.isMounted() || typeof this.refs.sizer.scrollWidth === 'undefined') {
				return;
			}
			var newInputWidth = undefined;
			if (this.props.placeholder && (!this.props.value || this.props.value && this.props.placeholderIsMinWidth)) {
				newInputWidth = Math.max(this.refs.sizer.scrollWidth, this.refs.placeholderSizer.scrollWidth) + 2;
			} else {
				newInputWidth = this.refs.sizer.scrollWidth + 2;
			}
			if (newInputWidth < this.props.minWidth) {
				newInputWidth = this.props.minWidth;
			}
			if (newInputWidth !== this.state.inputWidth) {
				this.setState({
					inputWidth: newInputWidth
				});
			}
		},
		getInput: function getInput() {
			return this.refs.input;
		},
		focus: function focus() {
			this.refs.input.focus();
		},
		blur: function blur() {
			this.refs.input.blur();
		},
		select: function select() {
			this.refs.input.select();
		},
		render: function render() {
			var sizerValue = this.props.defaultValue || this.props.value || '';
			var wrapperStyle = this.props.style || {};
			if (!wrapperStyle.display) wrapperStyle.display = 'inline-block';
			var inputStyle = _extends({}, this.props.inputStyle);
			inputStyle.width = this.state.inputWidth + 'px';
			inputStyle.boxSizing = 'content-box';
			var inputProps = _extends({}, this.props);
			inputProps.className = this.props.inputClassName;
			inputProps.style = inputStyle;
			// ensure props meant for `AutosizeInput` don't end up on the `input`
			delete inputProps.inputClassName;
			delete inputProps.inputStyle;
			delete inputProps.minWidth;
			delete inputProps.placeholderIsMinWidth;
			return React.createElement(
				'div',
				{ className: this.props.className, style: wrapperStyle },
				React.createElement('input', _extends({}, inputProps, { ref: 'input' })),
				React.createElement(
					'div',
					{ ref: 'sizer', style: sizerStyle },
					sizerValue
				),
				this.props.placeholder ? React.createElement(
					'div',
					{ ref: 'placeholderSizer', style: sizerStyle },
					this.props.placeholder
				) : null
			);
		}
	});

	module.exports = AutosizeInput;

/***/ },
/* 321 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	__webpack_require__(322);

	__webpack_require__(339);

	var _notifications = __webpack_require__(343);

	var _notifications2 = _interopRequireDefault(_notifications);

	var _ft_notifications = __webpack_require__(348);

	var _ft_notifications2 = _interopRequireDefault(_ft_notifications);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	$(function () {
	  //if ($("[data-notification-drop]").length) {
	  //new Notifications();
	  new _ft_notifications2.default();
	  //}
	});

/***/ },
/* 322 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["Tata"] = __webpack_require__(323);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 323 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _reactSelectPlus = __webpack_require__(324);

	var _reactSelectPlus2 = _interopRequireDefault(_reactSelectPlus);

	__webpack_require__(333);

	var _moment = __webpack_require__(215);

	var _moment2 = _interopRequireDefault(_moment);

	var _tata = __webpack_require__(337);

	var _tata2 = _interopRequireDefault(_tata);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var Tata = function (_React$Component) {
	  _inherits(Tata, _React$Component);

	  function Tata() {
	    _classCallCheck(this, Tata);

	    return _possibleConstructorReturn(this, (Tata.__proto__ || Object.getPrototypeOf(Tata)).apply(this, arguments));
	  }

	  _createClass(Tata, [{
	    key: 'render',
	    value: function render() {
	      var options = [{ value: 'one', label: 'One' }, { value: 'two', label: 'Two' }];

	      function logChange(val) {
	        console.log("Selected: " + val);
	      }

	      return _react2.default.createElement(
	        'div',
	        { className: _tata2.default.root },
	        _react2.default.createElement(
	          'div',
	          { className: 'nested-form' },
	          _react2.default.createElement(_reactSelectPlus2.default, {
	            name: 'form-field-name',
	            value: 'one',
	            options: options,
	            onChange: logChange
	          })
	        )
	      );
	    }
	  }]);

	  return Tata;
	}(_react2.default.Component);

	exports.default = Tata;

/***/ },
/* 324 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, '__esModule', {
		value: true
	});

	var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	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 _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _reactDom = __webpack_require__(64);

	var _reactDom2 = _interopRequireDefault(_reactDom);

	var _reactInputAutosize = __webpack_require__(320);

	var _reactInputAutosize2 = _interopRequireDefault(_reactInputAutosize);

	var _classnames = __webpack_require__(325);

	var _classnames2 = _interopRequireDefault(_classnames);

	var _blacklist = __webpack_require__(326);

	var _blacklist2 = _interopRequireDefault(_blacklist);

	var _utilsStripDiacritics = __webpack_require__(327);

	var _utilsStripDiacritics2 = _interopRequireDefault(_utilsStripDiacritics);

	var _Async = __webpack_require__(328);

	var _Async2 = _interopRequireDefault(_Async);

	var _Dropdown = __webpack_require__(329);

	var _Dropdown2 = _interopRequireDefault(_Dropdown);

	var _Option = __webpack_require__(330);

	var _Option2 = _interopRequireDefault(_Option);

	var _OptionGroup = __webpack_require__(331);

	var _OptionGroup2 = _interopRequireDefault(_OptionGroup);

	var _Value = __webpack_require__(332);

	var _Value2 = _interopRequireDefault(_Value);

	function clone(obj) {
		var copy = {};
		for (var attr in obj) {
			if (obj.hasOwnProperty(attr)) {
				copy[attr] = obj[attr];
			};
		}
		return copy;
	}

	function stringifyValue(value) {
		if (typeof value === 'object') {
			return JSON.stringify(value);
		} else {
			return value;
		}
	}

	var stringOrNode = _react2['default'].PropTypes.oneOfType([_react2['default'].PropTypes.string, _react2['default'].PropTypes.node]);

	var instanceId = 1;

	var Select = _react2['default'].createClass({

		displayName: 'Select',

		propTypes: {
			addLabelText: _react2['default'].PropTypes.string, // placeholder displayed when you want to add a label on a multi-value input
			allowCreate: _react2['default'].PropTypes.bool, // whether to allow creation of new entries
			'aria-label': _react2['default'].PropTypes.string, // Aria label (for assistive tech)
			'aria-labelledby': _react2['default'].PropTypes.string, // HTML ID of an element that should be used as the label (for assistive tech)
			autoBlur: _react2['default'].PropTypes.bool, // automatically blur the component when an option is selected
			autofocus: _react2['default'].PropTypes.bool, // autofocus the component on mount
			autosize: _react2['default'].PropTypes.bool, // whether to enable autosizing or not
			backspaceRemoves: _react2['default'].PropTypes.bool, // whether backspace removes an item if there is no text input
			backspaceToRemoveMessage: _react2['default'].PropTypes.string, // Message to use for screenreaders to press backspace to remove the current item -
			// {label} is replaced with the item label
			className: _react2['default'].PropTypes.string, // className for the outer element
			clearAllText: stringOrNode, // title for the "clear" control when multi: true
			clearValueText: stringOrNode, // title for the "clear" control
			clearable: _react2['default'].PropTypes.bool, // should it be possible to reset value
			delimiter: _react2['default'].PropTypes.string, // delimiter to use to join multiple values for the hidden field value
			disabled: _react2['default'].PropTypes.bool, // whether the Select is disabled or not
			dropdownComponent: _react2['default'].PropTypes.func, // dropdown component to render the menu in
			escapeClearsValue: _react2['default'].PropTypes.bool, // whether escape clears the value when the menu is closed
			filterOption: _react2['default'].PropTypes.func, // method to filter a single option (option, filterString)
			filterOptions: _react2['default'].PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
			ignoreAccents: _react2['default'].PropTypes.bool, // whether to strip diacritics when filtering
			ignoreCase: _react2['default'].PropTypes.bool, // whether to perform case-insensitive filtering
			inputProps: _react2['default'].PropTypes.object, // custom attributes for the Input
			inputRenderer: _react2['default'].PropTypes.func, // returns a custom input component
			isLoading: _react2['default'].PropTypes.bool, // whether the Select is loading externally or not (such as options being loaded)
			isOpen: _react2['default'].PropTypes.bool, // whether the Select dropdown menu is open or not
			joinValues: _react2['default'].PropTypes.bool, // joins multiple values into a single form field with the delimiter (legacy mode)
			labelKey: _react2['default'].PropTypes.string, // path of the label value in option objects
			matchPos: _react2['default'].PropTypes.string, // (any|start) match the start or entire string when filtering
			matchProp: _react2['default'].PropTypes.string, // (any|label|value) which option property to filter on
			menuBuffer: _react2['default'].PropTypes.number, // optional buffer (in px) between the bottom of the viewport and the bottom of the menu
			menuContainerStyle: _react2['default'].PropTypes.object, // optional style to apply to the menu container
			menuRenderer: _react2['default'].PropTypes.func, // renders a custom menu with options
			menuStyle: _react2['default'].PropTypes.object, // optional style to apply to the menu
			multi: _react2['default'].PropTypes.bool, // multi-value input
			name: _react2['default'].PropTypes.string, // generates a hidden <input /> tag with this field name for html forms
			newOptionCreator: _react2['default'].PropTypes.func, // factory to create new options when allowCreate set
			noResultsText: stringOrNode, // placeholder displayed when there are no matching search results
			onBlur: _react2['default'].PropTypes.func, // onBlur handler: function (event) {}
			onBlurResetsInput: _react2['default'].PropTypes.bool, // whether input is cleared on blur
			onChange: _react2['default'].PropTypes.func, // onChange handler: function (newValue) {}
			onClose: _react2['default'].PropTypes.func, // fires when the menu is closed
			onFocus: _react2['default'].PropTypes.func, // onFocus handler: function (event) {}
			onInputChange: _react2['default'].PropTypes.func, // onInputChange handler: function (inputValue) {}
			onMenuScrollToBottom: _react2['default'].PropTypes.func, // fires when the menu is scrolled to the bottom; can be used to paginate options
			onOpen: _react2['default'].PropTypes.func, // fires when the menu is opened
			onValueClick: _react2['default'].PropTypes.func, // onClick handler for value labels: function (value, event) {}
			openAfterFocus: _react2['default'].PropTypes.bool, // boolean to enable opening dropdown when focused
			openOnFocus: _react2['default'].PropTypes.bool, // always open options menu on focus
			optionClassName: _react2['default'].PropTypes.string, // additional class(es) to apply to the <Option /> elements
			optionComponent: _react2['default'].PropTypes.func, // option component to render in dropdown
			optionGroupComponent: _react2['default'].PropTypes.func, // option group component to render in dropdown
			optionRenderer: _react2['default'].PropTypes.func, // optionRenderer: function (option) {}
			options: _react2['default'].PropTypes.array, // array of options
			pageSize: _react2['default'].PropTypes.number, // number of entries to page when using page up/down keys
			placeholder: stringOrNode, // field placeholder, displayed when there's no value
			renderInvalidValues: _react2['default'].PropTypes.bool, // boolean to enable rendering values that do not match any options
			required: _react2['default'].PropTypes.bool, // applies HTML5 required attribute when needed
			resetValue: _react2['default'].PropTypes.any, // value to use when you clear the control
			scrollMenuIntoView: _react2['default'].PropTypes.bool, // boolean to enable the viewport to shift so that the full menu fully visible when engaged
			searchable: _react2['default'].PropTypes.bool, // whether to enable searching feature or not
			simpleValue: _react2['default'].PropTypes.bool, // pass the value to onChange as a simple value (legacy pre 1.0 mode), defaults to false
			style: _react2['default'].PropTypes.object, // optional style to apply to the control
			tabIndex: _react2['default'].PropTypes.string, // optional tab index of the control
			tabSelectsValue: _react2['default'].PropTypes.bool, // whether to treat tabbing out while focused to be value selection
			value: _react2['default'].PropTypes.any, // initial field value
			valueComponent: _react2['default'].PropTypes.func, // value component to render
			valueKey: _react2['default'].PropTypes.string, // path of the label value in option objects
			valueRenderer: _react2['default'].PropTypes.func, // valueRenderer: function (option) {}
			wrapperStyle: _react2['default'].PropTypes.object },

		// optional style to apply to the component wrapper
		statics: { Async: _Async2['default'] },

		getDefaultProps: function getDefaultProps() {
			return {
				addLabelText: 'Add "{label}"?',
				autosize: true,
				allowCreate: false,
				backspaceRemoves: true,
				backspaceToRemoveMessage: 'Press backspace to remove {label}',
				clearable: true,
				clearAllText: 'Clear all',
				clearValueText: 'Clear value',
				delimiter: ',',
				disabled: false,
				dropdownComponent: _Dropdown2['default'],
				escapeClearsValue: true,
				filterOptions: true,
				ignoreAccents: true,
				ignoreCase: true,
				inputProps: {},
				isLoading: false,
				joinValues: false,
				labelKey: 'label',
				matchPos: 'any',
				matchProp: 'any',
				menuBuffer: 0,
				multi: false,
				noResultsText: 'No results found',
				onBlurResetsInput: true,
				openAfterFocus: false,
				optionComponent: _Option2['default'],
				optionGroupComponent: _OptionGroup2['default'],
				pageSize: 5,
				placeholder: 'Select...',
				renderInvalidValues: false,
				required: false,
				resetValue: null,
				scrollMenuIntoView: true,
				searchable: true,
				simpleValue: false,
				tabSelectsValue: true,
				valueComponent: _Value2['default'],
				valueKey: 'value'
			};
		},

		getInitialState: function getInitialState() {
			return {
				inputValue: '',
				isFocused: false,
				isLoading: false,
				isOpen: false,
				isPseudoFocused: false,
				required: false
			};
		},

		componentWillMount: function componentWillMount() {
			this._flatOptions = this.flattenOptions(this.props.options);
			this._instancePrefix = 'react-select-' + ++instanceId + '-';
			var valueArray = this.getValueArray(this.props.value);

			if (this.props.required) {
				this.setState({
					required: this.handleRequired(valueArray[0], this.props.multi)
				});
			}
		},

		componentDidMount: function componentDidMount() {
			if (this.props.autofocus) {
				this.focus();
			}
		},

		componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
			if (nextProps.options !== this.props.options) {
				this._flatOptions = this.flattenOptions(nextProps.options);
			}

			var valueArray = this.getValueArray(nextProps.value, nextProps);

			if (nextProps.required) {
				this.setState({
					required: this.handleRequired(valueArray[0], nextProps.multi)
				});
			}
		},

		componentWillUpdate: function componentWillUpdate(nextProps, nextState) {
			if (nextState.isOpen !== this.state.isOpen) {
				var handler = nextState.isOpen ? nextProps.onOpen : nextProps.onClose;
				handler && handler();
			}
		},

		componentDidUpdate: function componentDidUpdate(prevProps, prevState) {
			// focus to the selected option
			if (this.refs.menu && this.refs.focused && this.state.isOpen && !this.hasScrolledToOption) {
				var focusedOptionNode = _reactDom2['default'].findDOMNode(this.refs.focused);
				var focusedOptionParent = focusedOptionNode.parentElement;
				var menuNode = _reactDom2['default'].findDOMNode(this.refs.menu);
				menuNode.scrollTop = focusedOptionParent.className === 'Select-menu' ? focusedOptionNode.offsetTop : focusedOptionParent.offsetTop;
				this.hasScrolledToOption = true;
			} else if (!this.state.isOpen) {
				this.hasScrolledToOption = false;
			}

			if (this._scrollToFocusedOptionOnUpdate && this.refs.focused && this.refs.menu) {
				this._scrollToFocusedOptionOnUpdate = false;
				var focusedDOM = _reactDom2['default'].findDOMNode(this.refs.focused);
				var menuDOM = _reactDom2['default'].findDOMNode(this.refs.menu);
				var focusedRect = focusedDOM.getBoundingClientRect();
				var menuRect = menuDOM.getBoundingClientRect();
				if (focusedRect.bottom > menuRect.bottom || focusedRect.top < menuRect.top) {
					menuDOM.scrollTop = focusedDOM.offsetTop + focusedDOM.clientHeight - menuDOM.offsetHeight;
				}
			}
			if (this.props.scrollMenuIntoView && this.refs.menuContainer) {
				var menuContainerRect = this.refs.menuContainer.getBoundingClientRect();
				if (window.innerHeight < menuContainerRect.bottom + this.props.menuBuffer) {
					window.scrollBy(0, menuContainerRect.bottom + this.props.menuBuffer - window.innerHeight);
				}
			}
			if (prevProps.disabled !== this.props.disabled) {
				this.setState({ isFocused: false }); // eslint-disable-line react/no-did-update-set-state
				this.closeMenu();
			}
		},

		focus: function focus() {
			if (!this.refs.input) return;
			this.refs.input.focus();

			if (this.props.openAfterFocus) {
				this.setState({
					isOpen: true
				});
			}
		},

		blurInput: function blurInput() {
			if (!this.refs.input) return;
			this.refs.input.blur();
		},

		handleTouchMove: function handleTouchMove(event) {
			// Set a flag that the view is being dragged
			this.dragging = true;
		},

		handleTouchStart: function handleTouchStart(event) {
			// Set a flag that the view is not being dragged
			this.dragging = false;
		},

		handleTouchEnd: function handleTouchEnd(event) {
			// Check if the view is being dragged, In this case
			// we don't want to fire the click event (because the user only wants to scroll)
			if (this.dragging) return;

			// Fire the mouse events
			this.handleMouseDown(event);
		},

		handleTouchEndClearValue: function handleTouchEndClearValue(event) {
			// Check if the view is being dragged, In this case
			// we don't want to fire the click event (because the user only wants to scroll)
			if (this.dragging) return;

			// Clear the value
			this.clearValue(event);
		},

		handleMouseDown: function handleMouseDown(event) {
			// if the event was triggered by a mousedown and not the primary
			// button, or if the component is disabled, ignore it.
			if (this.props.disabled || event.type === 'mousedown' && event.button !== 0) {
				return;
			}

			if (event.target.tagName === 'INPUT') {
				return;
			}

			// prevent default event handlers
			event.stopPropagation();
			event.preventDefault();

			// for the non-searchable select, toggle the menu
			if (!this.props.searchable) {
				this.focus();
				return this.setState({
					isOpen: !this.state.isOpen
				});
			}

			if (this.state.isFocused) {
				// On iOS, we can get into a state where we think the input is focused but it isn't really,
				// since iOS ignores programmatic calls to input.focus() that weren't triggered by a click event.
				// Call focus() again here to be safe.
				this.focus();

				var input = this.refs.input;
				if (typeof input.getInput === 'function') {
					// Get the actual DOM input if the ref is an <Input /> component
					input = input.getInput();
				}

				// clears the value so that the cursor will be at the end of input when the component re-renders
				input.value = '';

				// if the input is focused, ensure the menu is open
				this.setState({
					isOpen: true,
					isPseudoFocused: false
				});
			} else {
				// otherwise, focus the input and open the menu
				this._openAfterFocus = true;
				this.focus();
			}
		},

		handleMouseDownOnArrow: function handleMouseDownOnArrow(event) {
			// if the event was triggered by a mousedown and not the primary
			// button, or if the component is disabled, ignore it.
			if (this.props.disabled || event.type === 'mousedown' && event.button !== 0) {
				return;
			}
			// If the menu isn't open, let the event bubble to the main handleMouseDown
			if (!this.state.isOpen) {
				return;
			}
			// prevent default event handlers
			event.stopPropagation();
			event.preventDefault();
			// close the menu
			this.closeMenu();
		},

		handleMouseDownOnMenu: function handleMouseDownOnMenu(event) {
			// if the event was triggered by a mousedown and not the primary
			// button, or if the component is disabled, ignore it.
			if (this.props.disabled || event.type === 'mousedown' && event.button !== 0) {
				return;
			}
			event.stopPropagation();
			event.preventDefault();

			this._openAfterFocus = true;
			this.focus();
		},

		closeMenu: function closeMenu() {
			this.setState({
				isOpen: false,
				isPseudoFocused: this.state.isFocused && !this.props.multi,
				inputValue: ''
			});
			this.hasScrolledToOption = false;
		},

		handleInputFocus: function handleInputFocus(event) {
			var isOpen = this.state.isOpen || this._openAfterFocus || this.props.openOnFocus;
			if (this.props.onFocus) {
				this.props.onFocus(event);
			}
			this.setState({
				isFocused: true,
				isOpen: isOpen
			});
			this._openAfterFocus = false;
		},

		handleInputBlur: function handleInputBlur(event) {
			// The check for menu.contains(activeElement) is necessary to prevent IE11's scrollbar from closing the menu in certain contexts.
			if (this.refs.menu && (this.refs.menu === document.activeElement || this.refs.menu.contains(document.activeElement))) {
				this.focus();
				return;
			}

			if (this.props.onBlur) {
				this.props.onBlur(event);
			}
			var onBlurredState = {
				isFocused: false,
				isOpen: false,
				isPseudoFocused: false
			};
			if (this.props.onBlurResetsInput) {
				onBlurredState.inputValue = '';
			}
			this.setState(onBlurredState);
		},

		handleInputChange: function handleInputChange(event) {
			var newInputValue = event.target.value;
			if (this.state.inputValue !== event.target.value && this.props.onInputChange) {
				var nextState = this.props.onInputChange(newInputValue);
				// Note: != used deliberately here to catch undefined and null
				if (nextState != null && typeof nextState !== 'object') {
					newInputValue = '' + nextState;
				}
			}
			this.setState({
				isOpen: true,
				isPseudoFocused: false,
				inputValue: newInputValue
			});
		},

		handleKeyDown: function handleKeyDown(event) {
			if (this.props.disabled) return;
			switch (event.keyCode) {
				case 8:
					// backspace
					if (!this.state.inputValue && this.props.backspaceRemoves) {
						event.preventDefault();
						this.popValue();
					}
					return;
				case 9:
					// tab
					if (event.shiftKey || !this.state.isOpen || !this.props.tabSelectsValue) {
						return;
					}
					this.selectFocusedOption();
					return;
				case 13:
					// enter
					if (!this.state.isOpen) return;
					event.stopPropagation();
					this.selectFocusedOption();
					break;
				case 27:
					// escape
					if (this.state.isOpen) {
						this.closeMenu();
						event.stopPropagation();
					} else if (this.props.clearable && this.props.escapeClearsValue) {
						this.clearValue(event);
						event.stopPropagation();
					}
					break;
				case 38:
					// up
					this.focusPreviousOption();
					break;
				case 40:
					// down
					this.focusNextOption();
					break;
				case 33:
					// page up
					this.focusPageUpOption();
					break;
				case 34:
					// page down
					this.focusPageDownOption();
					break;
				case 35:
					// end key
					this.focusEndOption();
					break;
				case 36:
					// home key
					this.focusStartOption();
					break;
				// case 188: // ,
				// 	if (this.props.allowCreate && this.props.multi) {
				// 		event.preventDefault();
				// 		event.stopPropagation();
				// 		this.selectFocusedOption();
				// 	} else {
				// 		return;
				// 	}
				// break;
				default:
					return;
			}
			event.preventDefault();
		},

		handleValueClick: function handleValueClick(option, event) {
			if (!this.props.onValueClick) return;
			this.props.onValueClick(option, event);
		},

		handleMenuScroll: function handleMenuScroll(event) {
			if (!this.props.onMenuScrollToBottom) return;
			var target = event.target;

			if (target.scrollHeight > target.offsetHeight && !(target.scrollHeight - target.offsetHeight - target.scrollTop)) {
				this.props.onMenuScrollToBottom();
			}
		},

		handleRequired: function handleRequired(value, multi) {
			if (!value) return true;
			return multi ? value.length === 0 : Object.keys(value).length === 0;
		},

		getOptionLabel: function getOptionLabel(op) {
			return op[this.props.labelKey];
		},

		/**
	  * Turns a value into an array from the given options
	  * @param	{String|Number|Array}	value		- the value of the select input
	  * @param	{Object}		nextProps	- optionally specify the nextProps so the returned array uses the latest configuration
	  * @returns	{Array}	the value of the select represented in an array
	  */
		getValueArray: function getValueArray(value, nextProps) {
			var _this = this;

			/** support optionally passing in the `nextProps` so `componentWillReceiveProps` updates will function as expected */
			var props = typeof nextProps === 'object' ? nextProps : this.props;
			if (props.multi) {
				if (typeof value === 'string') value = value.split(props.delimiter);
				if (!Array.isArray(value)) {
					if (value === null || value === undefined) return [];
					value = [value];
				}
				return value.map(function (value) {
					return _this.expandValue(value, props);
				}).filter(function (i) {
					return i;
				});
			}
			var expandedValue = this.expandValue(value, props);
			return expandedValue ? [expandedValue] : [];
		},

		/**
	  * Retrieve a value from the given options and valueKey
	  * @param	{String|Number|Array}	value	- the selected value(s)
	  * @param	{Object}		props	- the Select component's props (or nextProps)
	  */
		expandValue: function expandValue(value, props) {
			if (typeof value !== 'string' && typeof value !== 'number') return value;
			var _props = this.props;
			var labelKey = _props.labelKey;
			var valueKey = _props.valueKey;
			var renderInvalidValues = _props.renderInvalidValues;

			var options = this._flatOptions;
			if (!options || value === '') return;
			for (var i = 0; i < options.length; i++) {
				if (options[i][valueKey] === value) return options[i];
			}

			// no matching option, return an invalid option if renderInvalidValues is enabled
			if (renderInvalidValues) {
				var _ref;

				return _ref = {
					invalid: true
				}, _defineProperty(_ref, labelKey, value), _defineProperty(_ref, valueKey, value), _ref;
			}
		},

		setValue: function setValue(value) {
			var _this2 = this;

			if (this.props.autoBlur) {
				this.blurInput();
			}
			if (!this.props.onChange) return;
			if (this.props.required) {
				var required = this.handleRequired(value, this.props.multi);
				this.setState({ required: required });
			}
			if (this.props.simpleValue && value) {
				value = this.props.multi ? value.map(function (i) {
					return i[_this2.props.valueKey];
				}).join(this.props.delimiter) : value[this.props.valueKey];
			}
			this.props.onChange(value);
		},

		selectValue: function selectValue(value) {
			var _this3 = this;

			//NOTE: update value in the callback to make sure the input value is empty so that there are no sttyling issues (Chrome had issue otherwise)
			this.hasScrolledToOption = false;
			if (this.props.multi) {
				this.setState({
					inputValue: '',
					focusedIndex: null
				}, function () {
					_this3.addValue(value);
				});
			} else {
				this.setState({
					isOpen: false,
					inputValue: '',
					isPseudoFocused: this.state.isFocused
				}, function () {
					_this3.setValue(value);
				});
			}
		},

		addValue: function addValue(value) {
			var valueArray = this.getValueArray(this.props.value);
			this.setValue(valueArray.concat(value));
		},

		popValue: function popValue() {
			var valueArray = this.getValueArray(this.props.value);
			if (!valueArray.length) return;
			if (valueArray[valueArray.length - 1].clearableValue === false) return;
			this.setValue(valueArray.slice(0, valueArray.length - 1));
		},

		removeValue: function removeValue(value) {
			var valueArray = this.getValueArray(this.props.value);
			this.setValue(valueArray.filter(function (i) {
				return i !== value;
			}));
			this.focus();
		},

		clearValue: function clearValue(event) {
			// if the event was triggered by a mousedown and not the primary
			// button, ignore it.
			if (event && event.type === 'mousedown' && event.button !== 0) {
				return;
			}
			event.stopPropagation();
			event.preventDefault();
			this.setValue(this.props.resetValue);
			this.setState({
				isOpen: false,
				inputValue: ''
			}, this.focus);
		},

		focusOption: function focusOption(option) {
			this.setState({
				focusedOption: option
			});
		},

		focusNextOption: function focusNextOption() {
			this.focusAdjacentOption('next');
		},

		focusPreviousOption: function focusPreviousOption() {
			this.focusAdjacentOption('previous');
		},

		focusPageUpOption: function focusPageUpOption() {
			this.focusAdjacentOption('page_up');
		},

		focusPageDownOption: function focusPageDownOption() {
			this.focusAdjacentOption('page_down');
		},

		focusStartOption: function focusStartOption() {
			this.focusAdjacentOption('start');
		},

		focusEndOption: function focusEndOption() {
			this.focusAdjacentOption('end');
		},

		focusAdjacentOption: function focusAdjacentOption(dir) {
			var options = this._visibleOptions.map(function (option, index) {
				return { option: option, index: index };
			}).filter(function (option) {
				return !option.option.disabled;
			});
			this._scrollToFocusedOptionOnUpdate = true;
			if (!this.state.isOpen) {
				this.setState({
					isOpen: true,
					inputValue: '',
					focusedOption: this._focusedOption || options[dir === 'next' ? 0 : options.length - 1].option
				});
				return;
			}
			if (!options.length) return;
			var focusedIndex = -1;
			for (var i = 0; i < options.length; i++) {
				if (this._focusedOption === options[i].option) {
					focusedIndex = i;
					break;
				}
			}
			if (dir === 'next' && focusedIndex !== -1) {
				focusedIndex = (focusedIndex + 1) % options.length;
			} else if (dir === 'previous') {
				if (focusedIndex > 0) {
					focusedIndex = focusedIndex - 1;
				} else {
					focusedIndex = options.length - 1;
				}
			} else if (dir === 'start') {
				focusedIndex = 0;
			} else if (dir === 'end') {
				focusedIndex = options.length - 1;
			} else if (dir === 'page_up') {
				var potentialIndex = focusedIndex - this.props.pageSize;
				if (potentialIndex < 0) {
					focusedIndex = 0;
				} else {
					focusedIndex = potentialIndex;
				}
			} else if (dir === 'page_down') {
				var potentialIndex = focusedIndex + this.props.pageSize;
				if (potentialIndex > options.length - 1) {
					focusedIndex = options.length - 1;
				} else {
					focusedIndex = potentialIndex;
				}
			}

			if (focusedIndex === -1) {
				focusedIndex = 0;
			}

			this.setState({
				focusedIndex: options[focusedIndex].index,
				focusedOption: options[focusedIndex].option
			});
		},

		selectFocusedOption: function selectFocusedOption() {
			// if (this.props.allowCreate && !this.state.focusedOption) {
			// 	return this.selectValue(this.state.inputValue);
			// }
			if (this._focusedOption) {
				return this.selectValue(this._focusedOption);
			}
		},

		renderLoading: function renderLoading() {
			if (!this.props.isLoading) return;
			return _react2['default'].createElement(
				'span',
				{ className: 'Select-loading-zone', 'aria-hidden': 'true' },
				_react2['default'].createElement('span', { className: 'Select-loading' })
			);
		},

		renderValue: function renderValue(valueArray, isOpen) {
			var _this4 = this;

			var renderLabel = this.props.valueRenderer || this.getOptionLabel;
			var ValueComponent = this.props.valueComponent;
			if (!valueArray.length) {
				return !this.state.inputValue ? _react2['default'].createElement(
					'div',
					{ className: 'Select-placeholder' },
					this.props.placeholder
				) : null;
			}
			var onClick = this.props.onValueClick ? this.handleValueClick : null;
			if (this.props.multi) {
				return valueArray.map(function (value, i) {
					return _react2['default'].createElement(
						ValueComponent,
						{
							id: _this4._instancePrefix + '-value-' + i,
							instancePrefix: _this4._instancePrefix,
							disabled: _this4.props.disabled || value.clearableValue === false,
							key: 'value-' + i + '-' + value[_this4.props.valueKey],
							onClick: onClick,
							onRemove: _this4.removeValue,
							value: value
						},
						renderLabel(value),
						_react2['default'].createElement(
							'span',
							{ className: 'Select-aria-only' },
							' '
						)
					);
				});
			} else if (!this.state.inputValue) {
				if (isOpen) onClick = null;
				return _react2['default'].createElement(
					ValueComponent,
					{
						id: this._instancePrefix + '-value-item',
						disabled: this.props.disabled,
						instancePrefix: this._instancePrefix,
						onClick: onClick,
						value: valueArray[0]
					},
					renderLabel(valueArray[0])
				);
			}
		},

		renderInput: function renderInput(valueArray, focusedOptionIndex) {
			if (this.props.inputRenderer) {
				return this.props.inputRenderer();
			} else {
				var _classNames;

				var className = (0, _classnames2['default'])('Select-input', this.props.inputProps.className);
				var isOpen = !!this.state.isOpen;

				var ariaOwns = (0, _classnames2['default'])((_classNames = {}, _defineProperty(_classNames, this._instancePrefix + '-list', isOpen), _defineProperty(_classNames, this._instancePrefix + '-backspace-remove-message', this.props.multi && !this.props.disabled && this.state.isFocused && !this.state.inputValue), _classNames));

				// TODO: Check how this project includes Object.assign()
				var inputProps = _extends({}, this.props.inputProps, {
					role: 'combobox',
					'aria-expanded': '' + isOpen,
					'aria-owns': ariaOwns,
					'aria-haspopup': '' + isOpen,
					'aria-activedescendant': isOpen ? this._instancePrefix + '-option-' + focusedOptionIndex : this._instancePrefix + '-value',
					'aria-labelledby': this.props['aria-labelledby'],
					'aria-label': this.props['aria-label'],
					className: className,
					tabIndex: this.props.tabIndex,
					onBlur: this.handleInputBlur,
					onChange: this.handleInputChange,
					onFocus: this.handleInputFocus,
					ref: 'input',
					required: this.state.required,
					value: this.state.inputValue
				});

				if (this.props.disabled || !this.props.searchable) {
					var divProps = (0, _blacklist2['default'])(this.props.inputProps, 'inputClassName');
					return _react2['default'].createElement('div', _extends({}, divProps, {
						role: 'combobox',
						'aria-expanded': isOpen,
						'aria-owns': isOpen ? this._instancePrefix + '-list' : this._instancePrefix + '-value',
						'aria-activedescendant': isOpen ? this._instancePrefix + '-option-' + focusedOptionIndex : this._instancePrefix + '-value',
						className: className,
						tabIndex: this.props.tabIndex || 0,
						onBlur: this.handleInputBlur,
						onFocus: this.handleInputFocus,
						ref: 'input',
						'aria-readonly': '' + !!this.props.disabled,
						style: { border: 0, width: 1, display: 'inline-block' } }));
				}

				if (this.props.autosize) {
					return _react2['default'].createElement(_reactInputAutosize2['default'], _extends({}, inputProps, { minWidth: '5px' }));
				}
				return _react2['default'].createElement(
					'div',
					{ className: className },
					_react2['default'].createElement('input', inputProps)
				);
			}
		},

		renderClear: function renderClear() {
			if (!this.props.clearable || !this.props.value || this.props.multi && !this.props.value.length || this.props.disabled || this.props.isLoading) return;
			return _react2['default'].createElement(
				'span',
				{ className: 'Select-clear-zone', title: this.props.multi ? this.props.clearAllText : this.props.clearValueText,
					'aria-label': this.props.multi ? this.props.clearAllText : this.props.clearValueText,
					onMouseDown: this.clearValue,
					onTouchStart: this.handleTouchStart,
					onTouchMove: this.handleTouchMove,
					onTouchEnd: this.handleTouchEndClearValue
				},
				_react2['default'].createElement('span', { className: 'Select-clear', dangerouslySetInnerHTML: { __html: '&times;' } })
			);
		},

		renderArrow: function renderArrow() {
			return _react2['default'].createElement(
				'span',
				{ className: 'Select-arrow-zone', onMouseDown: this.handleMouseDownOnArrow },
				_react2['default'].createElement('span', { className: 'Select-arrow', onMouseDown: this.handleMouseDownOnArrow })
			);
		},

		filterOptions: function filterOptions(options, excludeOptions) {
			var _this5 = this;

			var excludeOptionValues = null;
			var filterValue = this.state.inputValue;
			if (typeof this.props.filterOptions === 'function') {
				return this.props.filterOptions.call(this, options, filterValue, excludeOptions);
			} else if (this.props.filterOptions) {
				var _ret = (function () {
					if (_this5.props.ignoreAccents) {
						filterValue = (0, _utilsStripDiacritics2['default'])(filterValue);
					}
					if (_this5.props.ignoreCase) {
						filterValue = filterValue.toLowerCase();
					}
					if (excludeOptions) excludeOptionValues = excludeOptions.map(function (i) {
						return i[_this5.props.valueKey];
					});
					var includeOption = function includeOption(option) {
						if (excludeOptionValues && excludeOptionValues.indexOf(option[_this5.props.valueKey]) > -1) return false;
						if (_this5.props.filterOption) return _this5.props.filterOption.call(_this5, option, filterValue);
						if (!filterValue) return true;
						var valueTest = String(option[_this5.props.valueKey]);
						var labelTest = String(option[_this5.props.labelKey]);
						if (_this5.props.ignoreAccents) {
							if (_this5.props.matchProp !== 'label') valueTest = (0, _utilsStripDiacritics2['default'])(valueTest);
							if (_this5.props.matchProp !== 'value') labelTest = (0, _utilsStripDiacritics2['default'])(labelTest);
						}
						if (_this5.props.ignoreCase) {
							if (_this5.props.matchProp !== 'label') valueTest = valueTest.toLowerCase();
							if (_this5.props.matchProp !== 'value') labelTest = labelTest.toLowerCase();
						}
						return _this5.props.matchPos === 'start' ? _this5.props.matchProp !== 'label' && valueTest.substr(0, filterValue.length) === filterValue || _this5.props.matchProp !== 'value' && labelTest.substr(0, filterValue.length) === filterValue : _this5.props.matchProp !== 'label' && valueTest.indexOf(filterValue) >= 0 || _this5.props.matchProp !== 'value' && labelTest.indexOf(filterValue) >= 0;
					};
					var filteredOptions = [];
					options.forEach(function (option) {
						if (_this5.isGroup(option)) {
							var filteredGroup = clone(option);
							filteredGroup.options = _this5.filterOptions(option.options, excludeOptions);
							if (filteredGroup.options.length) {
								filteredOptions.push(filteredGroup);
							};
						} else if (includeOption(option)) {
							filteredOptions.push(option);
						};
					});
					return {
						v: filteredOptions
					};
				})();

				if (typeof _ret === 'object') return _ret.v;
			} else {
				return options;
			}
		},

		isGroup: function isGroup(option) {
			return option && Array.isArray(option.options);
		},

		flattenOptions: function flattenOptions(options) {
			if (!options) return;
			var flatOptions = [];
			for (var i = 0; i < options.length; i++) {
				if (this.isGroup(options[i])) {
					flatOptions = flatOptions.concat(this.flattenOptions(options[i].options));
				} else {
					flatOptions.push(options[i]);
				}
			}
			return flatOptions;
		},

		renderMenu: function renderMenu(options, valueArray, focusedOption) {
			var _this6 = this;

			if (options && options.length) {
				if (this.props.menuRenderer) {
					return this.props.menuRenderer({
						focusedOption: focusedOption,
						focusOption: this.focusOption,
						labelKey: this.props.labelKey,
						options: options,
						selectValue: this.selectValue,
						valueArray: valueArray
					});
				} else {
					var _ret2 = (function () {
						var OptionGroup = _this6.props.optionGroupComponent;
						var Option = _this6.props.optionComponent;
						var renderLabel = _this6.props.optionRenderer || _this6.getOptionLabel;

						return {
							v: options.map(function (option, i) {
								if (_this6.isGroup(option)) {
									var optionGroupClass = (0, _classnames2['default'])({
										'Select-option-group': true
									});

									return _react2['default'].createElement(
										OptionGroup,
										{
											className: optionGroupClass,
											key: 'option-group-' + i,
											label: renderLabel(option),
											option: option
										},
										_this6.renderMenu(option.options, valueArray, focusedOption)
									);
								} else {
									var isSelected = valueArray && valueArray.indexOf(option) > -1;
									var isFocused = option === focusedOption;
									var optionRef = isFocused ? 'focused' : null;
									var optionClass = (0, _classnames2['default'])(_this6.props.optionClassName, {
										'Select-option': true,
										'is-selected': isSelected,
										'is-focused': isFocused,
										'is-disabled': option.disabled
									});

									return _react2['default'].createElement(
										Option,
										{
											instancePrefix: _this6._instancePrefix,
											optionIndex: i,
											className: optionClass,
											isDisabled: option.disabled,
											isFocused: isFocused,
											key: 'option-' + i + '-' + option[_this6.props.valueKey],
											onSelect: _this6.selectValue,
											onFocus: _this6.focusOption,
											option: option,
											isSelected: isSelected,
											ref: optionRef
										},
										renderLabel(option)
									);
								}
							})
						};
					})();

					if (typeof _ret2 === 'object') return _ret2.v;
				}
			} else if (this.props.noResultsText) {
				return _react2['default'].createElement(
					'div',
					{ className: 'Select-noresults' },
					this.props.noResultsText
				);
			} else {
				return null;
			}
		},

		renderHiddenField: function renderHiddenField(valueArray) {
			var _this7 = this;

			if (!this.props.name) return;
			if (this.props.joinValues) {
				var value = valueArray.map(function (i) {
					return stringifyValue(i[_this7.props.valueKey]);
				}).join(this.props.delimiter);
				return _react2['default'].createElement('input', {
					type: 'hidden',
					ref: 'value',
					name: this.props.name,
					value: value,
					disabled: this.props.disabled });
			}
			return valueArray.map(function (item, index) {
				return _react2['default'].createElement('input', { key: 'hidden.' + index,
					type: 'hidden',
					ref: 'value' + index,
					name: _this7.props.name,
					value: stringifyValue(item[_this7.props.valueKey]),
					disabled: _this7.props.disabled });
			});
		},

		getFocusableOptionIndex: function getFocusableOptionIndex(selectedOption) {
			var options = this._visibleOptions;
			if (!options.length) return null;

			var focusedOption = this.state.focusedOption || selectedOption;
			if (focusedOption && !focusedOption.disabled) {
				var focusedOptionIndex = options.indexOf(focusedOption);
				if (focusedOptionIndex !== -1) {
					return focusedOptionIndex;
				}
			}

			for (var i = 0; i < options.length; i++) {
				if (!options[i].disabled) return i;
			}
			return null;
		},

		renderOuter: function renderOuter(options, valueArray, focusedOption) {
			var Dropdown = this.props.dropdownComponent;
			var menu = this.renderMenu(options, valueArray, focusedOption);
			if (!menu) {
				return null;
			}

			return _react2['default'].createElement(
				Dropdown,
				null,
				_react2['default'].createElement(
					'div',
					{ ref: 'menuContainer', className: 'Select-menu-outer', style: this.props.menuContainerStyle },
					_react2['default'].createElement(
						'div',
						{ ref: 'menu', role: 'listbox', className: 'Select-menu', id: this._instancePrefix + '-list',
							style: this.props.menuStyle,
							onScroll: this.handleMenuScroll,
							onMouseDown: this.handleMouseDownOnMenu },
						menu
					)
				)
			);
		},

		render: function render() {
			var valueArray = this.getValueArray(this.props.value);
			var options = this.filterOptions(this.props.options || [], this.props.multi ? valueArray : null);
			this._visibleOptions = this.flattenOptions(options);
			var isOpen = typeof this.props.isOpen === 'boolean' ? this.props.isOpen : this.state.isOpen;
			if (this.props.multi && !options.length && valueArray.length && !this.state.inputValue) isOpen = false;
			var focusedOptionIndex = this.getFocusableOptionIndex(valueArray[0]);

			var focusedOption = null;
			if (focusedOptionIndex !== null) {
				focusedOption = this._focusedOption = this._visibleOptions[focusedOptionIndex];
			} else {
				focusedOption = this._focusedOption = null;
			}
			var className = (0, _classnames2['default'])('Select', this.props.className, {
				'Select--multi': this.props.multi,
				'Select--single': !this.props.multi,
				'is-disabled': this.props.disabled,
				'is-focused': this.state.isFocused,
				'is-loading': this.props.isLoading,
				'is-open': isOpen,
				'is-pseudo-focused': this.state.isPseudoFocused,
				'is-searchable': this.props.searchable,
				'has-value': valueArray.length
			});

			var removeMessage = null;
			if (this.props.multi && !this.props.disabled && valueArray.length && !this.state.inputValue && this.state.isFocused && this.props.backspaceRemoves) {
				removeMessage = _react2['default'].createElement(
					'span',
					{ id: this._instancePrefix + '-backspace-remove-message', className: 'Select-aria-only', 'aria-live': 'assertive' },
					this.props.backspaceToRemoveMessage.replace('{label}', valueArray[valueArray.length - 1][this.props.labelKey])
				);
			}

			return _react2['default'].createElement(
				'div',
				{ ref: 'wrapper',
					className: className,
					style: this.props.wrapperStyle },
				this.renderHiddenField(valueArray),
				_react2['default'].createElement(
					'div',
					{ ref: 'control',
						className: 'Select-control',
						style: this.props.style,
						onKeyDown: this.handleKeyDown,
						onMouseDown: this.handleMouseDown,
						onTouchEnd: this.handleTouchEnd,
						onTouchStart: this.handleTouchStart,
						onTouchMove: this.handleTouchMove
					},
					_react2['default'].createElement(
						'span',
						{ className: 'Select-multi-value-wrapper', id: this._instancePrefix + '-value' },
						this.renderValue(valueArray, isOpen),
						this.renderInput(valueArray, focusedOptionIndex)
					),
					removeMessage,
					this.renderLoading(),
					this.renderClear(),
					this.renderArrow()
				),
				isOpen ? this.renderOuter(options, !this.props.multi ? valueArray : null, focusedOption) : null
			);
		}

	});

	exports['default'] = Select;
	module.exports = exports['default'];

/***/ },
/* 325 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
	  Copyright (c) 2017 Jed Watson.
	  Licensed under the MIT License (MIT), see
	  http://jedwatson.github.io/classnames
	*/
	/* global define */

	(function () {
		'use strict';

		var hasOwn = {}.hasOwnProperty;

		function classNames () {
			var classes = [];

			for (var i = 0; i < arguments.length; i++) {
				var arg = arguments[i];
				if (!arg) continue;

				var argType = typeof arg;

				if (argType === 'string' || argType === 'number') {
					classes.push(arg);
				} else if (Array.isArray(arg) && arg.length) {
					var inner = classNames.apply(null, arg);
					if (inner) {
						classes.push(inner);
					}
				} else if (argType === 'object') {
					for (var key in arg) {
						if (hasOwn.call(arg, key) && arg[key]) {
							classes.push(key);
						}
					}
				}
			}

			return classes.join(' ');
		}

		if (typeof module !== 'undefined' && module.exports) {
			classNames.default = classNames;
			module.exports = classNames;
		} else if (true) {
			// register as 'classnames', consistent with npm package name
			!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () {
				return classNames;
			}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
		} else {
			window.classNames = classNames;
		}
	}());


/***/ },
/* 326 */
/***/ function(module, exports) {

	module.exports = function blacklist (src) {
	  var copy = {}
	  var filter = arguments[1]

	  if (typeof filter === 'string') {
	    filter = {}
	    for (var i = 1; i < arguments.length; i++) {
	      filter[arguments[i]] = true
	    }
	  }

	  for (var key in src) {
	    // blacklist?
	    if (filter[key]) continue

	    copy[key] = src[key]
	  }

	  return copy
	}


/***/ },
/* 327 */
/***/ function(module, exports) {

	'use strict';

	var map = [{ 'base': 'A', 'letters': /[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g }, { 'base': 'AA', 'letters': /[\uA732]/g }, { 'base': 'AE', 'letters': /[\u00C6\u01FC\u01E2]/g }, { 'base': 'AO', 'letters': /[\uA734]/g }, { 'base': 'AU', 'letters': /[\uA736]/g }, { 'base': 'AV', 'letters': /[\uA738\uA73A]/g }, { 'base': 'AY', 'letters': /[\uA73C]/g }, { 'base': 'B', 'letters': /[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g }, { 'base': 'C', 'letters': /[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g }, { 'base': 'D', 'letters': /[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g }, { 'base': 'DZ', 'letters': /[\u01F1\u01C4]/g }, { 'base': 'Dz', 'letters': /[\u01F2\u01C5]/g }, { 'base': 'E', 'letters': /[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g }, { 'base': 'F', 'letters': /[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g }, { 'base': 'G', 'letters': /[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g }, { 'base': 'H', 'letters': /[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g }, { 'base': 'I', 'letters': /[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g }, { 'base': 'J', 'letters': /[\u004A\u24BF\uFF2A\u0134\u0248]/g }, { 'base': 'K', 'letters': /[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g }, { 'base': 'L', 'letters': /[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g }, { 'base': 'LJ', 'letters': /[\u01C7]/g }, { 'base': 'Lj', 'letters': /[\u01C8]/g }, { 'base': 'M', 'letters': /[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g }, { 'base': 'N', 'letters': /[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g }, { 'base': 'NJ', 'letters': /[\u01CA]/g }, { 'base': 'Nj', 'letters': /[\u01CB]/g }, { 'base': 'O', 'letters': /[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g }, { 'base': 'OI', 'letters': /[\u01A2]/g }, { 'base': 'OO', 'letters': /[\uA74E]/g }, { 'base': 'OU', 'letters': /[\u0222]/g }, { 'base': 'P', 'letters': /[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g }, { 'base': 'Q', 'letters': /[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g }, { 'base': 'R', 'letters': /[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g }, { 'base': 'S', 'letters': /[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g }, { 'base': 'T', 'letters': /[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g }, { 'base': 'TZ', 'letters': /[\uA728]/g }, { 'base': 'U', 'letters': /[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g }, { 'base': 'V', 'letters': /[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g }, { 'base': 'VY', 'letters': /[\uA760]/g }, { 'base': 'W', 'letters': /[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g }, { 'base': 'X', 'letters': /[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g }, { 'base': 'Y', 'letters': /[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g }, { 'base': 'Z', 'letters': /[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g }, { 'base': 'a', 'letters': /[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g }, { 'base': 'aa', 'letters': /[\uA733]/g }, { 'base': 'ae', 'letters': /[\u00E6\u01FD\u01E3]/g }, { 'base': 'ao', 'letters': /[\uA735]/g }, { 'base': 'au', 'letters': /[\uA737]/g }, { 'base': 'av', 'letters': /[\uA739\uA73B]/g }, { 'base': 'ay', 'letters': /[\uA73D]/g }, { 'base': 'b', 'letters': /[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g }, { 'base': 'c', 'letters': /[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g }, { 'base': 'd', 'letters': /[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g }, { 'base': 'dz', 'letters': /[\u01F3\u01C6]/g }, { 'base': 'e', 'letters': /[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g }, { 'base': 'f', 'letters': /[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g }, { 'base': 'g', 'letters': /[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g }, { 'base': 'h', 'letters': /[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g }, { 'base': 'hv', 'letters': /[\u0195]/g }, { 'base': 'i', 'letters': /[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g }, { 'base': 'j', 'letters': /[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g }, { 'base': 'k', 'letters': /[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g }, { 'base': 'l', 'letters': /[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g }, { 'base': 'lj', 'letters': /[\u01C9]/g }, { 'base': 'm', 'letters': /[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g }, { 'base': 'n', 'letters': /[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g }, { 'base': 'nj', 'letters': /[\u01CC]/g }, { 'base': 'o', 'letters': /[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g }, { 'base': 'oi', 'letters': /[\u01A3]/g }, { 'base': 'ou', 'letters': /[\u0223]/g }, { 'base': 'oo', 'letters': /[\uA74F]/g }, { 'base': 'p', 'letters': /[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g }, { 'base': 'q', 'letters': /[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g }, { 'base': 'r', 'letters': /[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g }, { 'base': 's', 'letters': /[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g }, { 'base': 't', 'letters': /[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g }, { 'base': 'tz', 'letters': /[\uA729]/g }, { 'base': 'u', 'letters': /[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g }, { 'base': 'v', 'letters': /[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g }, { 'base': 'vy', 'letters': /[\uA761]/g }, { 'base': 'w', 'letters': /[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g }, { 'base': 'x', 'letters': /[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g }, { 'base': 'y', 'letters': /[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g }, { 'base': 'z', 'letters': /[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g }];

	module.exports = function stripDiacritics(str) {
		for (var i = 0; i < map.length; i++) {
			str = str.replace(map[i].letters, map[i].base);
		}
		return str;
	};

/***/ },
/* 328 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _Select = __webpack_require__(324);

	var _Select2 = _interopRequireDefault(_Select);

	var _utilsStripDiacritics = __webpack_require__(327);

	var _utilsStripDiacritics2 = _interopRequireDefault(_utilsStripDiacritics);

	var requestId = 0;

	function initCache(cache) {
		if (cache && typeof cache !== 'object') {
			cache = {};
		}
		return cache ? cache : null;
	}

	function updateCache(cache, input, data) {
		if (!cache) return;
		cache[input] = data;
	}

	function getFromCache(cache, input) {
		if (!cache) return;
		for (var i = input.length; i >= 0; --i) {
			var cacheKey = input.slice(0, i);
			if (cache[cacheKey] && (input === cacheKey || cache[cacheKey].complete)) {
				return cache[cacheKey];
			}
		}
	}

	function thenPromise(promise, callback) {
		if (!promise || typeof promise.then !== 'function') return;
		return promise.then(function (data) {
			callback(null, data);
		}, function (err) {
			callback(err);
		});
	}

	var stringOrNode = _react2['default'].PropTypes.oneOfType([_react2['default'].PropTypes.string, _react2['default'].PropTypes.node]);

	var Async = _react2['default'].createClass({
		displayName: 'Async',

		propTypes: {
			cache: _react2['default'].PropTypes.any, // object to use to cache results, can be null to disable cache
			ignoreAccents: _react2['default'].PropTypes.bool, // whether to strip diacritics when filtering (shared with Select)
			ignoreCase: _react2['default'].PropTypes.bool, // whether to perform case-insensitive filtering (shared with Select)
			isLoading: _react2['default'].PropTypes.bool, // overrides the isLoading state when set to true
			loadOptions: _react2['default'].PropTypes.func.isRequired, // function to call to load options asynchronously
			loadingPlaceholder: _react2['default'].PropTypes.string, // replaces the placeholder while options are loading
			minimumInput: _react2['default'].PropTypes.number, // the minimum number of characters that trigger loadOptions
			noResultsText: stringOrNode, // placeholder displayed when there are no matching search results (shared with Select)
			onInputChange: _react2['default'].PropTypes.func, // onInputChange handler: function (inputValue) {}
			placeholder: stringOrNode, // field placeholder, displayed when there's no value (shared with Select)
			searchPromptText: stringOrNode, // label to prompt for search input
			searchingText: _react2['default'].PropTypes.string },
		// message to display while options are loading
		getDefaultProps: function getDefaultProps() {
			return {
				cache: true,
				ignoreAccents: true,
				ignoreCase: true,
				loadingPlaceholder: 'Loading...',
				minimumInput: 0,
				searchingText: 'Searching...',
				searchPromptText: 'Type to search'
			};
		},
		getInitialState: function getInitialState() {
			return {
				cache: initCache(this.props.cache),
				isLoading: false,
				options: []
			};
		},
		componentWillMount: function componentWillMount() {
			this._lastInput = '';
		},
		componentDidMount: function componentDidMount() {
			this.loadOptions('');
		},
		componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
			if (nextProps.cache !== this.props.cache) {
				this.setState({
					cache: initCache(nextProps.cache)
				});
			}
		},
		focus: function focus() {
			this.refs.select.focus();
		},
		resetState: function resetState() {
			this._currentRequestId = -1;
			this.setState({
				isLoading: false,
				options: []
			});
		},
		getResponseHandler: function getResponseHandler(input) {
			var _this = this;

			var _requestId = this._currentRequestId = requestId++;
			return function (err, data) {
				if (err) throw err;
				if (!_this.isMounted()) return;
				updateCache(_this.state.cache, input, data);
				if (_requestId !== _this._currentRequestId) return;
				_this.setState({
					isLoading: false,
					options: data && data.options || []
				});
			};
		},
		loadOptions: function loadOptions(input) {
			if (this.props.onInputChange) {
				var nextState = this.props.onInputChange(input);
				// Note: != used deliberately here to catch undefined and null
				if (nextState != null) {
					input = '' + nextState;
				}
			}
			if (this.props.ignoreAccents) input = (0, _utilsStripDiacritics2['default'])(input);
			if (this.props.ignoreCase) input = input.toLowerCase();

			this._lastInput = input;
			if (input.length < this.props.minimumInput) {
				return this.resetState();
			}
			var cacheResult = getFromCache(this.state.cache, input);
			if (cacheResult) {
				return this.setState({
					options: cacheResult.options
				});
			}
			this.setState({
				isLoading: true
			});
			var responseHandler = this.getResponseHandler(input);
			var inputPromise = thenPromise(this.props.loadOptions(input, responseHandler), responseHandler);
			return inputPromise ? inputPromise.then(function () {
				return input;
			}) : input;
		},
		render: function render() {
			var noResultsText = this.props.noResultsText;
			var _state = this.state;
			var isLoading = _state.isLoading;
			var options = _state.options;

			if (this.props.isLoading) isLoading = true;
			var placeholder = isLoading ? this.props.loadingPlaceholder : this.props.placeholder;
			if (isLoading) {
				noResultsText = this.props.searchingText;
			} else if (!options.length && this._lastInput.length < this.props.minimumInput) {
				noResultsText = this.props.searchPromptText;
			}
			return _react2['default'].createElement(_Select2['default'], _extends({}, this.props, {
				ref: 'select',
				isLoading: isLoading,
				noResultsText: noResultsText,
				onInputChange: this.loadOptions,
				options: options,
				placeholder: placeholder
			}));
		}
	});

	module.exports = Async;

/***/ },
/* 329 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var Dropdown = _react2['default'].createClass({
	  displayName: 'Dropdown',

	  propTypes: {
	    children: _react2['default'].PropTypes.node
	  },
	  render: function render() {
	    // This component adds no markup
	    return this.props.children;
	  }
	});

	module.exports = Dropdown;

/***/ },
/* 330 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _classnames = __webpack_require__(325);

	var _classnames2 = _interopRequireDefault(_classnames);

	var Option = _react2['default'].createClass({
		displayName: 'Option',

		propTypes: {
			children: _react2['default'].PropTypes.node,
			className: _react2['default'].PropTypes.string, // className (based on mouse position)
			instancePrefix: _react2['default'].PropTypes.string.isRequired, // unique prefix for the ids (used for aria)
			isDisabled: _react2['default'].PropTypes.bool, // the option is disabled
			isFocused: _react2['default'].PropTypes.bool, // the option is focused
			isSelected: _react2['default'].PropTypes.bool, // the option is selected
			onFocus: _react2['default'].PropTypes.func, // method to handle mouseEnter on option element
			onSelect: _react2['default'].PropTypes.func, // method to handle click on option element
			onUnfocus: _react2['default'].PropTypes.func, // method to handle mouseLeave on option element
			option: _react2['default'].PropTypes.object.isRequired, // object that is base for that option
			optionIndex: _react2['default'].PropTypes.number },
		// index of the option, used to generate unique ids for aria
		blockEvent: function blockEvent(event) {
			event.preventDefault();
			event.stopPropagation();
			if (event.target.tagName !== 'A' || !('href' in event.target)) {
				return;
			}
			if (event.target.target) {
				window.open(event.target.href, event.target.target);
			} else {
				window.location.href = event.target.href;
			}
		},

		handleMouseDown: function handleMouseDown(event) {
			event.preventDefault();
			event.stopPropagation();
			this.props.onSelect(this.props.option, event);
		},

		handleMouseEnter: function handleMouseEnter(event) {
			this.onFocus(event);
		},

		handleMouseMove: function handleMouseMove(event) {
			this.onFocus(event);
		},

		handleTouchEnd: function handleTouchEnd(event) {
			// Check if the view is being dragged, In this case
			// we don't want to fire the click event (because the user only wants to scroll)
			if (this.dragging) return;

			this.handleMouseDown(event);
		},

		handleTouchMove: function handleTouchMove(event) {
			// Set a flag that the view is being dragged
			this.dragging = true;
		},

		handleTouchStart: function handleTouchStart(event) {
			// Set a flag that the view is not being dragged
			this.dragging = false;
		},

		onFocus: function onFocus(event) {
			if (!this.props.isFocused) {
				this.props.onFocus(this.props.option, event);
			}
		},
		render: function render() {
			var _props = this.props;
			var option = _props.option;
			var instancePrefix = _props.instancePrefix;
			var optionIndex = _props.optionIndex;

			var className = (0, _classnames2['default'])(this.props.className, option.className);

			return option.disabled ? _react2['default'].createElement(
				'div',
				{ className: className,
					onMouseDown: this.blockEvent,
					onClick: this.blockEvent },
				this.props.children
			) : _react2['default'].createElement(
				'div',
				{ className: className,
					style: option.style,
					role: 'option',
					onMouseDown: this.handleMouseDown,
					onMouseEnter: this.handleMouseEnter,
					onMouseMove: this.handleMouseMove,
					onTouchStart: this.handleTouchStart,
					onTouchMove: this.handleTouchMove,
					onTouchEnd: this.handleTouchEnd,
					id: instancePrefix + '-option-' + optionIndex,
					title: option.title },
				this.props.children
			);
		}
	});

	module.exports = Option;

/***/ },
/* 331 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _classnames = __webpack_require__(325);

	var _classnames2 = _interopRequireDefault(_classnames);

	var OptionGroup = _react2['default'].createClass({
		displayName: 'OptionGroup',

		propTypes: {
			children: _react2['default'].PropTypes.any,
			className: _react2['default'].PropTypes.string, // className (based on mouse position)
			label: _react2['default'].PropTypes.node, // the heading to show above the child options
			option: _react2['default'].PropTypes.object.isRequired },

		// object that is base for that option group
		blockEvent: function blockEvent(event) {
			event.preventDefault();
			event.stopPropagation();
			if (event.target.tagName !== 'A' || !('href' in event.target)) {
				return;
			}
			if (event.target.target) {
				window.open(event.target.href, event.target.target);
			} else {
				window.location.href = event.target.href;
			}
		},

		handleMouseDown: function handleMouseDown(event) {
			event.preventDefault();
			event.stopPropagation();
		},

		handleTouchEnd: function handleTouchEnd(event) {
			// Check if the view is being dragged, In this case
			// we don't want to fire the click event (because the user only wants to scroll)
			if (this.dragging) return;

			this.handleMouseDown(event);
		},

		handleTouchMove: function handleTouchMove(event) {
			// Set a flag that the view is being dragged
			this.dragging = true;
		},

		handleTouchStart: function handleTouchStart(event) {
			// Set a flag that the view is not being dragged
			this.dragging = false;
		},

		render: function render() {
			var option = this.props.option;

			var className = (0, _classnames2['default'])(this.props.className, option.className);

			return option.disabled ? _react2['default'].createElement(
				'div',
				{ className: className,
					onMouseDown: this.blockEvent,
					onClick: this.blockEvent },
				this.props.children
			) : _react2['default'].createElement(
				'div',
				{ className: className,
					style: option.style,
					onMouseDown: this.handleMouseDown,
					onMouseEnter: this.handleMouseEnter,
					onMouseMove: this.handleMouseMove,
					onTouchStart: this.handleTouchStart,
					onTouchMove: this.handleTouchMove,
					onTouchEnd: this.handleTouchEnd,
					title: option.title },
				_react2['default'].createElement(
					'div',
					{ className: 'Select-option-group-label' },
					this.props.label
				),
				this.props.children
			);
		}
	});

	module.exports = OptionGroup;

/***/ },
/* 332 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _classnames = __webpack_require__(325);

	var _classnames2 = _interopRequireDefault(_classnames);

	var Value = _react2['default'].createClass({

		displayName: 'Value',

		propTypes: {
			children: _react2['default'].PropTypes.node,
			disabled: _react2['default'].PropTypes.bool, // disabled prop passed to ReactSelect
			id: _react2['default'].PropTypes.string, // Unique id for the value - used for aria
			onClick: _react2['default'].PropTypes.func, // method to handle click on value label
			onRemove: _react2['default'].PropTypes.func, // method to handle removal of the value
			value: _react2['default'].PropTypes.object.isRequired },

		// the option object for this value
		handleMouseDown: function handleMouseDown(event) {
			if (event.type === 'mousedown' && event.button !== 0) {
				return;
			}
			if (this.props.onClick) {
				event.stopPropagation();
				this.props.onClick(this.props.value, event);
				return;
			}
			if (this.props.value.href) {
				event.stopPropagation();
			}
		},

		onRemove: function onRemove(event) {
			event.preventDefault();
			event.stopPropagation();
			this.props.onRemove(this.props.value);
		},

		handleTouchEndRemove: function handleTouchEndRemove(event) {
			// Check if the view is being dragged, In this case
			// we don't want to fire the click event (because the user only wants to scroll)
			if (this.dragging) return;

			// Fire the mouse events
			this.onRemove(event);
		},

		handleTouchMove: function handleTouchMove(event) {
			// Set a flag that the view is being dragged
			this.dragging = true;
		},

		handleTouchStart: function handleTouchStart(event) {
			// Set a flag that the view is not being dragged
			this.dragging = false;
		},

		renderRemoveIcon: function renderRemoveIcon() {
			if (this.props.disabled || !this.props.onRemove) return;
			return _react2['default'].createElement(
				'span',
				{ className: 'Select-value-icon',
					'aria-hidden': 'true',
					onMouseDown: this.onRemove,
					onTouchEnd: this.handleTouchEndRemove,
					onTouchStart: this.handleTouchStart,
					onTouchMove: this.handleTouchMove },
				'×'
			);
		},

		renderLabel: function renderLabel() {
			var className = 'Select-value-label';
			return this.props.onClick || this.props.value.href ? _react2['default'].createElement(
				'a',
				{ className: className, href: this.props.value.href, target: this.props.value.target, onMouseDown: this.handleMouseDown, onTouchEnd: this.handleMouseDown },
				this.props.children
			) : _react2['default'].createElement(
				'span',
				{ className: className, role: 'option', 'aria-selected': 'true', id: this.props.id },
				this.props.children
			);
		},

		render: function render() {
			return _react2['default'].createElement(
				'div',
				{ className: (0, _classnames2['default'])('Select-value', this.props.value.className),
					style: this.props.value.style,
					title: this.props.value.title
				},
				this.renderRemoveIcon(),
				this.renderLabel()
			);
		}

	});

	module.exports = Value;

/***/ },
/* 333 */
/***/ function(module, exports) {

	// removed by extract-text-webpack-plugin

/***/ },
/* 334 */,
/* 335 */,
/* 336 */,
/* 337 */
/***/ function(module, exports) {

	// removed by extract-text-webpack-plugin
	module.exports = {"root":"tata_root_4bp"};

/***/ },
/* 338 */,
/* 339 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["StarRating"] = __webpack_require__(340);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 340 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _react = __webpack_require__(28);

	var _react2 = _interopRequireDefault(_react);

	var _star_rating = __webpack_require__(341);

	var _star_rating2 = _interopRequireDefault(_star_rating);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var StarRating = function (_React$Component) {
	  _inherits(StarRating, _React$Component);

	  function StarRating(props) {
	    _classCallCheck(this, StarRating);

	    var _this = _possibleConstructorReturn(this, (StarRating.__proto__ || Object.getPrototypeOf(StarRating)).call(this, props));

	    _this.state = {
	      hoveredId: null
	    };
	    return _this;
	  }

	  _createClass(StarRating, [{
	    key: 'onMouseOver',
	    value: function onMouseOver(id) {
	      this.setState({ hoveredId: id });
	    }
	  }, {
	    key: 'onMouseOut',
	    value: function onMouseOut() {
	      this.setState({ hoveredId: null });
	    }
	  }, {
	    key: 'render',
	    value: function render() {
	      var _this2 = this;

	      var styles = {
	        container: {
	          fontSize: 'medium',
	          cursor: 'pointer'
	        },
	        star: {
	          hovered: {
	            color: 'gray'
	          }
	        }
	      };
	      var _props = this.props,
	          max = _props.max,
	          onChange = _props.onChange,
	          value = _props.value,
	          titles = _props.titles;
	      var hoveredId = this.state.hoveredId;

	      var stars = [];

	      var _loop = function _loop(i) {
	        stars.push(_react2.default.createElement('span', { key: i, style: hoveredId !== null ? styles.star.hovered : {}, className: 'icon icon' + (i <= (hoveredId || value) ? 'f' : '') + '-star-1', onMouseOver: function onMouseOver() {
	            return _this2.onMouseOver(i);
	          }, onMouseOut: function onMouseOut() {
	            return _this2.onMouseOut();
	          }, onClick: function onClick() {
	            return onChange(i);
	          }, title: titles[i - 1] }));
	      };

	      for (var i = 1; i <= max; i++) {
	        _loop(i);
	      }
	      return _react2.default.createElement(
	        'div',
	        { style: styles.container },
	        stars
	      );
	    }
	  }]);

	  return StarRating;
	}(_react2.default.Component);

	exports.default = StarRating;

/***/ },
/* 341 */
/***/ function(module, exports) {

	// removed by extract-text-webpack-plugin

/***/ },
/* 342 */,
/* 343 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _drop_component = __webpack_require__(344);

	var _drop_component2 = _interopRequireDefault(_drop_component);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // Notification manager
	// The websocket event must have parameters:
	// - text -> STRING
	// - link -> STRING URL
	// - image (optional) -> STRING URL

	var Notifications = function (_DropComponent) {
	  _inherits(Notifications, _DropComponent);

	  function Notifications() {
	    _classCallCheck(this, Notifications);

	    var _this = _possibleConstructorReturn(this, (Notifications.__proto__ || Object.getPrototypeOf(Notifications)).call(this, "notification", "[data-notification-drop]"));

	    (0, _jquery2.default)(".dropdown").on("click", function (_) {
	      (0, _jquery2.default)(".notifications-container.open").removeClass("open");
	    });
	    (0, _jquery2.default)("[data-notification-drop]").on("click", function (_) {
	      (0, _jquery2.default)(".dropdown.open").removeClass("open");
	    });
	    _this.manageExistingNotifications();
	    return _this;
	  }

	  _createClass(Notifications, [{
	    key: 'manageExistingNotifications',
	    value: function manageExistingNotifications() {
	      // false
	      // @TODO
	      if (window._notifications != undefined) {
	        var _iteratorNormalCompletion = true;
	        var _didIteratorError = false;
	        var _iteratorError = undefined;

	        try {
	          for (var _iterator = window._notifications.unread[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	            var notif = _step.value;

	            this._addItem(notif);
	          }
	        } catch (err) {
	          _didIteratorError = true;
	          _iteratorError = err;
	        } finally {
	          try {
	            if (!_iteratorNormalCompletion && _iterator.return) {
	              _iterator.return();
	            }
	          } finally {
	            if (_didIteratorError) {
	              throw _iteratorError;
	            }
	          }
	        }

	        var _iteratorNormalCompletion2 = true;
	        var _didIteratorError2 = false;
	        var _iteratorError2 = undefined;

	        try {
	          for (var _iterator2 = window._notifications.read[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
	            var _notif = _step2.value;

	            this._addItem(_notif);
	          }
	        } catch (err) {
	          _didIteratorError2 = true;
	          _iteratorError2 = err;
	        } finally {
	          try {
	            if (!_iteratorNormalCompletion2 && _iterator2.return) {
	              _iterator2.return();
	            }
	          } finally {
	            if (_didIteratorError2) {
	              throw _iteratorError2;
	            }
	          }
	        }
	      }
	    }
	  }]);

	  return Notifications;
	}(_drop_component2.default);

	exports.default = Notifications;

/***/ },
/* 344 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _base_component = __webpack_require__(345);

	var _base_component2 = _interopRequireDefault(_base_component);

	var _data_date = __webpack_require__(346);

	var _data_date2 = _interopRequireDefault(_data_date);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var DropComponent = function (_BaseComponent) {
	  _inherits(DropComponent, _BaseComponent);

	  function DropComponent(name, target) {
	    _classCallCheck(this, DropComponent);

	    var _this = _possibleConstructorReturn(this, (DropComponent.__proto__ || Object.getPrototypeOf(DropComponent)).call(this, name, target));

	    if ((0, _jquery2.default)('[data-notification-drop]').length > 0) {
	      _this.dateEvents = _data_date2.default.get();
	      _this.containerSelector = '.notifications-container';
	      _this.url = (0, _jquery2.default)(_this.containerSelector).attr('data-notifications-url');
	      _this.data = [];
	      _this._handleEvents();
	      if ('Notification' in window) {
	        _this._askForNotifications(function (d) {
	          console.info('Notifications');
	        });
	      } // if true
	      _this.render();
	    } else if ((0, _jquery2.default)('[data-long-date]').length > 0) {
	      _this.dateEvents = _data_date2.default.get();
	    }
	    return _this;
	  }

	  _createClass(DropComponent, [{
	    key: 'render',
	    value: function render() {
	      this.data = _.sortBy(this.data, function (e) {
	        return e.updated_at || e.text || e.progress;
	      }).reverse();
	      (0, _jquery2.default)(this.containerSelector).html(this._renderTemplate());
	      if (this.dateEvents) {
	        this.dateEvents._updateAll();
	      }
	      this._position();
	    }
	  }, {
	    key: '_renderTemplate',
	    value: function _renderTemplate() {
	      this.template = '\n      <header class="notifications--header">\n        <span>notifications</span>\n        <a href="' + this.url + '">See all notifications</a>\n      </header>\n      <ul class="menu-drop-list">' + _.map(this.data, this._renderCellTemplate).join('') + '</ul>\n    ';
	      return this.template;
	    }
	  }, {
	    key: '_renderCellTemplate',
	    value: function _renderCellTemplate(data) {
	      return '\n    <li class="menu-drop-item dancer ' + (data.read ? 'read' : 'unread') + '">\n      <a href="' + (data.link || '#') + '">\n    ' + (data.image ? '<div class="menu-drop-image full-bg square-s" style="background-image: url(' + data.image + ')"></div>' : '') + ('\n        <div class="menu-drop-content">\n        ' + (data.title ? '<div class="menu-drop-title">' + data.title + '</div>' : '') + '\n        ' + (data.text ? '<div class="menu-drop-text">' + data.text + '</div>' : '') + '\n        ' + (data.updated_at ? '<span class="menu-drop-created" data-short-date="' + data.updated_at + '">' + data.updated_at + '</span>' : '') + '\n        ' + (data.progress ? '<div class="menu-drop-progress"><div class="progress"><div class="progress-bar" style="width:' + data.progress + '%"></div></div></div>' : '') + '\n        </div>\n      </a>\n    </li>\n    ');
	    }
	  }, {
	    key: '_onNew',
	    value: function _onNew(data) {
	      this._addItem(data);
	      this._createNotification(data); // if true
	    }
	  }, {
	    key: '_onUpdate',
	    value: function _onUpdate(data) {
	      this._updateItem(data);
	    }
	  }, {
	    key: '_onProgress',
	    value: function _onProgress(data) {
	      if (!data.progress) {
	        return;
	      }

	      var item = _.findWhere(window._notifications.read, { concern: data.concern });
	      if (item) {
	        item.progress = data.progress;
	        this._updateItem(data);
	      }
	    }
	  }, {
	    key: '_askForNotifications',
	    value: function _askForNotifications(callback) {
	      if (Notification.permission == 'granted') {
	        return true;
	      } else if (Notification.permission != 'denied') {
	        Notification.requestPermission(callback);
	      }

	      return Notification.permission == 'granted';
	    }
	  }, {
	    key: '_createNotification',
	    value: function _createNotification(data) {
	      // Let's check if the browser supports notifications
	      if (!('Notification' in window)) {
	        console.warn('This browser does not support desktop notification');
	      } else if (Notification.permission == 'granted') {
	        // If it's okay let's create a notification
	        var notification = new Notification(data.title, { icon: data.icon || 'https://cdn.intra.42.fr/mailer/logo_small.png', body: data.text });
	        notification.onClick = function (_) {
	          document.location = data.link;
	        };
	      } else if (Notification.permission != 'denied') {
	        this._askForNotifications(function (_) {
	          var notification = new Notification(content);
	          notification.onClick = function (_) {
	            document.location = data.link;
	          };
	        });
	      }
	      return Notification.permission == 'granted';
	    }
	  }, {
	    key: '_addItem',
	    value: function _addItem(item) {
	      item = this._filterObject(item);

	      if (!item.onCurrentPage()) {
	        this.data.unshift(item);
	        this.render();
	        if (!item.read) {
	          this._incrementCounters();
	        }
	      }
	    }
	  }, {
	    key: '_updateItem',
	    value: function _updateItem(item) {
	      item.read = false;
	      item = this._filterObject(item);
	      if (!item.onCurrentPage()) {
	        var old_item = _.findWhere(this.data, { title: item.title, concern: item.concern });
	        if (old_item) {
	          this.data = _.reject(this.data, { title: item.title, concern: item.concern });
	          this.data.unshift(item);
	          this.render();
	          if (old_item && old_item.read) {
	            this._incrementCounters();
	          }
	        }
	      }
	    }
	  }, {
	    key: '_onOpen',
	    value: function _onOpen() {
	      (0, _jquery2.default)(this.containerSelector).addClass('open');
	      if (this.data.length > 0) {
	        this._timeoutAndMarkAllAsRead();
	      }
	    }
	  }, {
	    key: '_onClose',
	    value: function _onClose() {
	      (0, _jquery2.default)(this.containerSelector).removeClass('open');
	      if (this.readingTimeout) {
	        clearTimeout(this.readingTimeout);
	      }
	    }
	  }, {
	    key: '_markAllAsRead',
	    value: function _markAllAsRead() {
	      _jquery2.default.signedAjax({ url: this.url + '/read_all', method: 'POST' }).done(function (d) {
	        console.log('Sucessfully read all !', d);
	      });
	    }
	  }, {
	    key: '_handleEvents',
	    value: function _handleEvents() {
	      var _this2 = this;

	      (0, _jquery2.default)(document).on('click', this.root, function (e) {
	        (0, _jquery2.default)(_this2.containerSelector).hasClass('open') ? _this2._onClose() : _this2._onOpen();
	        e.stopImmediatePropagation();
	        false;
	      });

	      (0, _jquery2.default)(document).on('click', function (_) {
	        (0, _jquery2.default)(_this2.containerSelector).removeClass('open');
	      });
	    }
	  }, {
	    key: '_timeoutAndMarkAllAsRead',
	    value: function _timeoutAndMarkAllAsRead() {
	      var _this3 = this;

	      this.readingTimeout = setTimeout(function (_) {
	        var _iteratorNormalCompletion = true;
	        var _didIteratorError = false;
	        var _iteratorError = undefined;

	        try {
	          for (var _iterator = _this3.data[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	            var data = _step.value;
	            _this3.data.read = true;
	          }
	        } catch (err) {
	          _didIteratorError = true;
	          _iteratorError = err;
	        } finally {
	          try {
	            if (!_iteratorNormalCompletion && _iterator.return) {
	              _iterator.return();
	            }
	          } finally {
	            if (_didIteratorError) {
	              throw _iteratorError;
	            }
	          }
	        }

	        (0, _jquery2.default)(_this3.containerSelector + ' .unread').addClass('read').removeClass('unread');
	        _this3._resetCounters();
	        _this3.readingTimeout = false;
	        _this3._markAllAsRead();
	      }, 1000);
	    }
	  }, {
	    key: '_position',
	    value: function _position() {
	      var _this4 = this;

	      (0, _jquery2.default)(window).on('resize', function () {
	        var top = (0, _jquery2.default)('.main-navbar').height();
	        var left = (0, _jquery2.default)(_this4.root).offset().left - 265;
	        (0, _jquery2.default)(_this4.containerSelector).css({ top: top, left: left });
	      }).trigger('resize');
	    }
	  }, {
	    key: '_filterObject',
	    value: function _filterObject(object) {
	      var _this5 = this;

	      if (!object.read) {
	        object.read = false;
	      }
	      if (!object.progress) {
	        object.progress = false;
	      }
	      if (object.image && object.image.url != undefined) {
	        object.image = object.image.url;
	      }

	      object.markAsRead = function (_) {
	        if (_this5.dispatcher) {
	          _this5.dispatcher.trigger('notifications.read', { concern: object.concern, title: object.title });
	        }
	      };

	      object.onCurrentPage = function (_) {
	        if (object.concern && (0, _jquery2.default)('[data-concern=\'' + _this5.concern + '\']').length > 0) {
	          _this5.markAsRead();
	          return true;
	        } else {
	          return false;
	        }
	      };

	      return object;
	    }
	  }]);

	  return DropComponent;
	}(_base_component2.default);

	exports.default = DropComponent;

/***/ },
/* 345 */
/***/ function(module, exports) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var BaseComponent = function () {
	  function BaseComponent(name, _root) {
	    _classCallCheck(this, BaseComponent);

	    this.name = name;
	    this.root = _root;
	    this.data = [];
	    this._renderTemplate();
	    this.verbose = true;
	    this.bindEvents = ["new", "update", "progress"];
	    this.counterClass = ".labeled";
	    this.dispatcher = window.dispatcher || false;
	  }

	  _createClass(BaseComponent, [{
	    key: "_channelNameFor",
	    value: function _channelNameFor(event) {
	      return this.name + "." + event;
	    }
	  }, {
	    key: "_renderTemplate",
	    value: function _renderTemplate() {
	      return "";
	    }
	  }, {
	    key: "bind",
	    value: function bind(event) {
	      switch (event) {
	        case "new":
	          return this._onNew;
	        case "update":
	          return this._onUpdate;
	        case "progress":
	          return this._onProgress;
	        default:
	          console.warn("Event " + event + " can't be binded on component...");
	          return false;
	      }
	    }
	  }, {
	    key: "_onNew",
	    value: function _onNew(data) {
	      log("[new] requested !", data);
	    }
	  }, {
	    key: "_onUpdate",
	    value: function _onUpdate(data) {
	      log("[update] requested !", data);
	    }
	  }, {
	    key: "_onProgress",
	    value: function _onProgress(data) {
	      if (this.verbose) {
	        log("[" + this.name + "] Progress " + this.name + " requested !", data);
	      }
	    }
	  }, {
	    key: "bindHandlers",
	    value: function bindHandlers(channel) {
	      var info = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "?";

	      // log("[#{this.name} (#{info})] - Binding on #{this._channelNameFor(event)}", channel) for event in this.bindEvents
	      var _iteratorNormalCompletion = true;
	      var _didIteratorError = false;
	      var _iteratorError = undefined;

	      try {
	        for (var _iterator = this.bindEvents[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	          var event = _step.value;

	          channel.bind(this._channelNameFor(event), this.bind(event));
	        }
	      } catch (err) {
	        _didIteratorError = true;
	        _iteratorError = err;
	      } finally {
	        try {
	          if (!_iteratorNormalCompletion && _iterator.return) {
	            _iterator.return();
	          }
	        } finally {
	          if (_didIteratorError) {
	            throw _iteratorError;
	          }
	        }
	      }
	    }
	  }, {
	    key: "bindPublicHandlers",
	    value: function bindPublicHandlers(dispatcher) {
	      this.dispatcher = dispatcher;
	      this.bindHandlers(dispatcher.subscribe("global"), "global");
	    }
	  }, {
	    key: "_incrementCounters",
	    value: function _incrementCounters() {
	      if (this.root != undefined && $(this.root).find(this.counterClass).length > 0) {
	        var current = parseInt($(this.root).find(this.counterClass).text());
	        $(this.root).find(this.counterClass).html(current + 1);
	        $(this.root).find(this.counterClass).attr("data-counter-count", current + 1);
	      }
	    }
	  }, {
	    key: "_resetCounters",
	    value: function _resetCounters() {
	      if (this.root != undefined && $(this.root).find(this.counterClass).length > 0) {
	        $(this.root).find(this.counterClass).html(0);
	        $(this.root).find(this.counterClass).attr("data-counter-count", 0);
	      }
	    }
	  }]);

	  return BaseComponent;
	}();

	exports.default = BaseComponent;

/***/ },
/* 346 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _momentTwitter = __webpack_require__(347);

	var _momentTwitter2 = _interopRequireDefault(_momentTwitter);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var DataDate = function () {
	    function DataDate() {
	        var _this = this;

	        _classCallCheck(this, DataDate);

	        this._updateAll();
	        this.handler = setInterval(function (_) {
	            _this._updateAll();
	        }, 15000);
	    }

	    _createClass(DataDate, [{
	        key: '_makeTheMoment',
	        value: function _makeTheMoment(date) {
	            date = date.replace("UTC", "+0000");

	            var m = (0, _momentTwitter2.default)(date, "YYYY-MM-DD HH:mm:ss Z");
	            if (m.isValid()) return m;
	            m = (0, _momentTwitter2.default)(date, "YYYY-MM-DD HH:mm Z");
	            if (m.isValid()) return m;

	            m = (0, _momentTwitter2.default)(new Date(date));
	            if (m.isValid()) return m;else console.warn(date + ' date is invalid !', m);
	            return m;
	        }
	    }, {
	        key: '_updateAll',
	        value: function _updateAll() {
	            var self = this === window ? DataDate.get() : this;

	            (0, _jquery2.default)("[data-long-date]").each(function () {
	                // Ne gere plus les timezones
	                // $(@).html(moment($(@).attr("data-long-date"), "YYYY-MM-DD HH:mm Z").fromNow())
	                (0, _jquery2.default)(this).html(self._makeTheMoment((0, _jquery2.default)(this).attr("data-long-date")).fromNow());
	            });

	            (0, _jquery2.default)("[data-short-date]").each(function () {
	                // Ne gere plus les timezones
	                // $(@).html(self._makeTheMoment($(@).attr("data-short-date"), "YYYY-MM-DD HH:mm Z").twitter())
	                (0, _jquery2.default)(this).html(self._makeTheMoment((0, _jquery2.default)(this).attr("data-short-date")).twitter());
	            });

	            (0, _jquery2.default)("[data-short-time]").each(function () {
	                (0, _jquery2.default)(this).html(self._makeTheMoment((0, _jquery2.default)(this).attr("data-short-time")).format("h:mm A"));
	            });

	            (0, _jquery2.default)("[data-cal-date]").each(function () {
	                // Ne gere plus les timezones
	                // $(@).html(self._makeTheMoment($(@).attr("data-cal-date"), "YYYY-MM-DD HH:mm Z").calendar())
	                (0, _jquery2.default)(this).html(self._makeTheMoment((0, _jquery2.default)(this).attr("data-cal-date")).calendar());
	            });
	        }
	    }, {
	        key: 'refresh',
	        value: function refresh() {
	            this._updateAll();
	            if (this.handler) {
	                clearInterval(this.handler);
	            }
	            this.handler = setInterval(this._updateAll, 15000);
	        }
	    }]);

	    return DataDate;
	}();

	;

	DataDate.singleton = undefined;

	DataDate.get = function () {
	    if (DataDate.singleton === undefined) {
	        DataDate.singleton = new DataDate();
	    }
	    DataDate.singleton.refresh();
	    return DataDate.singleton;
	};
	DataDate.refresh = function () {
	    DataDate.get().refresh();
	};

	exports.default = DataDate;

/***/ },
/* 347 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function() {
	  var day, formats, hour, initialize, minute, second, week;

	  second = 1e3;

	  minute = 6e4;

	  hour = 36e5;

	  day = 864e5;

	  week = 6048e5;

	  formats = {
	    seconds: {
	      short: 's',
	      long: ' sec'
	    },
	    minutes: {
	      short: 'm',
	      long: ' min'
	    },
	    hours: {
	      short: 'h',
	      long: ' hr'
	    },
	    days: {
	      short: 'd',
	      long: ' day'
	    }
	  };

	  initialize = function(moment) {
	    var twitterFormat;
	    twitterFormat = function(format) {
	      var diff, num, unit, unitStr;
	      diff = Math.abs(this.diff(moment()));
	      unit = null;
	      num = null;
	      if (diff <= second) {
	        unit = 'seconds';
	        num = 1;
	      } else if (diff < minute) {
	        unit = 'seconds';
	      } else if (diff < hour) {
	        unit = 'minutes';
	      } else if (diff < day) {
	        unit = 'hours';
	      } else if (format === 'short') {
	        if (diff < week) {
	          unit = 'days';
	        } else {
	          return this.format('M/D/YY');
	        }
	      } else {
	        return this.format('MMM D');
	      }
	      if (!(num && unit)) {
	        num = moment.duration(diff)[unit]();
	      }
	      unitStr = unit = formats[unit][format];
	      if (format === 'long' && num > 1) {
	        unitStr += 's';
	      }
	      return num + unitStr;
	    };
	    moment.fn.twitterLong = function() {
	      return twitterFormat.call(this, 'long');
	    };
	    moment.fn.twitter = moment.fn.twitterShort = function() {
	      return twitterFormat.call(this, 'short');
	    };
	    return moment;
	  };

	  if (true) {
	    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(215)], __WEBPACK_AMD_DEFINE_RESULT__ = function(moment) {
	      return this.moment = initialize(moment);
	    }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	  } else if (typeof module !== 'undefined') {
	    module.exports = initialize(require('moment'));
	  } else if (typeof window !== "undefined" && window.moment) {
	    this.moment = initialize(this.moment);
	  }

	}).call(this);


/***/ },
/* 348 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _drop_component = __webpack_require__(344);

	var _drop_component2 = _interopRequireDefault(_drop_component);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var FtNotifications = function (_DropComponent) {
	  _inherits(FtNotifications, _DropComponent);

	  function FtNotifications() {
	    _classCallCheck(this, FtNotifications);

	    //preset les counter
	    var _this = _possibleConstructorReturn(this, (FtNotifications.__proto__ || Object.getPrototypeOf(FtNotifications)).call(this, "notification", "[data-notification-drop]"));

	    var notifCount = window._notifCount;
	    _this.opened = false;
	    (0, _jquery2.default)('[data-counter-count]').attr('data-counter-count', notifCount);
	    (0, _jquery2.default)('[data-counter-count]').html(notifCount);

	    (0, _jquery2.default)(".dropdown").on("click", function (_) {
	      (0, _jquery2.default)(".notifications-container.open").removeClass("open");
	    });
	    (0, _jquery2.default)("[data-notification-drop]").on("click", function (_) {
	      (0, _jquery2.default)(".dropdown.open").removeClass("open");
	      // only fetch once
	      if (_this.opened == false) _this.fetchNotifications();
	      _this.opened = true;
	    });
	    //this.fetchNotifications()
	    window.ft_notification = _this;
	    return _this;
	  }

	  _createClass(FtNotifications, [{
	    key: 'fetchNotifications',
	    value: function fetchNotifications() {
	      var _this2 = this;

	      (0, _jquery2.default)(".notifications-container .menu-drop-list").addClass("loading");
	      _jquery2.default.signedAjax({
	        url: this.url + '/fetch_all',
	        method: "GET"
	      }).done(function (d) {
	        (0, _jquery2.default)(".notifications-container .menu-drop-list").removeClass("loading");
	        if (d) {
	          var notifIds = _.map(_this2.data, 'id');
	          var newNotifs = _.reject([].concat(_toConsumableArray(d.unread), _toConsumableArray(d.read)), function (n) {
	            return notifIds.includes(n.id);
	          });
	          if (newNotifs.length > 0) _this2._resetCounters();
	          var _iteratorNormalCompletion = true;
	          var _didIteratorError = false;
	          var _iteratorError = undefined;

	          try {
	            for (var _iterator = newNotifs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	              var notif = _step.value;

	              if (!notif.read && notifIds.length > 0) _this2._createNotification(notif);
	              _this2._addItem(notif);
	            }
	          } catch (err) {
	            _didIteratorError = true;
	            _iteratorError = err;
	          } finally {
	            try {
	              if (!_iteratorNormalCompletion && _iterator.return) {
	                _iterator.return();
	              }
	            } finally {
	              if (_didIteratorError) {
	                throw _iteratorError;
	              }
	            }
	          }

	          _this2._timeoutAndMarkAllAsRead();
	        }
	      });
	    }
	  }]);

	  return FtNotifications;
	}(_drop_component2.default);

	exports.default = FtNotifications;

/***/ },
/* 349 */
/***/ function(module, exports) {

	(function($, undefined) {

	/**
	 * Unobtrusive scripting adapter for jQuery
	 * https://github.com/rails/jquery-ujs
	 *
	 * Requires jQuery 1.8.0 or later.
	 *
	 * Released under the MIT license
	 *
	 */

	  // Cut down on the number of issues from people inadvertently including jquery_ujs twice
	  // by detecting and raising an error when it happens.
	  'use strict';

	  if ( $.rails !== undefined ) {
	    $.error('jquery-ujs has already been loaded!');
	  }

	  // Shorthand to make it a little easier to call public rails functions from within rails.js
	  var rails;
	  var $document = $(document);

	  $.rails = rails = {
	    // Link elements bound by jquery-ujs
	    linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]',

	    // Button elements bound by jquery-ujs
	    buttonClickSelector: 'button[data-remote]:not([form]):not(form button), button[data-confirm]:not([form]):not(form button)',

	    // Select elements bound by jquery-ujs
	    inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',

	    // Form elements bound by jquery-ujs
	    formSubmitSelector: 'form',

	    // Form input elements bound by jquery-ujs
	    formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])',

	    // Form input elements disabled during form submission
	    disableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled',

	    // Form input elements re-enabled after form submission
	    enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled',

	    // Form required input elements
	    requiredInputSelector: 'input[name][required]:not([disabled]), textarea[name][required]:not([disabled])',

	    // Form file input elements
	    fileInputSelector: 'input[type=file]:not([disabled])',

	    // Link onClick disable selector with possible reenable after remote submission
	    linkDisableSelector: 'a[data-disable-with], a[data-disable]',

	    // Button onClick disable selector with possible reenable after remote submission
	    buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]',

	    // Up-to-date Cross-Site Request Forgery token
	    csrfToken: function() {
	     return $('meta[name=csrf-token]').attr('content');
	    },

	    // URL param that must contain the CSRF token
	    csrfParam: function() {
	     return $('meta[name=csrf-param]').attr('content');
	    },

	    // Make sure that every Ajax request sends the CSRF token
	    CSRFProtection: function(xhr) {
	      var token = rails.csrfToken();
	      if (token) xhr.setRequestHeader('X-CSRF-Token', token);
	    },

	    // Make sure that all forms have actual up-to-date tokens (cached forms contain old ones)
	    refreshCSRFTokens: function(){
	      $('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken());
	    },

	    // Triggers an event on an element and returns false if the event result is false
	    fire: function(obj, name, data) {
	      var event = $.Event(name);
	      obj.trigger(event, data);
	      return event.result !== false;
	    },

	    // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
	    confirm: function(message) {
	      return confirm(message);
	    },

	    // Default ajax function, may be overridden with custom function in $.rails.ajax
	    ajax: function(options) {
	      return $.ajax(options);
	    },

	    // Default way to get an element's href. May be overridden at $.rails.href.
	    href: function(element) {
	      return element[0].href;
	    },

	    // Checks "data-remote" if true to handle the request through a XHR request.
	    isRemote: function(element) {
	      return element.data('remote') !== undefined && element.data('remote') !== false;
	    },

	    // Submits "remote" forms and links with ajax
	    handleRemote: function(element) {
	      var method, url, data, withCredentials, dataType, options;

	      if (rails.fire(element, 'ajax:before')) {
	        withCredentials = element.data('with-credentials') || null;
	        dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);

	        if (element.is('form')) {
	          method = element.data('ujs:submit-button-formmethod') || element.attr('method');
	          url = element.data('ujs:submit-button-formaction') || element.attr('action');
	          data = $(element[0]).serializeArray();
	          // memoized value from clicked submit button
	          var button = element.data('ujs:submit-button');
	          if (button) {
	            data.push(button);
	            element.data('ujs:submit-button', null);
	          }
	          element.data('ujs:submit-button-formmethod', null);
	          element.data('ujs:submit-button-formaction', null);
	        } else if (element.is(rails.inputChangeSelector)) {
	          method = element.data('method');
	          url = element.data('url');
	          data = element.serialize();
	          if (element.data('params')) data = data + '&' + element.data('params');
	        } else if (element.is(rails.buttonClickSelector)) {
	          method = element.data('method') || 'get';
	          url = element.data('url');
	          data = element.serialize();
	          if (element.data('params')) data = data + '&' + element.data('params');
	        } else {
	          method = element.data('method');
	          url = rails.href(element);
	          data = element.data('params') || null;
	        }

	        options = {
	          type: method || 'GET', data: data, dataType: dataType,
	          // stopping the "ajax:beforeSend" event will cancel the ajax request
	          beforeSend: function(xhr, settings) {
	            if (settings.dataType === undefined) {
	              xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
	            }
	            if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) {
	              element.trigger('ajax:send', xhr);
	            } else {
	              return false;
	            }
	          },
	          success: function(data, status, xhr) {
	            element.trigger('ajax:success', [data, status, xhr]);
	          },
	          complete: function(xhr, status) {
	            element.trigger('ajax:complete', [xhr, status]);
	          },
	          error: function(xhr, status, error) {
	            element.trigger('ajax:error', [xhr, status, error]);
	          },
	          crossDomain: rails.isCrossDomain(url)
	        };

	        // There is no withCredentials for IE6-8 when
	        // "Enable native XMLHTTP support" is disabled
	        if (withCredentials) {
	          options.xhrFields = {
	            withCredentials: withCredentials
	          };
	        }

	        // Only pass url to `ajax` options if not blank
	        if (url) { options.url = url; }

	        return rails.ajax(options);
	      } else {
	        return false;
	      }
	    },

	    // Determines if the request is a cross domain request.
	    isCrossDomain: function(url) {
	      var originAnchor = document.createElement('a');
	      originAnchor.href = location.href;
	      var urlAnchor = document.createElement('a');

	      try {
	        urlAnchor.href = url;
	        // This is a workaround to a IE bug.
	        urlAnchor.href = urlAnchor.href;

	        // If URL protocol is false or is a string containing a single colon
	        // *and* host are false, assume it is not a cross-domain request
	        // (should only be the case for IE7 and IE compatibility mode).
	        // Otherwise, evaluate protocol and host of the URL against the origin
	        // protocol and host.
	        return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) ||
	          (originAnchor.protocol + '//' + originAnchor.host ===
	            urlAnchor.protocol + '//' + urlAnchor.host));
	      } catch (e) {
	        // If there is an error parsing the URL, assume it is crossDomain.
	        return true;
	      }
	    },

	    // Handles "data-method" on links such as:
	    // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
	    handleMethod: function(link) {
	      var href = rails.href(link),
	        method = link.data('method'),
	        target = link.attr('target'),
	        csrfToken = rails.csrfToken(),
	        csrfParam = rails.csrfParam(),
	        form = $('<form method="post" action="' + href + '"></form>'),
	        metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';

	      if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) {
	        metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
	      }

	      if (target) { form.attr('target', target); }

	      form.hide().append(metadataInput).appendTo('body');
	      form.submit();
	    },

	    // Helper function that returns form elements that match the specified CSS selector
	    // If form is actually a "form" element this will return associated elements outside the from that have
	    // the html form attribute set
	    formElements: function(form, selector) {
	      return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector);
	    },

	    /* Disables form elements:
	      - Caches element value in 'ujs:enable-with' data store
	      - Replaces element text with value of 'data-disable-with' attribute
	      - Sets disabled property to true
	    */
	    disableFormElements: function(form) {
	      rails.formElements(form, rails.disableSelector).each(function() {
	        rails.disableFormElement($(this));
	      });
	    },

	    disableFormElement: function(element) {
	      var method, replacement;

	      method = element.is('button') ? 'html' : 'val';
	      replacement = element.data('disable-with');

	      if (replacement !== undefined) {
	        element.data('ujs:enable-with', element[method]());
	        element[method](replacement);
	      }

	      element.prop('disabled', true);
	      element.data('ujs:disabled', true);
	    },

	    /* Re-enables disabled form elements:
	      - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
	      - Sets disabled property to false
	    */
	    enableFormElements: function(form) {
	      rails.formElements(form, rails.enableSelector).each(function() {
	        rails.enableFormElement($(this));
	      });
	    },

	    enableFormElement: function(element) {
	      var method = element.is('button') ? 'html' : 'val';
	      if (element.data('ujs:enable-with') !== undefined) {
	        element[method](element.data('ujs:enable-with'));
	        element.removeData('ujs:enable-with'); // clean up cache
	      }
	      element.prop('disabled', false);
	      element.removeData('ujs:disabled');
	    },

	   /* For 'data-confirm' attribute:
	      - Fires `confirm` event
	      - Shows the confirmation dialog
	      - Fires the `confirm:complete` event

	      Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
	      Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
	      Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
	      return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
	   */
	    allowAction: function(element) {
	      var message = element.data('confirm'),
	          answer = false, callback;
	      if (!message) { return true; }

	      if (rails.fire(element, 'confirm')) {
	        try {
	          answer = rails.confirm(message);
	        } catch (e) {
	          (console.error || console.log).call(console, e.stack || e);
	        }
	        callback = rails.fire(element, 'confirm:complete', [answer]);
	      }
	      return answer && callback;
	    },

	    // Helper function which checks for blank inputs in a form that match the specified CSS selector
	    blankInputs: function(form, specifiedSelector, nonBlank) {
	      var foundInputs = $(),
	        input,
	        valueToCheck,
	        radiosForNameWithNoneSelected,
	        radioName,
	        selector = specifiedSelector || 'input,textarea',
	        requiredInputs = form.find(selector),
	        checkedRadioButtonNames = {};

	      requiredInputs.each(function() {
	        input = $(this);
	        if (input.is('input[type=radio]')) {

	          // Don't count unchecked required radio as blank if other radio with same name is checked,
	          // regardless of whether same-name radio input has required attribute or not. The spec
	          // states https://www.w3.org/TR/html5/forms.html#the-required-attribute
	          radioName = input.attr('name');

	          // Skip if we've already seen the radio with this name.
	          if (!checkedRadioButtonNames[radioName]) {

	            // If none checked
	            if (form.find('input[type=radio]:checked[name="' + radioName + '"]').length === 0) {
	              radiosForNameWithNoneSelected = form.find(
	                'input[type=radio][name="' + radioName + '"]');
	              foundInputs = foundInputs.add(radiosForNameWithNoneSelected);
	            }

	            // We only need to check each name once.
	            checkedRadioButtonNames[radioName] = radioName;
	          }
	        } else {
	          valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val();
	          if (valueToCheck === nonBlank) {
	            foundInputs = foundInputs.add(input);
	          }
	        }
	      });
	      return foundInputs.length ? foundInputs : false;
	    },

	    // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
	    nonBlankInputs: function(form, specifiedSelector) {
	      return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
	    },

	    // Helper function, needed to provide consistent behavior in IE
	    stopEverything: function(e) {
	      $(e.target).trigger('ujs:everythingStopped');
	      e.stopImmediatePropagation();
	      return false;
	    },

	    //  Replace element's html with the 'data-disable-with' after storing original html
	    //  and prevent clicking on it
	    disableElement: function(element) {
	      var replacement = element.data('disable-with');

	      if (replacement !== undefined) {
	        element.data('ujs:enable-with', element.html()); // store enabled state
	        element.html(replacement);
	      }

	      element.bind('click.railsDisable', function(e) { // prevent further clicking
	        return rails.stopEverything(e);
	      });
	      element.data('ujs:disabled', true);
	    },

	    // Restore element to its original state which was disabled by 'disableElement' above
	    enableElement: function(element) {
	      if (element.data('ujs:enable-with') !== undefined) {
	        element.html(element.data('ujs:enable-with')); // set to old enabled state
	        element.removeData('ujs:enable-with'); // clean up cache
	      }
	      element.unbind('click.railsDisable'); // enable element
	      element.removeData('ujs:disabled');
	    }
	  };

	  if (rails.fire($document, 'rails:attachBindings')) {

	    $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});

	    // This event works the same as the load event, except that it fires every
	    // time the page is loaded.
	    //
	    // See https://github.com/rails/jquery-ujs/issues/357
	    // See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
	    $(window).on('pageshow.rails', function () {
	      $($.rails.enableSelector).each(function () {
	        var element = $(this);

	        if (element.data('ujs:disabled')) {
	          $.rails.enableFormElement(element);
	        }
	      });

	      $($.rails.linkDisableSelector).each(function () {
	        var element = $(this);

	        if (element.data('ujs:disabled')) {
	          $.rails.enableElement(element);
	        }
	      });
	    });

	    $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() {
	        rails.enableElement($(this));
	    });

	    $document.delegate(rails.buttonDisableSelector, 'ajax:complete', function() {
	        rails.enableFormElement($(this));
	    });

	    $document.delegate(rails.linkClickSelector, 'click.rails', function(e) {
	      var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;
	      if (!rails.allowAction(link)) return rails.stopEverything(e);

	      if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link);

	      if (rails.isRemote(link)) {
	        if (metaClick && (!method || method === 'GET') && !data) { return true; }

	        var handleRemote = rails.handleRemote(link);
	        // Response from rails.handleRemote() will either be false or a deferred object promise.
	        if (handleRemote === false) {
	          rails.enableElement(link);
	        } else {
	          handleRemote.fail( function() { rails.enableElement(link); } );
	        }
	        return false;

	      } else if (method) {
	        rails.handleMethod(link);
	        return false;
	      }
	    });

	    $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) {
	      var button = $(this);

	      if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e);

	      if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button);

	      var handleRemote = rails.handleRemote(button);
	      // Response from rails.handleRemote() will either be false or a deferred object promise.
	      if (handleRemote === false) {
	        rails.enableFormElement(button);
	      } else {
	        handleRemote.fail( function() { rails.enableFormElement(button); } );
	      }
	      return false;
	    });

	    $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) {
	      var link = $(this);
	      if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e);

	      rails.handleRemote(link);
	      return false;
	    });

	    $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
	      var form = $(this),
	        remote = rails.isRemote(form),
	        blankRequiredInputs,
	        nonBlankFileInputs;

	      if (!rails.allowAction(form)) return rails.stopEverything(e);

	      // Skip other logic when required values are missing or file upload is present
	      if (form.attr('novalidate') === undefined) {
	        if (form.data('ujs:formnovalidate-button') === undefined) {
	          blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector, false);
	          if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
	            return rails.stopEverything(e);
	          }
	        } else {
	          // Clear the formnovalidate in case the next button click is not on a formnovalidate button
	          // Not strictly necessary to do here, since it is also reset on each button click, but just to be certain
	          form.data('ujs:formnovalidate-button', undefined);
	        }
	      }

	      if (remote) {
	        nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
	        if (nonBlankFileInputs) {
	          // Slight timeout so that the submit button gets properly serialized
	          // (make it easy for event handler to serialize form without disabled values)
	          setTimeout(function(){ rails.disableFormElements(form); }, 13);
	          var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);

	          // Re-enable form elements if event bindings return false (canceling normal form submission)
	          if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }

	          return aborted;
	        }

	        rails.handleRemote(form);
	        return false;

	      } else {
	        // Slight timeout so that the submit button gets properly serialized
	        setTimeout(function(){ rails.disableFormElements(form); }, 13);
	      }
	    });

	    $document.delegate(rails.formInputClickSelector, 'click.rails', function(event) {
	      var button = $(this);

	      if (!rails.allowAction(button)) return rails.stopEverything(event);

	      // Register the pressed submit button
	      var name = button.attr('name'),
	        data = name ? {name:name, value:button.val()} : null;

	      var form = button.closest('form');
	      if (form.length === 0) {
	        form = $('#' + button.attr('form'));
	      }
	      form.data('ujs:submit-button', data);

	      // Save attributes from button
	      form.data('ujs:formnovalidate-button', button.attr('formnovalidate'));
	      form.data('ujs:submit-button-formaction', button.attr('formaction'));
	      form.data('ujs:submit-button-formmethod', button.attr('formmethod'));
	    });

	    $document.delegate(rails.formSubmitSelector, 'ajax:send.rails', function(event) {
	      if (this === event.target) rails.disableFormElements($(this));
	    });

	    $document.delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) {
	      if (this === event.target) rails.enableFormElements($(this));
	    });

	    $(function(){
	      rails.refreshCSRFTokens();
	    });
	  }

	})( jQuery );


/***/ },
/* 350 */
/***/ function(module, exports, __webpack_require__) {

	/*global require,module*/
	"use strict";
	var CodeMirror = __webpack_require__(351);
	__webpack_require__(352);
	__webpack_require__(353);
	__webpack_require__(354);
	__webpack_require__(355);
	__webpack_require__(358);
	__webpack_require__(359);
	__webpack_require__(360);
	__webpack_require__(361);
	__webpack_require__(356);
	var CodeMirrorSpellChecker = __webpack_require__(362);
	var marked = __webpack_require__(369);


	// Some variables
	var isMac = /Mac/.test(navigator.platform);

	// Mapping of actions that can be bound to keyboard shortcuts or toolbar buttons
	var bindings = {
		"toggleBold": toggleBold,
		"toggleItalic": toggleItalic,
		"drawLink": drawLink,
		"toggleHeadingSmaller": toggleHeadingSmaller,
		"toggleHeadingBigger": toggleHeadingBigger,
		"drawImage": drawImage,
		"toggleBlockquote": toggleBlockquote,
		"toggleOrderedList": toggleOrderedList,
		"toggleUnorderedList": toggleUnorderedList,
		"toggleCodeBlock": toggleCodeBlock,
		"togglePreview": togglePreview,
		"toggleStrikethrough": toggleStrikethrough,
		"toggleHeading1": toggleHeading1,
		"toggleHeading2": toggleHeading2,
		"toggleHeading3": toggleHeading3,
		"cleanBlock": cleanBlock,
		"drawTable": drawTable,
		"drawHorizontalRule": drawHorizontalRule,
		"undo": undo,
		"redo": redo,
		"toggleSideBySide": toggleSideBySide,
		"toggleFullScreen": toggleFullScreen
	};

	var shortcuts = {
		"toggleBold": "Cmd-B",
		"toggleItalic": "Cmd-I",
		"drawLink": "Cmd-K",
		"toggleHeadingSmaller": "Cmd-H",
		"toggleHeadingBigger": "Shift-Cmd-H",
		"cleanBlock": "Cmd-E",
		"drawImage": "Cmd-Alt-I",
		"toggleBlockquote": "Cmd-'",
		"toggleOrderedList": "Cmd-Alt-L",
		"toggleUnorderedList": "Cmd-L",
		"toggleCodeBlock": "Cmd-Alt-C",
		"togglePreview": "Cmd-P",
		"toggleSideBySide": "F9",
		"toggleFullScreen": "F11"
	};

	var getBindingName = function(f) {
		for(var key in bindings) {
			if(bindings[key] === f) {
				return key;
			}
		}
		return null;
	};

	var isMobile = function() {
		var check = false;
		(function(a) {
			if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
		})(navigator.userAgent || navigator.vendor || window.opera);
		return check;
	};


	/**
	 * Fix shortcut. Mac use Command, others use Ctrl.
	 */
	function fixShortcut(name) {
		if(isMac) {
			name = name.replace("Ctrl", "Cmd");
		} else {
			name = name.replace("Cmd", "Ctrl");
		}
		return name;
	}


	/**
	 * Create icon element for toolbar.
	 */
	function createIcon(options, enableTooltips, shortcuts) {
		options = options || {};
		var el = document.createElement("a");
		enableTooltips = (enableTooltips == undefined) ? true : enableTooltips;

		if(options.title && enableTooltips) {
			el.title = createTootlip(options.title, options.action, shortcuts);

			if(isMac) {
				el.title = el.title.replace("Ctrl", "⌘");
				el.title = el.title.replace("Alt", "⌥");
			}
		}

		el.tabIndex = -1;
		el.className = options.className;
		return el;
	}

	function createSep() {
		var el = document.createElement("i");
		el.className = "separator";
		el.innerHTML = "|";
		return el;
	}

	function createTootlip(title, action, shortcuts) {
		var actionName;
		var tooltip = title;

		if(action) {
			actionName = getBindingName(action);
			if(shortcuts[actionName]) {
				tooltip += " (" + fixShortcut(shortcuts[actionName]) + ")";
			}
		}

		return tooltip;
	}

	/**
	 * The state of CodeMirror at the given position.
	 */
	function getState(cm, pos) {
		pos = pos || cm.getCursor("start");
		var stat = cm.getTokenAt(pos);
		if(!stat.type) return {};

		var types = stat.type.split(" ");

		var ret = {},
			data, text;
		for(var i = 0; i < types.length; i++) {
			data = types[i];
			if(data === "strong") {
				ret.bold = true;
			} else if(data === "variable-2") {
				text = cm.getLine(pos.line);
				if(/^\s*\d+\.\s/.test(text)) {
					ret["ordered-list"] = true;
				} else {
					ret["unordered-list"] = true;
				}
			} else if(data === "atom") {
				ret.quote = true;
			} else if(data === "em") {
				ret.italic = true;
			} else if(data === "quote") {
				ret.quote = true;
			} else if(data === "strikethrough") {
				ret.strikethrough = true;
			} else if(data === "comment") {
				ret.code = true;
			} else if(data === "link") {
				ret.link = true;
			} else if(data === "tag") {
				ret.image = true;
			} else if(data.match(/^header(\-[1-6])?$/)) {
				ret[data.replace("header", "heading")] = true;
			}
		}
		return ret;
	}


	// Saved overflow setting
	var saved_overflow = "";

	/**
	 * Toggle full screen of the editor.
	 */
	function toggleFullScreen(editor) {
		// Set fullscreen
		var cm = editor.codemirror;
		cm.setOption("fullScreen", !cm.getOption("fullScreen"));


		// Prevent scrolling on body during fullscreen active
		if(cm.getOption("fullScreen")) {
			saved_overflow = document.body.style.overflow;
			document.body.style.overflow = "hidden";
		} else {
			document.body.style.overflow = saved_overflow;
		}


		// Update toolbar class
		var wrap = cm.getWrapperElement();

		if(!/fullscreen/.test(wrap.previousSibling.className)) {
			wrap.previousSibling.className += " fullscreen";
		} else {
			wrap.previousSibling.className = wrap.previousSibling.className.replace(/\s*fullscreen\b/, "");
		}


		// Update toolbar button
		var toolbarButton = editor.toolbarElements.fullscreen;

		if(!/active/.test(toolbarButton.className)) {
			toolbarButton.className += " active";
		} else {
			toolbarButton.className = toolbarButton.className.replace(/\s*active\s*/g, "");
		}


		// Hide side by side if needed
		var sidebyside = cm.getWrapperElement().nextSibling;
		if(/editor-preview-active-side/.test(sidebyside.className))
			toggleSideBySide(editor);
	}


	/**
	 * Action for toggling bold.
	 */
	function toggleBold(editor) {
		_toggleBlock(editor, "bold", editor.options.blockStyles.bold);
	}


	/**
	 * Action for toggling italic.
	 */
	function toggleItalic(editor) {
		_toggleBlock(editor, "italic", editor.options.blockStyles.italic);
	}


	/**
	 * Action for toggling strikethrough.
	 */
	function toggleStrikethrough(editor) {
		_toggleBlock(editor, "strikethrough", "~~");
	}

	/**
	 * Action for toggling code block.
	 */
	function toggleCodeBlock(editor) {
		var fenceCharsToInsert = editor.options.blockStyles.code;

		function fencing_line(line) {
			/* return true, if this is a ``` or ~~~ line */
			if(typeof line !== "object") {
				throw "fencing_line() takes a 'line' object (not a line number, or line text).  Got: " + typeof line + ": " + line;
			}
			return line.styles && line.styles[2] && line.styles[2].indexOf("formatting-code-block") !== -1;
		}

		function token_state(token) {
			// base goes an extra level deep when mode backdrops are used, e.g. spellchecker on
			return token.state.base.base || token.state.base;
		}

		function code_type(cm, line_num, line, firstTok, lastTok) {
			/*
			 * Return "single", "indented", "fenced" or false
			 *
			 * cm and line_num are required.  Others are optional for efficiency
			 *   To check in the middle of a line, pass in firstTok yourself.
			 */
			line = line || cm.getLineHandle(line_num);
			firstTok = firstTok || cm.getTokenAt({
				line: line_num,
				ch: 1
			});
			lastTok = lastTok || (!!line.text && cm.getTokenAt({
				line: line_num,
				ch: line.text.length - 1
			}));
			var types = firstTok.type ? firstTok.type.split(" ") : [];
			if(lastTok && token_state(lastTok).indentedCode) {
				// have to check last char, since first chars of first line aren"t marked as indented
				return "indented";
			} else if(types.indexOf("comment") === -1) {
				// has to be after "indented" check, since first chars of first indented line aren"t marked as such
				return false;
			} else if(token_state(firstTok).fencedChars || token_state(lastTok).fencedChars || fencing_line(line)) {
				return "fenced";
			} else {
				return "single";
			}
		}

		function insertFencingAtSelection(cm, cur_start, cur_end, fenceCharsToInsert) {
			var start_line_sel = cur_start.line + 1,
				end_line_sel = cur_end.line + 1,
				sel_multi = cur_start.line !== cur_end.line,
				repl_start = fenceCharsToInsert + "\n",
				repl_end = "\n" + fenceCharsToInsert;
			if(sel_multi) {
				end_line_sel++;
			}
			// handle last char including \n or not
			if(sel_multi && cur_end.ch === 0) {
				repl_end = fenceCharsToInsert + "\n";
				end_line_sel--;
			}
			_replaceSelection(cm, false, [repl_start, repl_end]);
			cm.setSelection({
				line: start_line_sel,
				ch: 0
			}, {
				line: end_line_sel,
				ch: 0
			});
		}

		var cm = editor.codemirror,
			cur_start = cm.getCursor("start"),
			cur_end = cm.getCursor("end"),
			tok = cm.getTokenAt({
				line: cur_start.line,
				ch: cur_start.ch || 1
			}), // avoid ch 0 which is a cursor pos but not token
			line = cm.getLineHandle(cur_start.line),
			is_code = code_type(cm, cur_start.line, line, tok);
		var block_start, block_end, lineCount;

		if(is_code === "single") {
			// similar to some SimpleMDE _toggleBlock logic
			var start = line.text.slice(0, cur_start.ch).replace("`", ""),
				end = line.text.slice(cur_start.ch).replace("`", "");
			cm.replaceRange(start + end, {
				line: cur_start.line,
				ch: 0
			}, {
				line: cur_start.line,
				ch: 99999999999999
			});
			cur_start.ch--;
			if(cur_start !== cur_end) {
				cur_end.ch--;
			}
			cm.setSelection(cur_start, cur_end);
			cm.focus();
		} else if(is_code === "fenced") {
			if(cur_start.line !== cur_end.line || cur_start.ch !== cur_end.ch) {
				// use selection

				// find the fenced line so we know what type it is (tilde, backticks, number of them)
				for(block_start = cur_start.line; block_start >= 0; block_start--) {
					line = cm.getLineHandle(block_start);
					if(fencing_line(line)) {
						break;
					}
				}
				var fencedTok = cm.getTokenAt({
					line: block_start,
					ch: 1
				});
				var fence_chars = token_state(fencedTok).fencedChars;
				var start_text, start_line;
				var end_text, end_line;
				// check for selection going up against fenced lines, in which case we don't want to add more fencing
				if(fencing_line(cm.getLineHandle(cur_start.line))) {
					start_text = "";
					start_line = cur_start.line;
				} else if(fencing_line(cm.getLineHandle(cur_start.line - 1))) {
					start_text = "";
					start_line = cur_start.line - 1;
				} else {
					start_text = fence_chars + "\n";
					start_line = cur_start.line;
				}
				if(fencing_line(cm.getLineHandle(cur_end.line))) {
					end_text = "";
					end_line = cur_end.line;
					if(cur_end.ch === 0) {
						end_line += 1;
					}
				} else if(cur_end.ch !== 0 && fencing_line(cm.getLineHandle(cur_end.line + 1))) {
					end_text = "";
					end_line = cur_end.line + 1;
				} else {
					end_text = fence_chars + "\n";
					end_line = cur_end.line + 1;
				}
				if(cur_end.ch === 0) {
					// full last line selected, putting cursor at beginning of next
					end_line -= 1;
				}
				cm.operation(function() {
					// end line first, so that line numbers don't change
					cm.replaceRange(end_text, {
						line: end_line,
						ch: 0
					}, {
						line: end_line + (end_text ? 0 : 1),
						ch: 0
					});
					cm.replaceRange(start_text, {
						line: start_line,
						ch: 0
					}, {
						line: start_line + (start_text ? 0 : 1),
						ch: 0
					});
				});
				cm.setSelection({
					line: start_line + (start_text ? 1 : 0),
					ch: 0
				}, {
					line: end_line + (start_text ? 1 : -1),
					ch: 0
				});
				cm.focus();
			} else {
				// no selection, search for ends of this fenced block
				var search_from = cur_start.line;
				if(fencing_line(cm.getLineHandle(cur_start.line))) { // gets a little tricky if cursor is right on a fenced line
					if(code_type(cm, cur_start.line + 1) === "fenced") {
						block_start = cur_start.line;
						search_from = cur_start.line + 1; // for searching for "end"
					} else {
						block_end = cur_start.line;
						search_from = cur_start.line - 1; // for searching for "start"
					}
				}
				if(block_start === undefined) {
					for(block_start = search_from; block_start >= 0; block_start--) {
						line = cm.getLineHandle(block_start);
						if(fencing_line(line)) {
							break;
						}
					}
				}
				if(block_end === undefined) {
					lineCount = cm.lineCount();
					for(block_end = search_from; block_end < lineCount; block_end++) {
						line = cm.getLineHandle(block_end);
						if(fencing_line(line)) {
							break;
						}
					}
				}
				cm.operation(function() {
					cm.replaceRange("", {
						line: block_start,
						ch: 0
					}, {
						line: block_start + 1,
						ch: 0
					});
					cm.replaceRange("", {
						line: block_end - 1,
						ch: 0
					}, {
						line: block_end,
						ch: 0
					});
				});
				cm.focus();
			}
		} else if(is_code === "indented") {
			if(cur_start.line !== cur_end.line || cur_start.ch !== cur_end.ch) {
				// use selection
				block_start = cur_start.line;
				block_end = cur_end.line;
				if(cur_end.ch === 0) {
					block_end--;
				}
			} else {
				// no selection, search for ends of this indented block
				for(block_start = cur_start.line; block_start >= 0; block_start--) {
					line = cm.getLineHandle(block_start);
					if(line.text.match(/^\s*$/)) {
						// empty or all whitespace - keep going
						continue;
					} else {
						if(code_type(cm, block_start, line) !== "indented") {
							block_start += 1;
							break;
						}
					}
				}
				lineCount = cm.lineCount();
				for(block_end = cur_start.line; block_end < lineCount; block_end++) {
					line = cm.getLineHandle(block_end);
					if(line.text.match(/^\s*$/)) {
						// empty or all whitespace - keep going
						continue;
					} else {
						if(code_type(cm, block_end, line) !== "indented") {
							block_end -= 1;
							break;
						}
					}
				}
			}
			// if we are going to un-indent based on a selected set of lines, and the next line is indented too, we need to
			// insert a blank line so that the next line(s) continue to be indented code
			var next_line = cm.getLineHandle(block_end + 1),
				next_line_last_tok = next_line && cm.getTokenAt({
					line: block_end + 1,
					ch: next_line.text.length - 1
				}),
				next_line_indented = next_line_last_tok && token_state(next_line_last_tok).indentedCode;
			if(next_line_indented) {
				cm.replaceRange("\n", {
					line: block_end + 1,
					ch: 0
				});
			}

			for(var i = block_start; i <= block_end; i++) {
				cm.indentLine(i, "subtract"); // TODO: this doesn't get tracked in the history, so can't be undone :(
			}
			cm.focus();
		} else {
			// insert code formatting
			var no_sel_and_starting_of_line = (cur_start.line === cur_end.line && cur_start.ch === cur_end.ch && cur_start.ch === 0);
			var sel_multi = cur_start.line !== cur_end.line;
			if(no_sel_and_starting_of_line || sel_multi) {
				insertFencingAtSelection(cm, cur_start, cur_end, fenceCharsToInsert);
			} else {
				_replaceSelection(cm, false, ["`", "`"]);
			}
		}
	}

	/**
	 * Action for toggling blockquote.
	 */
	function toggleBlockquote(editor) {
		var cm = editor.codemirror;
		_toggleLine(cm, "quote");
	}

	/**
	 * Action for toggling heading size: normal -> h1 -> h2 -> h3 -> h4 -> h5 -> h6 -> normal
	 */
	function toggleHeadingSmaller(editor) {
		var cm = editor.codemirror;
		_toggleHeading(cm, "smaller");
	}

	/**
	 * Action for toggling heading size: normal -> h6 -> h5 -> h4 -> h3 -> h2 -> h1 -> normal
	 */
	function toggleHeadingBigger(editor) {
		var cm = editor.codemirror;
		_toggleHeading(cm, "bigger");
	}

	/**
	 * Action for toggling heading size 1
	 */
	function toggleHeading1(editor) {
		var cm = editor.codemirror;
		_toggleHeading(cm, undefined, 1);
	}

	/**
	 * Action for toggling heading size 2
	 */
	function toggleHeading2(editor) {
		var cm = editor.codemirror;
		_toggleHeading(cm, undefined, 2);
	}

	/**
	 * Action for toggling heading size 3
	 */
	function toggleHeading3(editor) {
		var cm = editor.codemirror;
		_toggleHeading(cm, undefined, 3);
	}


	/**
	 * Action for toggling ul.
	 */
	function toggleUnorderedList(editor) {
		var cm = editor.codemirror;
		_toggleLine(cm, "unordered-list");
	}


	/**
	 * Action for toggling ol.
	 */
	function toggleOrderedList(editor) {
		var cm = editor.codemirror;
		_toggleLine(cm, "ordered-list");
	}

	/**
	 * Action for clean block (remove headline, list, blockquote code, markers)
	 */
	function cleanBlock(editor) {
		var cm = editor.codemirror;
		_cleanBlock(cm);
	}

	/**
	 * Action for drawing a link.
	 */
	function drawLink(editor) {
		var cm = editor.codemirror;
		var stat = getState(cm);
		var options = editor.options;
		var url = "http://";
		if(options.promptURLs) {
			url = prompt(options.promptTexts.link);
			if(!url) {
				return false;
			}
		}
		_replaceSelection(cm, stat.link, options.insertTexts.link, url);
	}

	/**
	 * Action for drawing an img.
	 */
	function drawImage(editor) {
		var cm = editor.codemirror;
		var stat = getState(cm);
		var options = editor.options;
		var url = "http://";
		if(options.promptURLs) {
			url = prompt(options.promptTexts.image);
			if(!url) {
				return false;
			}
		}
		_replaceSelection(cm, stat.image, options.insertTexts.image, url);
	}

	/**
	 * Action for drawing a table.
	 */
	function drawTable(editor) {
		var cm = editor.codemirror;
		var stat = getState(cm);
		var options = editor.options;
		_replaceSelection(cm, stat.table, options.insertTexts.table);
	}

	/**
	 * Action for drawing a horizontal rule.
	 */
	function drawHorizontalRule(editor) {
		var cm = editor.codemirror;
		var stat = getState(cm);
		var options = editor.options;
		_replaceSelection(cm, stat.image, options.insertTexts.horizontalRule);
	}


	/**
	 * Undo action.
	 */
	function undo(editor) {
		var cm = editor.codemirror;
		cm.undo();
		cm.focus();
	}


	/**
	 * Redo action.
	 */
	function redo(editor) {
		var cm = editor.codemirror;
		cm.redo();
		cm.focus();
	}


	/**
	 * Toggle side by side preview
	 */
	function toggleSideBySide(editor) {
		var cm = editor.codemirror;
		var wrapper = cm.getWrapperElement();
		var preview = wrapper.nextSibling;
		var toolbarButton = editor.toolbarElements["side-by-side"];
		var useSideBySideListener = false;
		if(/editor-preview-active-side/.test(preview.className)) {
			preview.className = preview.className.replace(
				/\s*editor-preview-active-side\s*/g, ""
			);
			toolbarButton.className = toolbarButton.className.replace(/\s*active\s*/g, "");
			wrapper.className = wrapper.className.replace(/\s*CodeMirror-sided\s*/g, " ");
		} else {
			// When the preview button is clicked for the first time,
			// give some time for the transition from editor.css to fire and the view to slide from right to left,
			// instead of just appearing.
			setTimeout(function() {
				if(!cm.getOption("fullScreen"))
					toggleFullScreen(editor);
				preview.className += " editor-preview-active-side";
			}, 1);
			toolbarButton.className += " active";
			wrapper.className += " CodeMirror-sided";
			useSideBySideListener = true;
		}

		// Hide normal preview if active
		var previewNormal = wrapper.lastChild;
		if(/editor-preview-active/.test(previewNormal.className)) {
			previewNormal.className = previewNormal.className.replace(
				/\s*editor-preview-active\s*/g, ""
			);
			var toolbar = editor.toolbarElements.preview;
			var toolbar_div = wrapper.previousSibling;
			toolbar.className = toolbar.className.replace(/\s*active\s*/g, "");
			toolbar_div.className = toolbar_div.className.replace(/\s*disabled-for-preview*/g, "");
		}

		var sideBySideRenderingFunction = function() {
			preview.innerHTML = editor.options.previewRender(editor.value(), preview);
		};

		if(!cm.sideBySideRenderingFunction) {
			cm.sideBySideRenderingFunction = sideBySideRenderingFunction;
		}

		if(useSideBySideListener) {
			preview.innerHTML = editor.options.previewRender(editor.value(), preview);
			cm.on("update", cm.sideBySideRenderingFunction);
		} else {
			cm.off("update", cm.sideBySideRenderingFunction);
		}

		// Refresh to fix selection being off (#309)
		cm.refresh();
	}


	/**
	 * Preview action.
	 */
	function togglePreview(editor) {
		var cm = editor.codemirror;
		var wrapper = cm.getWrapperElement();
		var toolbar_div = wrapper.previousSibling;
		var toolbar = editor.options.toolbar ? editor.toolbarElements.preview : false;
		var preview = wrapper.lastChild;
		if(!preview || !/editor-preview/.test(preview.className)) {
			preview = document.createElement("div");
			preview.className = "editor-preview";
			wrapper.appendChild(preview);
		}
		if(/editor-preview-active/.test(preview.className)) {
			preview.className = preview.className.replace(
				/\s*editor-preview-active\s*/g, ""
			);
			if(toolbar) {
				toolbar.className = toolbar.className.replace(/\s*active\s*/g, "");
				toolbar_div.className = toolbar_div.className.replace(/\s*disabled-for-preview*/g, "");
			}
		} else {
			// When the preview button is clicked for the first time,
			// give some time for the transition from editor.css to fire and the view to slide from right to left,
			// instead of just appearing.
			setTimeout(function() {
				preview.className += " editor-preview-active";
			}, 1);
			if(toolbar) {
				toolbar.className += " active";
				toolbar_div.className += " disabled-for-preview";
			}
		}
		preview.innerHTML = editor.options.previewRender(editor.value(), preview);

		// Turn off side by side if needed
		var sidebyside = cm.getWrapperElement().nextSibling;
		if(/editor-preview-active-side/.test(sidebyside.className))
			toggleSideBySide(editor);
	}

	function _replaceSelection(cm, active, startEnd, url) {
		if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
			return;

		var text;
		var start = startEnd[0];
		var end = startEnd[1];
		var startPoint = cm.getCursor("start");
		var endPoint = cm.getCursor("end");
		if(url) {
			end = end.replace("#url#", url);
		}
		if(active) {
			text = cm.getLine(startPoint.line);
			start = text.slice(0, startPoint.ch);
			end = text.slice(startPoint.ch);
			cm.replaceRange(start + end, {
				line: startPoint.line,
				ch: 0
			});
		} else {
			text = cm.getSelection();
			cm.replaceSelection(start + text + end);

			startPoint.ch += start.length;
			if(startPoint !== endPoint) {
				endPoint.ch += start.length;
			}
		}
		cm.setSelection(startPoint, endPoint);
		cm.focus();
	}


	function _toggleHeading(cm, direction, size) {
		if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
			return;

		var startPoint = cm.getCursor("start");
		var endPoint = cm.getCursor("end");
		for(var i = startPoint.line; i <= endPoint.line; i++) {
			(function(i) {
				var text = cm.getLine(i);
				var currHeadingLevel = text.search(/[^#]/);

				if(direction !== undefined) {
					if(currHeadingLevel <= 0) {
						if(direction == "bigger") {
							text = "###### " + text;
						} else {
							text = "# " + text;
						}
					} else if(currHeadingLevel == 6 && direction == "smaller") {
						text = text.substr(7);
					} else if(currHeadingLevel == 1 && direction == "bigger") {
						text = text.substr(2);
					} else {
						if(direction == "bigger") {
							text = text.substr(1);
						} else {
							text = "#" + text;
						}
					}
				} else {
					if(size == 1) {
						if(currHeadingLevel <= 0) {
							text = "# " + text;
						} else if(currHeadingLevel == size) {
							text = text.substr(currHeadingLevel + 1);
						} else {
							text = "# " + text.substr(currHeadingLevel + 1);
						}
					} else if(size == 2) {
						if(currHeadingLevel <= 0) {
							text = "## " + text;
						} else if(currHeadingLevel == size) {
							text = text.substr(currHeadingLevel + 1);
						} else {
							text = "## " + text.substr(currHeadingLevel + 1);
						}
					} else {
						if(currHeadingLevel <= 0) {
							text = "### " + text;
						} else if(currHeadingLevel == size) {
							text = text.substr(currHeadingLevel + 1);
						} else {
							text = "### " + text.substr(currHeadingLevel + 1);
						}
					}
				}

				cm.replaceRange(text, {
					line: i,
					ch: 0
				}, {
					line: i,
					ch: 99999999999999
				});
			})(i);
		}
		cm.focus();
	}


	function _toggleLine(cm, name) {
		if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
			return;

		var stat = getState(cm);
		var startPoint = cm.getCursor("start");
		var endPoint = cm.getCursor("end");
		var repl = {
			"quote": /^(\s*)\>\s+/,
			"unordered-list": /^(\s*)(\*|\-|\+)\s+/,
			"ordered-list": /^(\s*)\d+\.\s+/
		};
		var map = {
			"quote": "> ",
			"unordered-list": "* ",
			"ordered-list": "1. "
		};
		for(var i = startPoint.line; i <= endPoint.line; i++) {
			(function(i) {
				var text = cm.getLine(i);
				if(stat[name]) {
					text = text.replace(repl[name], "$1");
				} else {
					text = map[name] + text;
				}
				cm.replaceRange(text, {
					line: i,
					ch: 0
				}, {
					line: i,
					ch: 99999999999999
				});
			})(i);
		}
		cm.focus();
	}

	function _toggleBlock(editor, type, start_chars, end_chars) {
		if(/editor-preview-active/.test(editor.codemirror.getWrapperElement().lastChild.className))
			return;

		end_chars = (typeof end_chars === "undefined") ? start_chars : end_chars;
		var cm = editor.codemirror;
		var stat = getState(cm);

		var text;
		var start = start_chars;
		var end = end_chars;

		var startPoint = cm.getCursor("start");
		var endPoint = cm.getCursor("end");

		if(stat[type]) {
			text = cm.getLine(startPoint.line);
			start = text.slice(0, startPoint.ch);
			end = text.slice(startPoint.ch);
			if(type == "bold") {
				start = start.replace(/(\*\*|__)(?![\s\S]*(\*\*|__))/, "");
				end = end.replace(/(\*\*|__)/, "");
			} else if(type == "italic") {
				start = start.replace(/(\*|_)(?![\s\S]*(\*|_))/, "");
				end = end.replace(/(\*|_)/, "");
			} else if(type == "strikethrough") {
				start = start.replace(/(\*\*|~~)(?![\s\S]*(\*\*|~~))/, "");
				end = end.replace(/(\*\*|~~)/, "");
			}
			cm.replaceRange(start + end, {
				line: startPoint.line,
				ch: 0
			}, {
				line: startPoint.line,
				ch: 99999999999999
			});

			if(type == "bold" || type == "strikethrough") {
				startPoint.ch -= 2;
				if(startPoint !== endPoint) {
					endPoint.ch -= 2;
				}
			} else if(type == "italic") {
				startPoint.ch -= 1;
				if(startPoint !== endPoint) {
					endPoint.ch -= 1;
				}
			}
		} else {
			text = cm.getSelection();
			if(type == "bold") {
				text = text.split("**").join("");
				text = text.split("__").join("");
			} else if(type == "italic") {
				text = text.split("*").join("");
				text = text.split("_").join("");
			} else if(type == "strikethrough") {
				text = text.split("~~").join("");
			}
			cm.replaceSelection(start + text + end);

			startPoint.ch += start_chars.length;
			endPoint.ch = startPoint.ch + text.length;
		}

		cm.setSelection(startPoint, endPoint);
		cm.focus();
	}

	function _cleanBlock(cm) {
		if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
			return;

		var startPoint = cm.getCursor("start");
		var endPoint = cm.getCursor("end");
		var text;

		for(var line = startPoint.line; line <= endPoint.line; line++) {
			text = cm.getLine(line);
			text = text.replace(/^[ ]*([# ]+|\*|\-|[> ]+|[0-9]+(.|\)))[ ]*/, "");

			cm.replaceRange(text, {
				line: line,
				ch: 0
			}, {
				line: line,
				ch: 99999999999999
			});
		}
	}

	// Merge the properties of one object into another.
	function _mergeProperties(target, source) {
		for(var property in source) {
			if(source.hasOwnProperty(property)) {
				if(source[property] instanceof Array) {
					target[property] = source[property].concat(target[property] instanceof Array ? target[property] : []);
				} else if(
					source[property] !== null &&
					typeof source[property] === "object" &&
					source[property].constructor === Object
				) {
					target[property] = _mergeProperties(target[property] || {}, source[property]);
				} else {
					target[property] = source[property];
				}
			}
		}

		return target;
	}

	// Merge an arbitrary number of objects into one.
	function extend(target) {
		for(var i = 1; i < arguments.length; i++) {
			target = _mergeProperties(target, arguments[i]);
		}

		return target;
	}

	/* The right word count in respect for CJK. */
	function wordCount(data) {
		var pattern = /[a-zA-Z0-9_\u0392-\u03c9\u0410-\u04F9]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af]+/g;
		var m = data.match(pattern);
		var count = 0;
		if(m === null) return count;
		for(var i = 0; i < m.length; i++) {
			if(m[i].charCodeAt(0) >= 0x4E00) {
				count += m[i].length;
			} else {
				count += 1;
			}
		}
		return count;
	}

	var toolbarBuiltInButtons = {
		"bold": {
			name: "bold",
			action: toggleBold,
			className: "fa fa-bold",
			title: "Bold",
			default: true
		},
		"italic": {
			name: "italic",
			action: toggleItalic,
			className: "fa fa-italic",
			title: "Italic",
			default: true
		},
		"strikethrough": {
			name: "strikethrough",
			action: toggleStrikethrough,
			className: "fa fa-strikethrough",
			title: "Strikethrough"
		},
		"heading": {
			name: "heading",
			action: toggleHeadingSmaller,
			className: "fa fa-header",
			title: "Heading",
			default: true
		},
		"heading-smaller": {
			name: "heading-smaller",
			action: toggleHeadingSmaller,
			className: "fa fa-header fa-header-x fa-header-smaller",
			title: "Smaller Heading"
		},
		"heading-bigger": {
			name: "heading-bigger",
			action: toggleHeadingBigger,
			className: "fa fa-header fa-header-x fa-header-bigger",
			title: "Bigger Heading"
		},
		"heading-1": {
			name: "heading-1",
			action: toggleHeading1,
			className: "fa fa-header fa-header-x fa-header-1",
			title: "Big Heading"
		},
		"heading-2": {
			name: "heading-2",
			action: toggleHeading2,
			className: "fa fa-header fa-header-x fa-header-2",
			title: "Medium Heading"
		},
		"heading-3": {
			name: "heading-3",
			action: toggleHeading3,
			className: "fa fa-header fa-header-x fa-header-3",
			title: "Small Heading"
		},
		"separator-1": {
			name: "separator-1"
		},
		"code": {
			name: "code",
			action: toggleCodeBlock,
			className: "fa fa-code",
			title: "Code"
		},
		"quote": {
			name: "quote",
			action: toggleBlockquote,
			className: "fa fa-quote-left",
			title: "Quote",
			default: true
		},
		"unordered-list": {
			name: "unordered-list",
			action: toggleUnorderedList,
			className: "fa fa-list-ul",
			title: "Generic List",
			default: true
		},
		"ordered-list": {
			name: "ordered-list",
			action: toggleOrderedList,
			className: "fa fa-list-ol",
			title: "Numbered List",
			default: true
		},
		"clean-block": {
			name: "clean-block",
			action: cleanBlock,
			className: "fa fa-eraser fa-clean-block",
			title: "Clean block"
		},
		"separator-2": {
			name: "separator-2"
		},
		"link": {
			name: "link",
			action: drawLink,
			className: "fa fa-link",
			title: "Create Link",
			default: true
		},
		"image": {
			name: "image",
			action: drawImage,
			className: "fa fa-picture-o",
			title: "Insert Image",
			default: true
		},
		"table": {
			name: "table",
			action: drawTable,
			className: "fa fa-table",
			title: "Insert Table"
		},
		"horizontal-rule": {
			name: "horizontal-rule",
			action: drawHorizontalRule,
			className: "fa fa-minus",
			title: "Insert Horizontal Line"
		},
		"separator-3": {
			name: "separator-3"
		},
		"preview": {
			name: "preview",
			action: togglePreview,
			className: "fa fa-eye no-disable",
			title: "Toggle Preview",
			default: true
		},
		"side-by-side": {
			name: "side-by-side",
			action: toggleSideBySide,
			className: "fa fa-columns no-disable no-mobile",
			title: "Toggle Side by Side",
			default: true
		},
		"fullscreen": {
			name: "fullscreen",
			action: toggleFullScreen,
			className: "fa fa-arrows-alt no-disable no-mobile",
			title: "Toggle Fullscreen",
			default: true
		},
		"separator-4": {
			name: "separator-4"
		},
		"guide": {
			name: "guide",
			action: "https://simplemde.com/markdown-guide",
			className: "fa fa-question-circle",
			title: "Markdown Guide",
			default: true
		},
		"separator-5": {
			name: "separator-5"
		},
		"undo": {
			name: "undo",
			action: undo,
			className: "fa fa-undo no-disable",
			title: "Undo"
		},
		"redo": {
			name: "redo",
			action: redo,
			className: "fa fa-repeat no-disable",
			title: "Redo"
		}
	};

	var insertTexts = {
		link: ["[", "](#url#)"],
		image: ["![](", "#url#)"],
		table: ["", "\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text     | Text     | Text     |\n\n"],
		horizontalRule: ["", "\n\n-----\n\n"]
	};

	var promptTexts = {
		link: "URL for the link:",
		image: "URL of the image:"
	};

	var blockStyles = {
		"bold": "**",
		"code": "```",
		"italic": "*"
	};

	/**
	 * Interface of SimpleMDE.
	 */
	function SimpleMDE(options) {
		// Handle options parameter
		options = options || {};


		// Used later to refer to it"s parent
		options.parent = this;


		// Check if Font Awesome needs to be auto downloaded
		var autoDownloadFA = true;

		if(options.autoDownloadFontAwesome === false) {
			autoDownloadFA = false;
		}

		if(options.autoDownloadFontAwesome !== true) {
			var styleSheets = document.styleSheets;
			for(var i = 0; i < styleSheets.length; i++) {
				if(!styleSheets[i].href)
					continue;

				if(styleSheets[i].href.indexOf("//maxcdn.bootstrapcdn.com/font-awesome/") > -1) {
					autoDownloadFA = false;
				}
			}
		}

		if(autoDownloadFA) {
			var link = document.createElement("link");
			link.rel = "stylesheet";
			link.href = "https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css";
			document.getElementsByTagName("head")[0].appendChild(link);
		}


		// Find the textarea to use
		if(options.element) {
			this.element = options.element;
		} else if(options.element === null) {
			// This means that the element option was specified, but no element was found
			console.log("SimpleMDE: Error. No element was found.");
			return;
		}


		// Handle toolbar
		if(options.toolbar === undefined) {
			// Initialize
			options.toolbar = [];


			// Loop over the built in buttons, to get the preferred order
			for(var key in toolbarBuiltInButtons) {
				if(toolbarBuiltInButtons.hasOwnProperty(key)) {
					if(key.indexOf("separator-") != -1) {
						options.toolbar.push("|");
					}

					if(toolbarBuiltInButtons[key].default === true || (options.showIcons && options.showIcons.constructor === Array && options.showIcons.indexOf(key) != -1)) {
						options.toolbar.push(key);
					}
				}
			}
		}


		// Handle status bar
		if(!options.hasOwnProperty("status")) {
			options.status = ["autosave", "lines", "words", "cursor"];
		}


		// Add default preview rendering function
		if(!options.previewRender) {
			options.previewRender = function(plainText) {
				// Note: "this" refers to the options object
				return this.parent.markdown(plainText);
			};
		}


		// Set default options for parsing config
		options.parsingConfig = extend({
			highlightFormatting: true // needed for toggleCodeBlock to detect types of code
		}, options.parsingConfig || {});


		// Merging the insertTexts, with the given options
		options.insertTexts = extend({}, insertTexts, options.insertTexts || {});


		// Merging the promptTexts, with the given options
		options.promptTexts = promptTexts;


		// Merging the blockStyles, with the given options
		options.blockStyles = extend({}, blockStyles, options.blockStyles || {});


		// Merging the shortcuts, with the given options
		options.shortcuts = extend({}, shortcuts, options.shortcuts || {});


		// Change unique_id to uniqueId for backwards compatibility
		if(options.autosave != undefined && options.autosave.unique_id != undefined && options.autosave.unique_id != "")
			options.autosave.uniqueId = options.autosave.unique_id;


		// Update this options
		this.options = options;


		// Auto render
		this.render();


		// The codemirror component is only available after rendering
		// so, the setter for the initialValue can only run after
		// the element has been rendered
		if(options.initialValue && (!this.options.autosave || this.options.autosave.foundSavedValue !== true)) {
			this.value(options.initialValue);
		}
	}

	/**
	 * Default markdown render.
	 */
	SimpleMDE.prototype.markdown = function(text) {
		if(marked) {
			// Initialize
			var markedOptions = {};


			// Update options
			if(this.options && this.options.renderingConfig && this.options.renderingConfig.singleLineBreaks === false) {
				markedOptions.breaks = false;
			} else {
				markedOptions.breaks = true;
			}

			if(this.options && this.options.renderingConfig && this.options.renderingConfig.codeSyntaxHighlighting === true && window.hljs) {
				markedOptions.highlight = function(code) {
					return window.hljs.highlightAuto(code).value;
				};
			}


			// Set options
			marked.setOptions(markedOptions);


			// Return
			return marked(text);
		}
	};

	/**
	 * Render editor to the given element.
	 */
	SimpleMDE.prototype.render = function(el) {
		if(!el) {
			el = this.element || document.getElementsByTagName("textarea")[0];
		}

		if(this._rendered && this._rendered === el) {
			// Already rendered.
			return;
		}

		this.element = el;
		var options = this.options;

		var self = this;
		var keyMaps = {};

		for(var key in options.shortcuts) {
			// null stands for "do not bind this command"
			if(options.shortcuts[key] !== null && bindings[key] !== null) {
				(function(key) {
					keyMaps[fixShortcut(options.shortcuts[key])] = function() {
						bindings[key](self);
					};
				})(key);
			}
		}

		keyMaps["Enter"] = "newlineAndIndentContinueMarkdownList";
		keyMaps["Tab"] = "tabAndIndentMarkdownList";
		keyMaps["Shift-Tab"] = "shiftTabAndUnindentMarkdownList";
		keyMaps["Esc"] = function(cm) {
			if(cm.getOption("fullScreen")) toggleFullScreen(self);
		};

		document.addEventListener("keydown", function(e) {
			e = e || window.event;

			if(e.keyCode == 27) {
				if(self.codemirror.getOption("fullScreen")) toggleFullScreen(self);
			}
		}, false);

		var mode, backdrop;
		if(options.spellChecker !== false) {
			mode = "spell-checker";
			backdrop = options.parsingConfig;
			backdrop.name = "gfm";
			backdrop.gitHubSpice = false;

			CodeMirrorSpellChecker({
				codeMirrorInstance: CodeMirror
			});
		} else {
			mode = options.parsingConfig;
			mode.name = "gfm";
			mode.gitHubSpice = false;
		}

		this.codemirror = CodeMirror.fromTextArea(el, {
			mode: mode,
			backdrop: backdrop,
			theme: "paper",
			tabSize: (options.tabSize != undefined) ? options.tabSize : 2,
			indentUnit: (options.tabSize != undefined) ? options.tabSize : 2,
			indentWithTabs: (options.indentWithTabs === false) ? false : true,
			lineNumbers: false,
			autofocus: (options.autofocus === true) ? true : false,
			extraKeys: keyMaps,
			lineWrapping: (options.lineWrapping === false) ? false : true,
			allowDropFileTypes: ["text/plain"],
			placeholder: options.placeholder || el.getAttribute("placeholder") || "",
			styleSelectedText: (options.styleSelectedText != undefined) ? options.styleSelectedText : true
		});

		if(options.forceSync === true) {
			var cm = this.codemirror;
			cm.on("change", function() {
				cm.save();
			});
		}

		this.gui = {};

		if(options.toolbar !== false) {
			this.gui.toolbar = this.createToolbar();
		}
		if(options.status !== false) {
			this.gui.statusbar = this.createStatusbar();
		}
		if(options.autosave != undefined && options.autosave.enabled === true) {
			this.autosave();
		}

		this.gui.sideBySide = this.createSideBySide();

		this._rendered = this.element;


		// Fixes CodeMirror bug (#344)
		var temp_cm = this.codemirror;
		setTimeout(function() {
			temp_cm.refresh();
		}.bind(temp_cm), 0);
	};

	// Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem throw QuotaExceededError. We're going to detect this and set a variable accordingly.
	function isLocalStorageAvailable() {
		if(typeof localStorage === "object") {
			try {
				localStorage.setItem("smde_localStorage", 1);
				localStorage.removeItem("smde_localStorage");
			} catch(e) {
				return false;
			}
		} else {
			return false;
		}

		return true;
	}

	SimpleMDE.prototype.autosave = function() {
		if(isLocalStorageAvailable()) {
			var simplemde = this;

			if(this.options.autosave.uniqueId == undefined || this.options.autosave.uniqueId == "") {
				console.log("SimpleMDE: You must set a uniqueId to use the autosave feature");
				return;
			}

			if(simplemde.element.form != null && simplemde.element.form != undefined) {
				simplemde.element.form.addEventListener("submit", function() {
					localStorage.removeItem("smde_" + simplemde.options.autosave.uniqueId);
				});
			}

			if(this.options.autosave.loaded !== true) {
				if(typeof localStorage.getItem("smde_" + this.options.autosave.uniqueId) == "string" && localStorage.getItem("smde_" + this.options.autosave.uniqueId) != "") {
					this.codemirror.setValue(localStorage.getItem("smde_" + this.options.autosave.uniqueId));
					this.options.autosave.foundSavedValue = true;
				}

				this.options.autosave.loaded = true;
			}

			localStorage.setItem("smde_" + this.options.autosave.uniqueId, simplemde.value());

			var el = document.getElementById("autosaved");
			if(el != null && el != undefined && el != "") {
				var d = new Date();
				var hh = d.getHours();
				var m = d.getMinutes();
				var dd = "am";
				var h = hh;
				if(h >= 12) {
					h = hh - 12;
					dd = "pm";
				}
				if(h == 0) {
					h = 12;
				}
				m = m < 10 ? "0" + m : m;

				el.innerHTML = "Autosaved: " + h + ":" + m + " " + dd;
			}

			this.autosaveTimeoutId = setTimeout(function() {
				simplemde.autosave();
			}, this.options.autosave.delay || 10000);
		} else {
			console.log("SimpleMDE: localStorage not available, cannot autosave");
		}
	};

	SimpleMDE.prototype.clearAutosavedValue = function() {
		if(isLocalStorageAvailable()) {
			if(this.options.autosave == undefined || this.options.autosave.uniqueId == undefined || this.options.autosave.uniqueId == "") {
				console.log("SimpleMDE: You must set a uniqueId to clear the autosave value");
				return;
			}

			localStorage.removeItem("smde_" + this.options.autosave.uniqueId);
		} else {
			console.log("SimpleMDE: localStorage not available, cannot autosave");
		}
	};

	SimpleMDE.prototype.createSideBySide = function() {
		var cm = this.codemirror;
		var wrapper = cm.getWrapperElement();
		var preview = wrapper.nextSibling;

		if(!preview || !/editor-preview-side/.test(preview.className)) {
			preview = document.createElement("div");
			preview.className = "editor-preview-side";
			wrapper.parentNode.insertBefore(preview, wrapper.nextSibling);
		}

		// Syncs scroll  editor -> preview
		var cScroll = false;
		var pScroll = false;
		cm.on("scroll", function(v) {
			if(cScroll) {
				cScroll = false;
				return;
			}
			pScroll = true;
			var height = v.getScrollInfo().height - v.getScrollInfo().clientHeight;
			var ratio = parseFloat(v.getScrollInfo().top) / height;
			var move = (preview.scrollHeight - preview.clientHeight) * ratio;
			preview.scrollTop = move;
		});

		// Syncs scroll  preview -> editor
		preview.onscroll = function() {
			if(pScroll) {
				pScroll = false;
				return;
			}
			cScroll = true;
			var height = preview.scrollHeight - preview.clientHeight;
			var ratio = parseFloat(preview.scrollTop) / height;
			var move = (cm.getScrollInfo().height - cm.getScrollInfo().clientHeight) * ratio;
			cm.scrollTo(0, move);
		};
		return preview;
	};

	SimpleMDE.prototype.createToolbar = function(items) {
		items = items || this.options.toolbar;

		if(!items || items.length === 0) {
			return;
		}
		var i;
		for(i = 0; i < items.length; i++) {
			if(toolbarBuiltInButtons[items[i]] != undefined) {
				items[i] = toolbarBuiltInButtons[items[i]];
			}
		}

		var bar = document.createElement("div");
		bar.className = "editor-toolbar";

		var self = this;

		var toolbarData = {};
		self.toolbar = items;

		for(i = 0; i < items.length; i++) {
			if(items[i].name == "guide" && self.options.toolbarGuideIcon === false)
				continue;

			if(self.options.hideIcons && self.options.hideIcons.indexOf(items[i].name) != -1)
				continue;

			// Fullscreen does not work well on mobile devices (even tablets)
			// In the future, hopefully this can be resolved
			if((items[i].name == "fullscreen" || items[i].name == "side-by-side") && isMobile())
				continue;


			// Don't include trailing separators
			if(items[i] === "|") {
				var nonSeparatorIconsFollow = false;

				for(var x = (i + 1); x < items.length; x++) {
					if(items[x] !== "|" && (!self.options.hideIcons || self.options.hideIcons.indexOf(items[x].name) == -1)) {
						nonSeparatorIconsFollow = true;
					}
				}

				if(!nonSeparatorIconsFollow)
					continue;
			}


			// Create the icon and append to the toolbar
			(function(item) {
				var el;
				if(item === "|") {
					el = createSep();
				} else {
					el = createIcon(item, self.options.toolbarTips, self.options.shortcuts);
				}

				// bind events, special for info
				if(item.action) {
					if(typeof item.action === "function") {
						el.onclick = function(e) {
							e.preventDefault();
							item.action(self);
						};
					} else if(typeof item.action === "string") {
						el.href = item.action;
						el.target = "_blank";
					}
				}

				toolbarData[item.name || item] = el;
				bar.appendChild(el);
			})(items[i]);
		}

		self.toolbarElements = toolbarData;

		var cm = this.codemirror;
		cm.on("cursorActivity", function() {
			var stat = getState(cm);

			for(var key in toolbarData) {
				(function(key) {
					var el = toolbarData[key];
					if(stat[key]) {
						el.className += " active";
					} else if(key != "fullscreen" && key != "side-by-side") {
						el.className = el.className.replace(/\s*active\s*/g, "");
					}
				})(key);
			}
		});

		var cmWrapper = cm.getWrapperElement();
		cmWrapper.parentNode.insertBefore(bar, cmWrapper);
		return bar;
	};

	SimpleMDE.prototype.createStatusbar = function(status) {
		// Initialize
		status = status || this.options.status;
		var options = this.options;
		var cm = this.codemirror;


		// Make sure the status variable is valid
		if(!status || status.length === 0)
			return;


		// Set up the built-in items
		var items = [];
		var i, onUpdate, defaultValue;

		for(i = 0; i < status.length; i++) {
			// Reset some values
			onUpdate = undefined;
			defaultValue = undefined;


			// Handle if custom or not
			if(typeof status[i] === "object") {
				items.push({
					className: status[i].className,
					defaultValue: status[i].defaultValue,
					onUpdate: status[i].onUpdate
				});
			} else {
				var name = status[i];

				if(name === "words") {
					defaultValue = function(el) {
						el.innerHTML = wordCount(cm.getValue());
					};
					onUpdate = function(el) {
						el.innerHTML = wordCount(cm.getValue());
					};
				} else if(name === "lines") {
					defaultValue = function(el) {
						el.innerHTML = cm.lineCount();
					};
					onUpdate = function(el) {
						el.innerHTML = cm.lineCount();
					};
				} else if(name === "cursor") {
					defaultValue = function(el) {
						el.innerHTML = "0:0";
					};
					onUpdate = function(el) {
						var pos = cm.getCursor();
						el.innerHTML = pos.line + ":" + pos.ch;
					};
				} else if(name === "autosave") {
					defaultValue = function(el) {
						if(options.autosave != undefined && options.autosave.enabled === true) {
							el.setAttribute("id", "autosaved");
						}
					};
				}

				items.push({
					className: name,
					defaultValue: defaultValue,
					onUpdate: onUpdate
				});
			}
		}


		// Create element for the status bar
		var bar = document.createElement("div");
		bar.className = "editor-statusbar";


		// Create a new span for each item
		for(i = 0; i < items.length; i++) {
			// Store in temporary variable
			var item = items[i];


			// Create span element
			var el = document.createElement("span");
			el.className = item.className;


			// Ensure the defaultValue is a function
			if(typeof item.defaultValue === "function") {
				item.defaultValue(el);
			}


			// Ensure the onUpdate is a function
			if(typeof item.onUpdate === "function") {
				// Create a closure around the span of the current action, then execute the onUpdate handler
				this.codemirror.on("update", (function(el, item) {
					return function() {
						item.onUpdate(el);
					};
				}(el, item)));
			}


			// Append the item to the status bar
			bar.appendChild(el);
		}


		// Insert the status bar into the DOM
		var cmWrapper = this.codemirror.getWrapperElement();
		cmWrapper.parentNode.insertBefore(bar, cmWrapper.nextSibling);
		return bar;
	};

	/**
	 * Get or set the text content.
	 */
	SimpleMDE.prototype.value = function(val) {
		if(val === undefined) {
			return this.codemirror.getValue();
		} else {
			this.codemirror.getDoc().setValue(val);
			return this;
		}
	};


	/**
	 * Bind static methods for exports.
	 */
	SimpleMDE.toggleBold = toggleBold;
	SimpleMDE.toggleItalic = toggleItalic;
	SimpleMDE.toggleStrikethrough = toggleStrikethrough;
	SimpleMDE.toggleBlockquote = toggleBlockquote;
	SimpleMDE.toggleHeadingSmaller = toggleHeadingSmaller;
	SimpleMDE.toggleHeadingBigger = toggleHeadingBigger;
	SimpleMDE.toggleHeading1 = toggleHeading1;
	SimpleMDE.toggleHeading2 = toggleHeading2;
	SimpleMDE.toggleHeading3 = toggleHeading3;
	SimpleMDE.toggleCodeBlock = toggleCodeBlock;
	SimpleMDE.toggleUnorderedList = toggleUnorderedList;
	SimpleMDE.toggleOrderedList = toggleOrderedList;
	SimpleMDE.cleanBlock = cleanBlock;
	SimpleMDE.drawLink = drawLink;
	SimpleMDE.drawImage = drawImage;
	SimpleMDE.drawTable = drawTable;
	SimpleMDE.drawHorizontalRule = drawHorizontalRule;
	SimpleMDE.undo = undo;
	SimpleMDE.redo = redo;
	SimpleMDE.togglePreview = togglePreview;
	SimpleMDE.toggleSideBySide = toggleSideBySide;
	SimpleMDE.toggleFullScreen = toggleFullScreen;

	/**
	 * Bind instance methods for exports.
	 */
	SimpleMDE.prototype.toggleBold = function() {
		toggleBold(this);
	};
	SimpleMDE.prototype.toggleItalic = function() {
		toggleItalic(this);
	};
	SimpleMDE.prototype.toggleStrikethrough = function() {
		toggleStrikethrough(this);
	};
	SimpleMDE.prototype.toggleBlockquote = function() {
		toggleBlockquote(this);
	};
	SimpleMDE.prototype.toggleHeadingSmaller = function() {
		toggleHeadingSmaller(this);
	};
	SimpleMDE.prototype.toggleHeadingBigger = function() {
		toggleHeadingBigger(this);
	};
	SimpleMDE.prototype.toggleHeading1 = function() {
		toggleHeading1(this);
	};
	SimpleMDE.prototype.toggleHeading2 = function() {
		toggleHeading2(this);
	};
	SimpleMDE.prototype.toggleHeading3 = function() {
		toggleHeading3(this);
	};
	SimpleMDE.prototype.toggleCodeBlock = function() {
		toggleCodeBlock(this);
	};
	SimpleMDE.prototype.toggleUnorderedList = function() {
		toggleUnorderedList(this);
	};
	SimpleMDE.prototype.toggleOrderedList = function() {
		toggleOrderedList(this);
	};
	SimpleMDE.prototype.cleanBlock = function() {
		cleanBlock(this);
	};
	SimpleMDE.prototype.drawLink = function() {
		drawLink(this);
	};
	SimpleMDE.prototype.drawImage = function() {
		drawImage(this);
	};
	SimpleMDE.prototype.drawTable = function() {
		drawTable(this);
	};
	SimpleMDE.prototype.drawHorizontalRule = function() {
		drawHorizontalRule(this);
	};
	SimpleMDE.prototype.undo = function() {
		undo(this);
	};
	SimpleMDE.prototype.redo = function() {
		redo(this);
	};
	SimpleMDE.prototype.togglePreview = function() {
		togglePreview(this);
	};
	SimpleMDE.prototype.toggleSideBySide = function() {
		toggleSideBySide(this);
	};
	SimpleMDE.prototype.toggleFullScreen = function() {
		toggleFullScreen(this);
	};

	SimpleMDE.prototype.isPreviewActive = function() {
		var cm = this.codemirror;
		var wrapper = cm.getWrapperElement();
		var preview = wrapper.lastChild;

		return /editor-preview-active/.test(preview.className);
	};

	SimpleMDE.prototype.isSideBySideActive = function() {
		var cm = this.codemirror;
		var wrapper = cm.getWrapperElement();
		var preview = wrapper.nextSibling;

		return /editor-preview-active-side/.test(preview.className);
	};

	SimpleMDE.prototype.isFullscreenActive = function() {
		var cm = this.codemirror;

		return cm.getOption("fullScreen");
	};

	SimpleMDE.prototype.getState = function() {
		var cm = this.codemirror;

		return getState(cm);
	};

	SimpleMDE.prototype.toTextArea = function() {
		var cm = this.codemirror;
		var wrapper = cm.getWrapperElement();

		if(wrapper.parentNode) {
			if(this.gui.toolbar) {
				wrapper.parentNode.removeChild(this.gui.toolbar);
			}
			if(this.gui.statusbar) {
				wrapper.parentNode.removeChild(this.gui.statusbar);
			}
			if(this.gui.sideBySide) {
				wrapper.parentNode.removeChild(this.gui.sideBySide);
			}
		}

		cm.toTextArea();

		if(this.autosaveTimeoutId) {
			clearTimeout(this.autosaveTimeoutId);
			this.autosaveTimeoutId = undefined;
			this.clearAutosavedValue();
		}
	};

	module.exports = SimpleMDE;

/***/ },
/* 351 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	// This is CodeMirror (https://codemirror.net), a code editor
	// implemented in JavaScript on top of the browser's DOM.
	//
	// You can find some technical background for some of the code below
	// at http://marijnhaverbeke.nl/blog/#cm-internals .

	(function (global, factory) {
	   true ? module.exports = factory() :
	  typeof define === 'function' && define.amd ? define(factory) :
	  (global.CodeMirror = factory());
	}(this, (function () { 'use strict';

	  // Kludges for bugs and behavior differences that can't be feature
	  // detected are enabled based on userAgent etc sniffing.
	  var userAgent = navigator.userAgent;
	  var platform = navigator.platform;

	  var gecko = /gecko\/\d/i.test(userAgent);
	  var ie_upto10 = /MSIE \d/.test(userAgent);
	  var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
	  var edge = /Edge\/(\d+)/.exec(userAgent);
	  var ie = ie_upto10 || ie_11up || edge;
	  var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]);
	  var webkit = !edge && /WebKit\//.test(userAgent);
	  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
	  var chrome = !edge && /Chrome\//.test(userAgent);
	  var presto = /Opera\//.test(userAgent);
	  var safari = /Apple Computer/.test(navigator.vendor);
	  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
	  var phantom = /PhantomJS/.test(userAgent);

	  var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
	  var android = /Android/.test(userAgent);
	  // This is woefully incomplete. Suggestions for alternative methods welcome.
	  var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
	  var mac = ios || /Mac/.test(platform);
	  var chromeOS = /\bCrOS\b/.test(userAgent);
	  var windows = /win/i.test(platform);

	  var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
	  if (presto_version) { presto_version = Number(presto_version[1]); }
	  if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
	  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
	  var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
	  var captureRightClick = gecko || (ie && ie_version >= 9);

	  function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }

	  var rmClass = function(node, cls) {
	    var current = node.className;
	    var match = classTest(cls).exec(current);
	    if (match) {
	      var after = current.slice(match.index + match[0].length);
	      node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
	    }
	  };

	  function removeChildren(e) {
	    for (var count = e.childNodes.length; count > 0; --count)
	      { e.removeChild(e.firstChild); }
	    return e
	  }

	  function removeChildrenAndAdd(parent, e) {
	    return removeChildren(parent).appendChild(e)
	  }

	  function elt(tag, content, className, style) {
	    var e = document.createElement(tag);
	    if (className) { e.className = className; }
	    if (style) { e.style.cssText = style; }
	    if (typeof content == "string") { e.appendChild(document.createTextNode(content)); }
	    else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } }
	    return e
	  }
	  // wrapper for elt, which removes the elt from the accessibility tree
	  function eltP(tag, content, className, style) {
	    var e = elt(tag, content, className, style);
	    e.setAttribute("role", "presentation");
	    return e
	  }

	  var range;
	  if (document.createRange) { range = function(node, start, end, endNode) {
	    var r = document.createRange();
	    r.setEnd(endNode || node, end);
	    r.setStart(node, start);
	    return r
	  }; }
	  else { range = function(node, start, end) {
	    var r = document.body.createTextRange();
	    try { r.moveToElementText(node.parentNode); }
	    catch(e) { return r }
	    r.collapse(true);
	    r.moveEnd("character", end);
	    r.moveStart("character", start);
	    return r
	  }; }

	  function contains(parent, child) {
	    if (child.nodeType == 3) // Android browser always returns false when child is a textnode
	      { child = child.parentNode; }
	    if (parent.contains)
	      { return parent.contains(child) }
	    do {
	      if (child.nodeType == 11) { child = child.host; }
	      if (child == parent) { return true }
	    } while (child = child.parentNode)
	  }

	  function activeElt() {
	    // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
	    // IE < 10 will throw when accessed while the page is loading or in an iframe.
	    // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
	    var activeElement;
	    try {
	      activeElement = document.activeElement;
	    } catch(e) {
	      activeElement = document.body || null;
	    }
	    while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
	      { activeElement = activeElement.shadowRoot.activeElement; }
	    return activeElement
	  }

	  function addClass(node, cls) {
	    var current = node.className;
	    if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; }
	  }
	  function joinClasses(a, b) {
	    var as = a.split(" ");
	    for (var i = 0; i < as.length; i++)
	      { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } }
	    return b
	  }

	  var selectInput = function(node) { node.select(); };
	  if (ios) // Mobile Safari apparently has a bug where select() is broken.
	    { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; }
	  else if (ie) // Suppress mysterious IE10 errors
	    { selectInput = function(node) { try { node.select(); } catch(_e) {} }; }

	  function bind(f) {
	    var args = Array.prototype.slice.call(arguments, 1);
	    return function(){return f.apply(null, args)}
	  }

	  function copyObj(obj, target, overwrite) {
	    if (!target) { target = {}; }
	    for (var prop in obj)
	      { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
	        { target[prop] = obj[prop]; } }
	    return target
	  }

	  // Counts the column offset in a string, taking tabs into account.
	  // Used mostly to find indentation.
	  function countColumn(string, end, tabSize, startIndex, startValue) {
	    if (end == null) {
	      end = string.search(/[^\s\u00a0]/);
	      if (end == -1) { end = string.length; }
	    }
	    for (var i = startIndex || 0, n = startValue || 0;;) {
	      var nextTab = string.indexOf("\t", i);
	      if (nextTab < 0 || nextTab >= end)
	        { return n + (end - i) }
	      n += nextTab - i;
	      n += tabSize - (n % tabSize);
	      i = nextTab + 1;
	    }
	  }

	  var Delayed = function() {this.id = null;};
	  Delayed.prototype.set = function (ms, f) {
	    clearTimeout(this.id);
	    this.id = setTimeout(f, ms);
	  };

	  function indexOf(array, elt) {
	    for (var i = 0; i < array.length; ++i)
	      { if (array[i] == elt) { return i } }
	    return -1
	  }

	  // Number of pixels added to scroller and sizer to hide scrollbar
	  var scrollerGap = 30;

	  // Returned or thrown by various protocols to signal 'I'm not
	  // handling this'.
	  var Pass = {toString: function(){return "CodeMirror.Pass"}};

	  // Reused option objects for setSelection & friends
	  var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};

	  // The inverse of countColumn -- find the offset that corresponds to
	  // a particular column.
	  function findColumn(string, goal, tabSize) {
	    for (var pos = 0, col = 0;;) {
	      var nextTab = string.indexOf("\t", pos);
	      if (nextTab == -1) { nextTab = string.length; }
	      var skipped = nextTab - pos;
	      if (nextTab == string.length || col + skipped >= goal)
	        { return pos + Math.min(skipped, goal - col) }
	      col += nextTab - pos;
	      col += tabSize - (col % tabSize);
	      pos = nextTab + 1;
	      if (col >= goal) { return pos }
	    }
	  }

	  var spaceStrs = [""];
	  function spaceStr(n) {
	    while (spaceStrs.length <= n)
	      { spaceStrs.push(lst(spaceStrs) + " "); }
	    return spaceStrs[n]
	  }

	  function lst(arr) { return arr[arr.length-1] }

	  function map(array, f) {
	    var out = [];
	    for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); }
	    return out
	  }

	  function insertSorted(array, value, score) {
	    var pos = 0, priority = score(value);
	    while (pos < array.length && score(array[pos]) <= priority) { pos++; }
	    array.splice(pos, 0, value);
	  }

	  function nothing() {}

	  function createObj(base, props) {
	    var inst;
	    if (Object.create) {
	      inst = Object.create(base);
	    } else {
	      nothing.prototype = base;
	      inst = new nothing();
	    }
	    if (props) { copyObj(props, inst); }
	    return inst
	  }

	  var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
	  function isWordCharBasic(ch) {
	    return /\w/.test(ch) || ch > "\x80" &&
	      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
	  }
	  function isWordChar(ch, helper) {
	    if (!helper) { return isWordCharBasic(ch) }
	    if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true }
	    return helper.test(ch)
	  }

	  function isEmpty(obj) {
	    for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }
	    return true
	  }

	  // Extending unicode characters. A series of a non-extending char +
	  // any number of extending chars is treated as a single unit as far
	  // as editing and measuring is concerned. This is not fully correct,
	  // since some scripts/fonts/browsers also treat other configurations
	  // of code points as a group.
	  var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
	  function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }

	  // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range.
	  function skipExtendingChars(str, pos, dir) {
	    while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; }
	    return pos
	  }

	  // Returns the value from the range [`from`; `to`] that satisfies
	  // `pred` and is closest to `from`. Assumes that at least `to`
	  // satisfies `pred`. Supports `from` being greater than `to`.
	  function findFirst(pred, from, to) {
	    // At any point we are certain `to` satisfies `pred`, don't know
	    // whether `from` does.
	    var dir = from > to ? -1 : 1;
	    for (;;) {
	      if (from == to) { return from }
	      var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF);
	      if (mid == from) { return pred(mid) ? from : to }
	      if (pred(mid)) { to = mid; }
	      else { from = mid + dir; }
	    }
	  }

	  // The display handles the DOM integration, both for input reading
	  // and content drawing. It holds references to DOM nodes and
	  // display-related state.

	  function Display(place, doc, input) {
	    var d = this;
	    this.input = input;

	    // Covers bottom-right square when both scrollbars are present.
	    d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
	    d.scrollbarFiller.setAttribute("cm-not-content", "true");
	    // Covers bottom of gutter when coverGutterNextToScrollbar is on
	    // and h scrollbar is present.
	    d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
	    d.gutterFiller.setAttribute("cm-not-content", "true");
	    // Will contain the actual code, positioned to cover the viewport.
	    d.lineDiv = eltP("div", null, "CodeMirror-code");
	    // Elements are added to these to represent selection and cursors.
	    d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
	    d.cursorDiv = elt("div", null, "CodeMirror-cursors");
	    // A visibility: hidden element used to find the size of things.
	    d.measure = elt("div", null, "CodeMirror-measure");
	    // When lines outside of the viewport are measured, they are drawn in this.
	    d.lineMeasure = elt("div", null, "CodeMirror-measure");
	    // Wraps everything that needs to exist inside the vertically-padded coordinate system
	    d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
	                      null, "position: relative; outline: none");
	    var lines = eltP("div", [d.lineSpace], "CodeMirror-lines");
	    // Moved around its parent to cover visible view.
	    d.mover = elt("div", [lines], null, "position: relative");
	    // Set to the height of the document, allowing scrolling.
	    d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
	    d.sizerWidth = null;
	    // Behavior of elts with overflow: auto and padding is
	    // inconsistent across browsers. This is used to ensure the
	    // scrollable area is big enough.
	    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
	    // Will contain the gutters, if any.
	    d.gutters = elt("div", null, "CodeMirror-gutters");
	    d.lineGutter = null;
	    // Actual scrollable element.
	    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
	    d.scroller.setAttribute("tabIndex", "-1");
	    // The element in which the editor lives.
	    d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");

	    // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
	    if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
	    if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; }

	    if (place) {
	      if (place.appendChild) { place.appendChild(d.wrapper); }
	      else { place(d.wrapper); }
	    }

	    // Current rendered range (may be bigger than the view window).
	    d.viewFrom = d.viewTo = doc.first;
	    d.reportedViewFrom = d.reportedViewTo = doc.first;
	    // Information about the rendered lines.
	    d.view = [];
	    d.renderedView = null;
	    // Holds info about a single rendered line when it was rendered
	    // for measurement, while not in view.
	    d.externalMeasured = null;
	    // Empty space (in pixels) above the view
	    d.viewOffset = 0;
	    d.lastWrapHeight = d.lastWrapWidth = 0;
	    d.updateLineNumbers = null;

	    d.nativeBarWidth = d.barHeight = d.barWidth = 0;
	    d.scrollbarsClipped = false;

	    // Used to only resize the line number gutter when necessary (when
	    // the amount of lines crosses a boundary that makes its width change)
	    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
	    // Set to true when a non-horizontal-scrolling line widget is
	    // added. As an optimization, line widget aligning is skipped when
	    // this is false.
	    d.alignWidgets = false;

	    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;

	    // Tracks the maximum line length so that the horizontal scrollbar
	    // can be kept static when scrolling.
	    d.maxLine = null;
	    d.maxLineLength = 0;
	    d.maxLineChanged = false;

	    // Used for measuring wheel scrolling granularity
	    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;

	    // True when shift is held down.
	    d.shift = false;

	    // Used to track whether anything happened since the context menu
	    // was opened.
	    d.selForContextMenu = null;

	    d.activeTouch = null;

	    input.init(d);
	  }

	  // Find the line object corresponding to the given line number.
	  function getLine(doc, n) {
	    n -= doc.first;
	    if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") }
	    var chunk = doc;
	    while (!chunk.lines) {
	      for (var i = 0;; ++i) {
	        var child = chunk.children[i], sz = child.chunkSize();
	        if (n < sz) { chunk = child; break }
	        n -= sz;
	      }
	    }
	    return chunk.lines[n]
	  }

	  // Get the part of a document between two positions, as an array of
	  // strings.
	  function getBetween(doc, start, end) {
	    var out = [], n = start.line;
	    doc.iter(start.line, end.line + 1, function (line) {
	      var text = line.text;
	      if (n == end.line) { text = text.slice(0, end.ch); }
	      if (n == start.line) { text = text.slice(start.ch); }
	      out.push(text);
	      ++n;
	    });
	    return out
	  }
	  // Get the lines between from and to, as array of strings.
	  function getLines(doc, from, to) {
	    var out = [];
	    doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value
	    return out
	  }

	  // Update the height of a line, propagating the height change
	  // upwards to parent nodes.
	  function updateLineHeight(line, height) {
	    var diff = height - line.height;
	    if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } }
	  }

	  // Given a line object, find its line number by walking up through
	  // its parent links.
	  function lineNo(line) {
	    if (line.parent == null) { return null }
	    var cur = line.parent, no = indexOf(cur.lines, line);
	    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
	      for (var i = 0;; ++i) {
	        if (chunk.children[i] == cur) { break }
	        no += chunk.children[i].chunkSize();
	      }
	    }
	    return no + cur.first
	  }

	  // Find the line at the given vertical position, using the height
	  // information in the document tree.
	  function lineAtHeight(chunk, h) {
	    var n = chunk.first;
	    outer: do {
	      for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {
	        var child = chunk.children[i$1], ch = child.height;
	        if (h < ch) { chunk = child; continue outer }
	        h -= ch;
	        n += child.chunkSize();
	      }
	      return n
	    } while (!chunk.lines)
	    var i = 0;
	    for (; i < chunk.lines.length; ++i) {
	      var line = chunk.lines[i], lh = line.height;
	      if (h < lh) { break }
	      h -= lh;
	    }
	    return n + i
	  }

	  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}

	  function lineNumberFor(options, i) {
	    return String(options.lineNumberFormatter(i + options.firstLineNumber))
	  }

	  // A Pos instance represents a position within the text.
	  function Pos(line, ch, sticky) {
	    if ( sticky === void 0 ) sticky = null;

	    if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) }
	    this.line = line;
	    this.ch = ch;
	    this.sticky = sticky;
	  }

	  // Compare two positions, return 0 if they are the same, a negative
	  // number when a is less, and a positive number otherwise.
	  function cmp(a, b) { return a.line - b.line || a.ch - b.ch }

	  function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 }

	  function copyPos(x) {return Pos(x.line, x.ch)}
	  function maxPos(a, b) { return cmp(a, b) < 0 ? b : a }
	  function minPos(a, b) { return cmp(a, b) < 0 ? a : b }

	  // Most of the external API clips given positions to make sure they
	  // actually exist within the document.
	  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}
	  function clipPos(doc, pos) {
	    if (pos.line < doc.first) { return Pos(doc.first, 0) }
	    var last = doc.first + doc.size - 1;
	    if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }
	    return clipToLen(pos, getLine(doc, pos.line).text.length)
	  }
	  function clipToLen(pos, linelen) {
	    var ch = pos.ch;
	    if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }
	    else if (ch < 0) { return Pos(pos.line, 0) }
	    else { return pos }
	  }
	  function clipPosArray(doc, array) {
	    var out = [];
	    for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); }
	    return out
	  }

	  // Optimize some code when these features are not used.
	  var sawReadOnlySpans = false, sawCollapsedSpans = false;

	  function seeReadOnlySpans() {
	    sawReadOnlySpans = true;
	  }

	  function seeCollapsedSpans() {
	    sawCollapsedSpans = true;
	  }

	  // TEXTMARKER SPANS

	  function MarkedSpan(marker, from, to) {
	    this.marker = marker;
	    this.from = from; this.to = to;
	  }

	  // Search an array of spans for a span matching the given marker.
	  function getMarkedSpanFor(spans, marker) {
	    if (spans) { for (var i = 0; i < spans.length; ++i) {
	      var span = spans[i];
	      if (span.marker == marker) { return span }
	    } }
	  }
	  // Remove a span from an array, returning undefined if no spans are
	  // left (we don't store arrays for lines without spans).
	  function removeMarkedSpan(spans, span) {
	    var r;
	    for (var i = 0; i < spans.length; ++i)
	      { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }
	    return r
	  }
	  // Add a span to a line.
	  function addMarkedSpan(line, span) {
	    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
	    span.marker.attachLine(line);
	  }

	  // Used for the algorithm that adjusts markers for a change in the
	  // document. These functions cut an array of spans at a given
	  // character position, returning an array of remaining chunks (or
	  // undefined if nothing remains).
	  function markedSpansBefore(old, startCh, isInsert) {
	    var nw;
	    if (old) { for (var i = 0; i < old.length; ++i) {
	      var span = old[i], marker = span.marker;
	      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
	      if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
	        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh)
	        ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
	      }
	    } }
	    return nw
	  }
	  function markedSpansAfter(old, endCh, isInsert) {
	    var nw;
	    if (old) { for (var i = 0; i < old.length; ++i) {
	      var span = old[i], marker = span.marker;
	      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
	      if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
	        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh)
	        ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
	                                              span.to == null ? null : span.to - endCh));
	      }
	    } }
	    return nw
	  }

	  // Given a change object, compute the new set of marker spans that
	  // cover the line in which the change took place. Removes spans
	  // entirely within the change, reconnects spans belonging to the
	  // same marker that appear on both sides of the change, and cuts off
	  // spans partially within the change. Returns an array of span
	  // arrays with one element for each line in (after) the change.
	  function stretchSpansOverChange(doc, change) {
	    if (change.full) { return null }
	    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
	    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
	    if (!oldFirst && !oldLast) { return null }

	    var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
	    // Get the spans that 'stick out' on both sides
	    var first = markedSpansBefore(oldFirst, startCh, isInsert);
	    var last = markedSpansAfter(oldLast, endCh, isInsert);

	    // Next, merge those two ends
	    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
	    if (first) {
	      // Fix up .to properties of first
	      for (var i = 0; i < first.length; ++i) {
	        var span = first[i];
	        if (span.to == null) {
	          var found = getMarkedSpanFor(last, span.marker);
	          if (!found) { span.to = startCh; }
	          else if (sameLine) { span.to = found.to == null ? null : found.to + offset; }
	        }
	      }
	    }
	    if (last) {
	      // Fix up .from in last (or move them into first in case of sameLine)
	      for (var i$1 = 0; i$1 < last.length; ++i$1) {
	        var span$1 = last[i$1];
	        if (span$1.to != null) { span$1.to += offset; }
	        if (span$1.from == null) {
	          var found$1 = getMarkedSpanFor(first, span$1.marker);
	          if (!found$1) {
	            span$1.from = offset;
	            if (sameLine) { (first || (first = [])).push(span$1); }
	          }
	        } else {
	          span$1.from += offset;
	          if (sameLine) { (first || (first = [])).push(span$1); }
	        }
	      }
	    }
	    // Make sure we didn't create any zero-length spans
	    if (first) { first = clearEmptySpans(first); }
	    if (last && last != first) { last = clearEmptySpans(last); }

	    var newMarkers = [first];
	    if (!sameLine) {
	      // Fill gap with whole-line-spans
	      var gap = change.text.length - 2, gapMarkers;
	      if (gap > 0 && first)
	        { for (var i$2 = 0; i$2 < first.length; ++i$2)
	          { if (first[i$2].to == null)
	            { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } }
	      for (var i$3 = 0; i$3 < gap; ++i$3)
	        { newMarkers.push(gapMarkers); }
	      newMarkers.push(last);
	    }
	    return newMarkers
	  }

	  // Remove spans that are empty and don't have a clearWhenEmpty
	  // option of false.
	  function clearEmptySpans(spans) {
	    for (var i = 0; i < spans.length; ++i) {
	      var span = spans[i];
	      if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
	        { spans.splice(i--, 1); }
	    }
	    if (!spans.length) { return null }
	    return spans
	  }

	  // Used to 'clip' out readOnly ranges when making a change.
	  function removeReadOnlyRanges(doc, from, to) {
	    var markers = null;
	    doc.iter(from.line, to.line + 1, function (line) {
	      if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
	        var mark = line.markedSpans[i].marker;
	        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
	          { (markers || (markers = [])).push(mark); }
	      } }
	    });
	    if (!markers) { return null }
	    var parts = [{from: from, to: to}];
	    for (var i = 0; i < markers.length; ++i) {
	      var mk = markers[i], m = mk.find(0);
	      for (var j = 0; j < parts.length; ++j) {
	        var p = parts[j];
	        if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }
	        var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
	        if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
	          { newParts.push({from: p.from, to: m.from}); }
	        if (dto > 0 || !mk.inclusiveRight && !dto)
	          { newParts.push({from: m.to, to: p.to}); }
	        parts.splice.apply(parts, newParts);
	        j += newParts.length - 3;
	      }
	    }
	    return parts
	  }

	  // Connect or disconnect spans from a line.
	  function detachMarkedSpans(line) {
	    var spans = line.markedSpans;
	    if (!spans) { return }
	    for (var i = 0; i < spans.length; ++i)
	      { spans[i].marker.detachLine(line); }
	    line.markedSpans = null;
	  }
	  function attachMarkedSpans(line, spans) {
	    if (!spans) { return }
	    for (var i = 0; i < spans.length; ++i)
	      { spans[i].marker.attachLine(line); }
	    line.markedSpans = spans;
	  }

	  // Helpers used when computing which overlapping collapsed span
	  // counts as the larger one.
	  function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }
	  function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }

	  // Returns a number indicating which of two overlapping collapsed
	  // spans is larger (and thus includes the other). Falls back to
	  // comparing ids when the spans cover exactly the same range.
	  function compareCollapsedMarkers(a, b) {
	    var lenDiff = a.lines.length - b.lines.length;
	    if (lenDiff != 0) { return lenDiff }
	    var aPos = a.find(), bPos = b.find();
	    var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
	    if (fromCmp) { return -fromCmp }
	    var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
	    if (toCmp) { return toCmp }
	    return b.id - a.id
	  }

	  // Find out whether a line ends or starts in a collapsed span. If
	  // so, return the marker for that span.
	  function collapsedSpanAtSide(line, start) {
	    var sps = sawCollapsedSpans && line.markedSpans, found;
	    if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
	      sp = sps[i];
	      if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
	          (!found || compareCollapsedMarkers(found, sp.marker) < 0))
	        { found = sp.marker; }
	    } }
	    return found
	  }
	  function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
	  function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }

	  function collapsedSpanAround(line, ch) {
	    var sps = sawCollapsedSpans && line.markedSpans, found;
	    if (sps) { for (var i = 0; i < sps.length; ++i) {
	      var sp = sps[i];
	      if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) &&
	          (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; }
	    } }
	    return found
	  }

	  // Test whether there exists a collapsed span that partially
	  // overlaps (covers the start or end, but not both) of a new span.
	  // Such overlap is not allowed.
	  function conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) {
	    var line = getLine(doc, lineNo$$1);
	    var sps = sawCollapsedSpans && line.markedSpans;
	    if (sps) { for (var i = 0; i < sps.length; ++i) {
	      var sp = sps[i];
	      if (!sp.marker.collapsed) { continue }
	      var found = sp.marker.find(0);
	      var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
	      var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
	      if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }
	      if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
	          fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
	        { return true }
	    } }
	  }

	  // A visual line is a line as drawn on the screen. Folding, for
	  // example, can cause multiple logical lines to appear on the same
	  // visual line. This finds the start of the visual line that the
	  // given line is part of (usually that is the line itself).
	  function visualLine(line) {
	    var merged;
	    while (merged = collapsedSpanAtStart(line))
	      { line = merged.find(-1, true).line; }
	    return line
	  }

	  function visualLineEnd(line) {
	    var merged;
	    while (merged = collapsedSpanAtEnd(line))
	      { line = merged.find(1, true).line; }
	    return line
	  }

	  // Returns an array of logical lines that continue the visual line
	  // started by the argument, or undefined if there are no such lines.
	  function visualLineContinued(line) {
	    var merged, lines;
	    while (merged = collapsedSpanAtEnd(line)) {
	      line = merged.find(1, true).line
	      ;(lines || (lines = [])).push(line);
	    }
	    return lines
	  }

	  // Get the line number of the start of the visual line that the
	  // given line number is part of.
	  function visualLineNo(doc, lineN) {
	    var line = getLine(doc, lineN), vis = visualLine(line);
	    if (line == vis) { return lineN }
	    return lineNo(vis)
	  }

	  // Get the line number of the start of the next visual line after
	  // the given line.
	  function visualLineEndNo(doc, lineN) {
	    if (lineN > doc.lastLine()) { return lineN }
	    var line = getLine(doc, lineN), merged;
	    if (!lineIsHidden(doc, line)) { return lineN }
	    while (merged = collapsedSpanAtEnd(line))
	      { line = merged.find(1, true).line; }
	    return lineNo(line) + 1
	  }

	  // Compute whether a line is hidden. Lines count as hidden when they
	  // are part of a visual line that starts with another line, or when
	  // they are entirely covered by collapsed, non-widget span.
	  function lineIsHidden(doc, line) {
	    var sps = sawCollapsedSpans && line.markedSpans;
	    if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
	      sp = sps[i];
	      if (!sp.marker.collapsed) { continue }
	      if (sp.from == null) { return true }
	      if (sp.marker.widgetNode) { continue }
	      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
	        { return true }
	    } }
	  }
	  function lineIsHiddenInner(doc, line, span) {
	    if (span.to == null) {
	      var end = span.marker.find(1, true);
	      return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))
	    }
	    if (span.marker.inclusiveRight && span.to == line.text.length)
	      { return true }
	    for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {
	      sp = line.markedSpans[i];
	      if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
	          (sp.to == null || sp.to != span.from) &&
	          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
	          lineIsHiddenInner(doc, line, sp)) { return true }
	    }
	  }

	  // Find the height above the given line.
	  function heightAtLine(lineObj) {
	    lineObj = visualLine(lineObj);

	    var h = 0, chunk = lineObj.parent;
	    for (var i = 0; i < chunk.lines.length; ++i) {
	      var line = chunk.lines[i];
	      if (line == lineObj) { break }
	      else { h += line.height; }
	    }
	    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
	      for (var i$1 = 0; i$1 < p.children.length; ++i$1) {
	        var cur = p.children[i$1];
	        if (cur == chunk) { break }
	        else { h += cur.height; }
	      }
	    }
	    return h
	  }

	  // Compute the character length of a line, taking into account
	  // collapsed ranges (see markText) that might hide parts, and join
	  // other lines onto it.
	  function lineLength(line) {
	    if (line.height == 0) { return 0 }
	    var len = line.text.length, merged, cur = line;
	    while (merged = collapsedSpanAtStart(cur)) {
	      var found = merged.find(0, true);
	      cur = found.from.line;
	      len += found.from.ch - found.to.ch;
	    }
	    cur = line;
	    while (merged = collapsedSpanAtEnd(cur)) {
	      var found$1 = merged.find(0, true);
	      len -= cur.text.length - found$1.from.ch;
	      cur = found$1.to.line;
	      len += cur.text.length - found$1.to.ch;
	    }
	    return len
	  }

	  // Find the longest line in the document.
	  function findMaxLine(cm) {
	    var d = cm.display, doc = cm.doc;
	    d.maxLine = getLine(doc, doc.first);
	    d.maxLineLength = lineLength(d.maxLine);
	    d.maxLineChanged = true;
	    doc.iter(function (line) {
	      var len = lineLength(line);
	      if (len > d.maxLineLength) {
	        d.maxLineLength = len;
	        d.maxLine = line;
	      }
	    });
	  }

	  // BIDI HELPERS

	  function iterateBidiSections(order, from, to, f) {
	    if (!order) { return f(from, to, "ltr", 0) }
	    var found = false;
	    for (var i = 0; i < order.length; ++i) {
	      var part = order[i];
	      if (part.from < to && part.to > from || from == to && part.to == from) {
	        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i);
	        found = true;
	      }
	    }
	    if (!found) { f(from, to, "ltr"); }
	  }

	  var bidiOther = null;
	  function getBidiPartAt(order, ch, sticky) {
	    var found;
	    bidiOther = null;
	    for (var i = 0; i < order.length; ++i) {
	      var cur = order[i];
	      if (cur.from < ch && cur.to > ch) { return i }
	      if (cur.to == ch) {
	        if (cur.from != cur.to && sticky == "before") { found = i; }
	        else { bidiOther = i; }
	      }
	      if (cur.from == ch) {
	        if (cur.from != cur.to && sticky != "before") { found = i; }
	        else { bidiOther = i; }
	      }
	    }
	    return found != null ? found : bidiOther
	  }

	  // Bidirectional ordering algorithm
	  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
	  // that this (partially) implements.

	  // One-char codes used for character types:
	  // L (L):   Left-to-Right
	  // R (R):   Right-to-Left
	  // r (AL):  Right-to-Left Arabic
	  // 1 (EN):  European Number
	  // + (ES):  European Number Separator
	  // % (ET):  European Number Terminator
	  // n (AN):  Arabic Number
	  // , (CS):  Common Number Separator
	  // m (NSM): Non-Spacing Mark
	  // b (BN):  Boundary Neutral
	  // s (B):   Paragraph Separator
	  // t (S):   Segment Separator
	  // w (WS):  Whitespace
	  // N (ON):  Other Neutrals

	  // Returns null if characters are ordered as they appear
	  // (left-to-right), or an array of sections ({from, to, level}
	  // objects) in the order in which they occur visually.
	  var bidiOrdering = (function() {
	    // Character types for codepoints 0 to 0xff
	    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
	    // Character types for codepoints 0x600 to 0x6f9
	    var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";
	    function charType(code) {
	      if (code <= 0xf7) { return lowTypes.charAt(code) }
	      else if (0x590 <= code && code <= 0x5f4) { return "R" }
	      else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }
	      else if (0x6ee <= code && code <= 0x8ac) { return "r" }
	      else if (0x2000 <= code && code <= 0x200b) { return "w" }
	      else if (code == 0x200c) { return "b" }
	      else { return "L" }
	    }

	    var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
	    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;

	    function BidiSpan(level, from, to) {
	      this.level = level;
	      this.from = from; this.to = to;
	    }

	    return function(str, direction) {
	      var outerType = direction == "ltr" ? "L" : "R";

	      if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false }
	      var len = str.length, types = [];
	      for (var i = 0; i < len; ++i)
	        { types.push(charType(str.charCodeAt(i))); }

	      // W1. Examine each non-spacing mark (NSM) in the level run, and
	      // change the type of the NSM to the type of the previous
	      // character. If the NSM is at the start of the level run, it will
	      // get the type of sor.
	      for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {
	        var type = types[i$1];
	        if (type == "m") { types[i$1] = prev; }
	        else { prev = type; }
	      }

	      // W2. Search backwards from each instance of a European number
	      // until the first strong type (R, L, AL, or sor) is found. If an
	      // AL is found, change the type of the European number to Arabic
	      // number.
	      // W3. Change all ALs to R.
	      for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {
	        var type$1 = types[i$2];
	        if (type$1 == "1" && cur == "r") { types[i$2] = "n"; }
	        else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } }
	      }

	      // W4. A single European separator between two European numbers
	      // changes to a European number. A single common separator between
	      // two numbers of the same type changes to that type.
	      for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {
	        var type$2 = types[i$3];
	        if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; }
	        else if (type$2 == "," && prev$1 == types[i$3+1] &&
	                 (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; }
	        prev$1 = type$2;
	      }

	      // W5. A sequence of European terminators adjacent to European
	      // numbers changes to all European numbers.
	      // W6. Otherwise, separators and terminators change to Other
	      // Neutral.
	      for (var i$4 = 0; i$4 < len; ++i$4) {
	        var type$3 = types[i$4];
	        if (type$3 == ",") { types[i$4] = "N"; }
	        else if (type$3 == "%") {
	          var end = (void 0);
	          for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {}
	          var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
	          for (var j = i$4; j < end; ++j) { types[j] = replace; }
	          i$4 = end - 1;
	        }
	      }

	      // W7. Search backwards from each instance of a European number
	      // until the first strong type (R, L, or sor) is found. If an L is
	      // found, then change the type of the European number to L.
	      for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {
	        var type$4 = types[i$5];
	        if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; }
	        else if (isStrong.test(type$4)) { cur$1 = type$4; }
	      }

	      // N1. A sequence of neutrals takes the direction of the
	      // surrounding strong text if the text on both sides has the same
	      // direction. European and Arabic numbers act as if they were R in
	      // terms of their influence on neutrals. Start-of-level-run (sor)
	      // and end-of-level-run (eor) are used at level run boundaries.
	      // N2. Any remaining neutrals take the embedding direction.
	      for (var i$6 = 0; i$6 < len; ++i$6) {
	        if (isNeutral.test(types[i$6])) {
	          var end$1 = (void 0);
	          for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}
	          var before = (i$6 ? types[i$6-1] : outerType) == "L";
	          var after = (end$1 < len ? types[end$1] : outerType) == "L";
	          var replace$1 = before == after ? (before ? "L" : "R") : outerType;
	          for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; }
	          i$6 = end$1 - 1;
	        }
	      }

	      // Here we depart from the documented algorithm, in order to avoid
	      // building up an actual levels array. Since there are only three
	      // levels (0, 1, 2) in an implementation that doesn't take
	      // explicit embedding into account, we can build up the order on
	      // the fly, without following the level-based algorithm.
	      var order = [], m;
	      for (var i$7 = 0; i$7 < len;) {
	        if (countsAsLeft.test(types[i$7])) {
	          var start = i$7;
	          for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}
	          order.push(new BidiSpan(0, start, i$7));
	        } else {
	          var pos = i$7, at = order.length;
	          for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {}
	          for (var j$2 = pos; j$2 < i$7;) {
	            if (countsAsNum.test(types[j$2])) {
	              if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); }
	              var nstart = j$2;
	              for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}
	              order.splice(at, 0, new BidiSpan(2, nstart, j$2));
	              pos = j$2;
	            } else { ++j$2; }
	          }
	          if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); }
	        }
	      }
	      if (direction == "ltr") {
	        if (order[0].level == 1 && (m = str.match(/^\s+/))) {
	          order[0].from = m[0].length;
	          order.unshift(new BidiSpan(0, 0, m[0].length));
	        }
	        if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
	          lst(order).to -= m[0].length;
	          order.push(new BidiSpan(0, len - m[0].length, len));
	        }
	      }

	      return direction == "rtl" ? order.reverse() : order
	    }
	  })();

	  // Get the bidi ordering for the given line (and cache it). Returns
	  // false for lines that are fully left-to-right, and an array of
	  // BidiSpan objects otherwise.
	  function getOrder(line, direction) {
	    var order = line.order;
	    if (order == null) { order = line.order = bidiOrdering(line.text, direction); }
	    return order
	  }

	  // EVENT HANDLING

	  // Lightweight event framework. on/off also work on DOM nodes,
	  // registering native DOM handlers.

	  var noHandlers = [];

	  var on = function(emitter, type, f) {
	    if (emitter.addEventListener) {
	      emitter.addEventListener(type, f, false);
	    } else if (emitter.attachEvent) {
	      emitter.attachEvent("on" + type, f);
	    } else {
	      var map$$1 = emitter._handlers || (emitter._handlers = {});
	      map$$1[type] = (map$$1[type] || noHandlers).concat(f);
	    }
	  };

	  function getHandlers(emitter, type) {
	    return emitter._handlers && emitter._handlers[type] || noHandlers
	  }

	  function off(emitter, type, f) {
	    if (emitter.removeEventListener) {
	      emitter.removeEventListener(type, f, false);
	    } else if (emitter.detachEvent) {
	      emitter.detachEvent("on" + type, f);
	    } else {
	      var map$$1 = emitter._handlers, arr = map$$1 && map$$1[type];
	      if (arr) {
	        var index = indexOf(arr, f);
	        if (index > -1)
	          { map$$1[type] = arr.slice(0, index).concat(arr.slice(index + 1)); }
	      }
	    }
	  }

	  function signal(emitter, type /*, values...*/) {
	    var handlers = getHandlers(emitter, type);
	    if (!handlers.length) { return }
	    var args = Array.prototype.slice.call(arguments, 2);
	    for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); }
	  }

	  // The DOM events that CodeMirror handles can be overridden by
	  // registering a (non-DOM) handler on the editor for the event name,
	  // and preventDefault-ing the event in that handler.
	  function signalDOMEvent(cm, e, override) {
	    if (typeof e == "string")
	      { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; }
	    signal(cm, override || e.type, cm, e);
	    return e_defaultPrevented(e) || e.codemirrorIgnore
	  }

	  function signalCursorActivity(cm) {
	    var arr = cm._handlers && cm._handlers.cursorActivity;
	    if (!arr) { return }
	    var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
	    for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)
	      { set.push(arr[i]); } }
	  }

	  function hasHandler(emitter, type) {
	    return getHandlers(emitter, type).length > 0
	  }

	  // Add on and off methods to a constructor's prototype, to make
	  // registering events on such objects more convenient.
	  function eventMixin(ctor) {
	    ctor.prototype.on = function(type, f) {on(this, type, f);};
	    ctor.prototype.off = function(type, f) {off(this, type, f);};
	  }

	  // Due to the fact that we still support jurassic IE versions, some
	  // compatibility wrappers are needed.

	  function e_preventDefault(e) {
	    if (e.preventDefault) { e.preventDefault(); }
	    else { e.returnValue = false; }
	  }
	  function e_stopPropagation(e) {
	    if (e.stopPropagation) { e.stopPropagation(); }
	    else { e.cancelBubble = true; }
	  }
	  function e_defaultPrevented(e) {
	    return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
	  }
	  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}

	  function e_target(e) {return e.target || e.srcElement}
	  function e_button(e) {
	    var b = e.which;
	    if (b == null) {
	      if (e.button & 1) { b = 1; }
	      else if (e.button & 2) { b = 3; }
	      else if (e.button & 4) { b = 2; }
	    }
	    if (mac && e.ctrlKey && b == 1) { b = 3; }
	    return b
	  }

	  // Detect drag-and-drop
	  var dragAndDrop = function() {
	    // There is *some* kind of drag-and-drop support in IE6-8, but I
	    // couldn't get it to work yet.
	    if (ie && ie_version < 9) { return false }
	    var div = elt('div');
	    return "draggable" in div || "dragDrop" in div
	  }();

	  var zwspSupported;
	  function zeroWidthElement(measure) {
	    if (zwspSupported == null) {
	      var test = elt("span", "\u200b");
	      removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
	      if (measure.firstChild.offsetHeight != 0)
	        { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); }
	    }
	    var node = zwspSupported ? elt("span", "\u200b") :
	      elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
	    node.setAttribute("cm-text", "");
	    return node
	  }

	  // Feature-detect IE's crummy client rect reporting for bidi text
	  var badBidiRects;
	  function hasBadBidiRects(measure) {
	    if (badBidiRects != null) { return badBidiRects }
	    var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
	    var r0 = range(txt, 0, 1).getBoundingClientRect();
	    var r1 = range(txt, 1, 2).getBoundingClientRect();
	    removeChildren(measure);
	    if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)
	    return badBidiRects = (r1.right - r0.right < 3)
	  }

	  // See if "".split is the broken IE version, if so, provide an
	  // alternative way to split lines.
	  var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) {
	    var pos = 0, result = [], l = string.length;
	    while (pos <= l) {
	      var nl = string.indexOf("\n", pos);
	      if (nl == -1) { nl = string.length; }
	      var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
	      var rt = line.indexOf("\r");
	      if (rt != -1) {
	        result.push(line.slice(0, rt));
	        pos += rt + 1;
	      } else {
	        result.push(line);
	        pos = nl + 1;
	      }
	    }
	    return result
	  } : function (string) { return string.split(/\r\n?|\n/); };

	  var hasSelection = window.getSelection ? function (te) {
	    try { return te.selectionStart != te.selectionEnd }
	    catch(e) { return false }
	  } : function (te) {
	    var range$$1;
	    try {range$$1 = te.ownerDocument.selection.createRange();}
	    catch(e) {}
	    if (!range$$1 || range$$1.parentElement() != te) { return false }
	    return range$$1.compareEndPoints("StartToEnd", range$$1) != 0
	  };

	  var hasCopyEvent = (function () {
	    var e = elt("div");
	    if ("oncopy" in e) { return true }
	    e.setAttribute("oncopy", "return;");
	    return typeof e.oncopy == "function"
	  })();

	  var badZoomedRects = null;
	  function hasBadZoomedRects(measure) {
	    if (badZoomedRects != null) { return badZoomedRects }
	    var node = removeChildrenAndAdd(measure, elt("span", "x"));
	    var normal = node.getBoundingClientRect();
	    var fromRange = range(node, 0, 1).getBoundingClientRect();
	    return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
	  }

	  // Known modes, by name and by MIME
	  var modes = {}, mimeModes = {};

	  // Extra arguments are stored as the mode's dependencies, which is
	  // used by (legacy) mechanisms like loadmode.js to automatically
	  // load a mode. (Preferred mechanism is the require/define calls.)
	  function defineMode(name, mode) {
	    if (arguments.length > 2)
	      { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
	    modes[name] = mode;
	  }

	  function defineMIME(mime, spec) {
	    mimeModes[mime] = spec;
	  }

	  // Given a MIME type, a {name, ...options} config object, or a name
	  // string, return a mode config object.
	  function resolveMode(spec) {
	    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
	      spec = mimeModes[spec];
	    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
	      var found = mimeModes[spec.name];
	      if (typeof found == "string") { found = {name: found}; }
	      spec = createObj(found, spec);
	      spec.name = found.name;
	    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
	      return resolveMode("application/xml")
	    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
	      return resolveMode("application/json")
	    }
	    if (typeof spec == "string") { return {name: spec} }
	    else { return spec || {name: "null"} }
	  }

	  // Given a mode spec (anything that resolveMode accepts), find and
	  // initialize an actual mode object.
	  function getMode(options, spec) {
	    spec = resolveMode(spec);
	    var mfactory = modes[spec.name];
	    if (!mfactory) { return getMode(options, "text/plain") }
	    var modeObj = mfactory(options, spec);
	    if (modeExtensions.hasOwnProperty(spec.name)) {
	      var exts = modeExtensions[spec.name];
	      for (var prop in exts) {
	        if (!exts.hasOwnProperty(prop)) { continue }
	        if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
	        modeObj[prop] = exts[prop];
	      }
	    }
	    modeObj.name = spec.name;
	    if (spec.helperType) { modeObj.helperType = spec.helperType; }
	    if (spec.modeProps) { for (var prop$1 in spec.modeProps)
	      { modeObj[prop$1] = spec.modeProps[prop$1]; } }

	    return modeObj
	  }

	  // This can be used to attach properties to mode objects from
	  // outside the actual mode definition.
	  var modeExtensions = {};
	  function extendMode(mode, properties) {
	    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
	    copyObj(properties, exts);
	  }

	  function copyState(mode, state) {
	    if (state === true) { return state }
	    if (mode.copyState) { return mode.copyState(state) }
	    var nstate = {};
	    for (var n in state) {
	      var val = state[n];
	      if (val instanceof Array) { val = val.concat([]); }
	      nstate[n] = val;
	    }
	    return nstate
	  }

	  // Given a mode and a state (for that mode), find the inner mode and
	  // state at the position that the state refers to.
	  function innerMode(mode, state) {
	    var info;
	    while (mode.innerMode) {
	      info = mode.innerMode(state);
	      if (!info || info.mode == mode) { break }
	      state = info.state;
	      mode = info.mode;
	    }
	    return info || {mode: mode, state: state}
	  }

	  function startState(mode, a1, a2) {
	    return mode.startState ? mode.startState(a1, a2) : true
	  }

	  // STRING STREAM

	  // Fed to the mode parsers, provides helper functions to make
	  // parsers more succinct.

	  var StringStream = function(string, tabSize, lineOracle) {
	    this.pos = this.start = 0;
	    this.string = string;
	    this.tabSize = tabSize || 8;
	    this.lastColumnPos = this.lastColumnValue = 0;
	    this.lineStart = 0;
	    this.lineOracle = lineOracle;
	  };

	  StringStream.prototype.eol = function () {return this.pos >= this.string.length};
	  StringStream.prototype.sol = function () {return this.pos == this.lineStart};
	  StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
	  StringStream.prototype.next = function () {
	    if (this.pos < this.string.length)
	      { return this.string.charAt(this.pos++) }
	  };
	  StringStream.prototype.eat = function (match) {
	    var ch = this.string.charAt(this.pos);
	    var ok;
	    if (typeof match == "string") { ok = ch == match; }
	    else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
	    if (ok) {++this.pos; return ch}
	  };
	  StringStream.prototype.eatWhile = function (match) {
	    var start = this.pos;
	    while (this.eat(match)){}
	    return this.pos > start
	  };
	  StringStream.prototype.eatSpace = function () {
	      var this$1 = this;

	    var start = this.pos;
	    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos; }
	    return this.pos > start
	  };
	  StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
	  StringStream.prototype.skipTo = function (ch) {
	    var found = this.string.indexOf(ch, this.pos);
	    if (found > -1) {this.pos = found; return true}
	  };
	  StringStream.prototype.backUp = function (n) {this.pos -= n;};
	  StringStream.prototype.column = function () {
	    if (this.lastColumnPos < this.start) {
	      this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
	      this.lastColumnPos = this.start;
	    }
	    return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
	  };
	  StringStream.prototype.indentation = function () {
	    return countColumn(this.string, null, this.tabSize) -
	      (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
	  };
	  StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
	    if (typeof pattern == "string") {
	      var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
	      var substr = this.string.substr(this.pos, pattern.length);
	      if (cased(substr) == cased(pattern)) {
	        if (consume !== false) { this.pos += pattern.length; }
	        return true
	      }
	    } else {
	      var match = this.string.slice(this.pos).match(pattern);
	      if (match && match.index > 0) { return null }
	      if (match && consume !== false) { this.pos += match[0].length; }
	      return match
	    }
	  };
	  StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
	  StringStream.prototype.hideFirstChars = function (n, inner) {
	    this.lineStart += n;
	    try { return inner() }
	    finally { this.lineStart -= n; }
	  };
	  StringStream.prototype.lookAhead = function (n) {
	    var oracle = this.lineOracle;
	    return oracle && oracle.lookAhead(n)
	  };
	  StringStream.prototype.baseToken = function () {
	    var oracle = this.lineOracle;
	    return oracle && oracle.baseToken(this.pos)
	  };

	  var SavedContext = function(state, lookAhead) {
	    this.state = state;
	    this.lookAhead = lookAhead;
	  };

	  var Context = function(doc, state, line, lookAhead) {
	    this.state = state;
	    this.doc = doc;
	    this.line = line;
	    this.maxLookAhead = lookAhead || 0;
	    this.baseTokens = null;
	    this.baseTokenPos = 1;
	  };

	  Context.prototype.lookAhead = function (n) {
	    var line = this.doc.getLine(this.line + n);
	    if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; }
	    return line
	  };

	  Context.prototype.baseToken = function (n) {
	      var this$1 = this;

	    if (!this.baseTokens) { return null }
	    while (this.baseTokens[this.baseTokenPos] <= n)
	      { this$1.baseTokenPos += 2; }
	    var type = this.baseTokens[this.baseTokenPos + 1];
	    return {type: type && type.replace(/( |^)overlay .*/, ""),
	            size: this.baseTokens[this.baseTokenPos] - n}
	  };

	  Context.prototype.nextLine = function () {
	    this.line++;
	    if (this.maxLookAhead > 0) { this.maxLookAhead--; }
	  };

	  Context.fromSaved = function (doc, saved, line) {
	    if (saved instanceof SavedContext)
	      { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) }
	    else
	      { return new Context(doc, copyState(doc.mode, saved), line) }
	  };

	  Context.prototype.save = function (copy) {
	    var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state;
	    return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state
	  };


	  // Compute a style array (an array starting with a mode generation
	  // -- for invalidation -- followed by pairs of end positions and
	  // style strings), which is used to highlight the tokens on the
	  // line.
	  function highlightLine(cm, line, context, forceToEnd) {
	    // A styles array always starts with a number identifying the
	    // mode/overlays that it is based on (for easy invalidation).
	    var st = [cm.state.modeGen], lineClasses = {};
	    // Compute the base array of styles
	    runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); },
	            lineClasses, forceToEnd);
	    var state = context.state;

	    // Run overlays, adjust style array.
	    var loop = function ( o ) {
	      context.baseTokens = st;
	      var overlay = cm.state.overlays[o], i = 1, at = 0;
	      context.state = true;
	      runMode(cm, line.text, overlay.mode, context, function (end, style) {
	        var start = i;
	        // Ensure there's a token end at the current position, and that i points at it
	        while (at < end) {
	          var i_end = st[i];
	          if (i_end > end)
	            { st.splice(i, 1, end, st[i+1], i_end); }
	          i += 2;
	          at = Math.min(end, i_end);
	        }
	        if (!style) { return }
	        if (overlay.opaque) {
	          st.splice(start, i - start, end, "overlay " + style);
	          i = start + 2;
	        } else {
	          for (; start < i; start += 2) {
	            var cur = st[start+1];
	            st[start+1] = (cur ? cur + " " : "") + "overlay " + style;
	          }
	        }
	      }, lineClasses);
	      context.state = state;
	      context.baseTokens = null;
	      context.baseTokenPos = 1;
	    };

	    for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );

	    return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}
	  }

	  function getLineStyles(cm, line, updateFrontier) {
	    if (!line.styles || line.styles[0] != cm.state.modeGen) {
	      var context = getContextBefore(cm, lineNo(line));
	      var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state);
	      var result = highlightLine(cm, line, context);
	      if (resetState) { context.state = resetState; }
	      line.stateAfter = context.save(!resetState);
	      line.styles = result.styles;
	      if (result.classes) { line.styleClasses = result.classes; }
	      else if (line.styleClasses) { line.styleClasses = null; }
	      if (updateFrontier === cm.doc.highlightFrontier)
	        { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); }
	    }
	    return line.styles
	  }

	  function getContextBefore(cm, n, precise) {
	    var doc = cm.doc, display = cm.display;
	    if (!doc.mode.startState) { return new Context(doc, true, n) }
	    var start = findStartLine(cm, n, precise);
	    var saved = start > doc.first && getLine(doc, start - 1).stateAfter;
	    var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start);

	    doc.iter(start, n, function (line) {
	      processLine(cm, line.text, context);
	      var pos = context.line;
	      line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null;
	      context.nextLine();
	    });
	    if (precise) { doc.modeFrontier = context.line; }
	    return context
	  }

	  // Lightweight form of highlight -- proceed over this line and
	  // update state, but don't save a style array. Used for lines that
	  // aren't currently visible.
	  function processLine(cm, text, context, startAt) {
	    var mode = cm.doc.mode;
	    var stream = new StringStream(text, cm.options.tabSize, context);
	    stream.start = stream.pos = startAt || 0;
	    if (text == "") { callBlankLine(mode, context.state); }
	    while (!stream.eol()) {
	      readToken(mode, stream, context.state);
	      stream.start = stream.pos;
	    }
	  }

	  function callBlankLine(mode, state) {
	    if (mode.blankLine) { return mode.blankLine(state) }
	    if (!mode.innerMode) { return }
	    var inner = innerMode(mode, state);
	    if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }
	  }

	  function readToken(mode, stream, state, inner) {
	    for (var i = 0; i < 10; i++) {
	      if (inner) { inner[0] = innerMode(mode, state).mode; }
	      var style = mode.token(stream, state);
	      if (stream.pos > stream.start) { return style }
	    }
	    throw new Error("Mode " + mode.name + " failed to advance stream.")
	  }

	  var Token = function(stream, type, state) {
	    this.start = stream.start; this.end = stream.pos;
	    this.string = stream.current();
	    this.type = type || null;
	    this.state = state;
	  };

	  // Utility for getTokenAt and getLineTokens
	  function takeToken(cm, pos, precise, asArray) {
	    var doc = cm.doc, mode = doc.mode, style;
	    pos = clipPos(doc, pos);
	    var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise);
	    var stream = new StringStream(line.text, cm.options.tabSize, context), tokens;
	    if (asArray) { tokens = []; }
	    while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
	      stream.start = stream.pos;
	      style = readToken(mode, stream, context.state);
	      if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); }
	    }
	    return asArray ? tokens : new Token(stream, style, context.state)
	  }

	  function extractLineClasses(type, output) {
	    if (type) { for (;;) {
	      var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
	      if (!lineClass) { break }
	      type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
	      var prop = lineClass[1] ? "bgClass" : "textClass";
	      if (output[prop] == null)
	        { output[prop] = lineClass[2]; }
	      else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
	        { output[prop] += " " + lineClass[2]; }
	    } }
	    return type
	  }

	  // Run the given mode's parser over a line, calling f for each token.
	  function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) {
	    var flattenSpans = mode.flattenSpans;
	    if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; }
	    var curStart = 0, curStyle = null;
	    var stream = new StringStream(text, cm.options.tabSize, context), style;
	    var inner = cm.options.addModeClass && [null];
	    if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); }
	    while (!stream.eol()) {
	      if (stream.pos > cm.options.maxHighlightLength) {
	        flattenSpans = false;
	        if (forceToEnd) { processLine(cm, text, context, stream.pos); }
	        stream.pos = text.length;
	        style = null;
	      } else {
	        style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses);
	      }
	      if (inner) {
	        var mName = inner[0].name;
	        if (mName) { style = "m-" + (style ? mName + " " + style : mName); }
	      }
	      if (!flattenSpans || curStyle != style) {
	        while (curStart < stream.start) {
	          curStart = Math.min(stream.start, curStart + 5000);
	          f(curStart, curStyle);
	        }
	        curStyle = style;
	      }
	      stream.start = stream.pos;
	    }
	    while (curStart < stream.pos) {
	      // Webkit seems to refuse to render text nodes longer than 57444
	      // characters, and returns inaccurate measurements in nodes
	      // starting around 5000 chars.
	      var pos = Math.min(stream.pos, curStart + 5000);
	      f(pos, curStyle);
	      curStart = pos;
	    }
	  }

	  // Finds the line to start with when starting a parse. Tries to
	  // find a line with a stateAfter, so that it can start with a
	  // valid state. If that fails, it returns the line with the
	  // smallest indentation, which tends to need the least context to
	  // parse correctly.
	  function findStartLine(cm, n, precise) {
	    var minindent, minline, doc = cm.doc;
	    var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
	    for (var search = n; search > lim; --search) {
	      if (search <= doc.first) { return doc.first }
	      var line = getLine(doc, search - 1), after = line.stateAfter;
	      if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier))
	        { return search }
	      var indented = countColumn(line.text, null, cm.options.tabSize);
	      if (minline == null || minindent > indented) {
	        minline = search - 1;
	        minindent = indented;
	      }
	    }
	    return minline
	  }

	  function retreatFrontier(doc, n) {
	    doc.modeFrontier = Math.min(doc.modeFrontier, n);
	    if (doc.highlightFrontier < n - 10) { return }
	    var start = doc.first;
	    for (var line = n - 1; line > start; line--) {
	      var saved = getLine(doc, line).stateAfter;
	      // change is on 3
	      // state on line 1 looked ahead 2 -- so saw 3
	      // test 1 + 2 < 3 should cover this
	      if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) {
	        start = line + 1;
	        break
	      }
	    }
	    doc.highlightFrontier = Math.min(doc.highlightFrontier, start);
	  }

	  // LINE DATA STRUCTURE

	  // Line objects. These hold state related to a line, including
	  // highlighting info (the styles array).
	  var Line = function(text, markedSpans, estimateHeight) {
	    this.text = text;
	    attachMarkedSpans(this, markedSpans);
	    this.height = estimateHeight ? estimateHeight(this) : 1;
	  };

	  Line.prototype.lineNo = function () { return lineNo(this) };
	  eventMixin(Line);

	  // Change the content (text, markers) of a line. Automatically
	  // invalidates cached information and tries to re-estimate the
	  // line's height.
	  function updateLine(line, text, markedSpans, estimateHeight) {
	    line.text = text;
	    if (line.stateAfter) { line.stateAfter = null; }
	    if (line.styles) { line.styles = null; }
	    if (line.order != null) { line.order = null; }
	    detachMarkedSpans(line);
	    attachMarkedSpans(line, markedSpans);
	    var estHeight = estimateHeight ? estimateHeight(line) : 1;
	    if (estHeight != line.height) { updateLineHeight(line, estHeight); }
	  }

	  // Detach a line from the document tree and its markers.
	  function cleanUpLine(line) {
	    line.parent = null;
	    detachMarkedSpans(line);
	  }

	  // Convert a style as returned by a mode (either null, or a string
	  // containing one or more styles) to a CSS style. This is cached,
	  // and also looks for line-wide styles.
	  var styleToClassCache = {}, styleToClassCacheWithMode = {};
	  function interpretTokenStyle(style, options) {
	    if (!style || /^\s*$/.test(style)) { return null }
	    var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
	    return cache[style] ||
	      (cache[style] = style.replace(/\S+/g, "cm-$&"))
	  }

	  // Render the DOM representation of the text of a line. Also builds
	  // up a 'line map', which points at the DOM nodes that represent
	  // specific stretches of text, and is used by the measuring code.
	  // The returned object contains the DOM node, this map, and
	  // information about line-wide styles that were set by the mode.
	  function buildLineContent(cm, lineView) {
	    // The padding-right forces the element to have a 'border', which
	    // is needed on Webkit to be able to get line-level bounding
	    // rectangles for it (in measureChar).
	    var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null);
	    var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content,
	                   col: 0, pos: 0, cm: cm,
	                   trailingSpace: false,
	                   splitSpaces: cm.getOption("lineWrapping")};
	    lineView.measure = {};

	    // Iterate over the logical lines that make up this visual line.
	    for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
	      var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0);
	      builder.pos = 0;
	      builder.addToken = buildToken;
	      // Optionally wire in some hacks into the token-rendering
	      // algorithm, to deal with browser quirks.
	      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction)))
	        { builder.addToken = buildTokenBadBidi(builder.addToken, order); }
	      builder.map = [];
	      var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
	      insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
	      if (line.styleClasses) {
	        if (line.styleClasses.bgClass)
	          { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); }
	        if (line.styleClasses.textClass)
	          { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); }
	      }

	      // Ensure at least a single node is present, for measuring.
	      if (builder.map.length == 0)
	        { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); }

	      // Store the map and a cache object for the current logical line
	      if (i == 0) {
	        lineView.measure.map = builder.map;
	        lineView.measure.cache = {};
	      } else {
	  (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)
	        ;(lineView.measure.caches || (lineView.measure.caches = [])).push({});
	      }
	    }

	    // See issue #2901
	    if (webkit) {
	      var last = builder.content.lastChild;
	      if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
	        { builder.content.className = "cm-tab-wrap-hack"; }
	    }

	    signal(cm, "renderLine", cm, lineView.line, builder.pre);
	    if (builder.pre.className)
	      { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); }

	    return builder
	  }

	  function defaultSpecialCharPlaceholder(ch) {
	    var token = elt("span", "\u2022", "cm-invalidchar");
	    token.title = "\\u" + ch.charCodeAt(0).toString(16);
	    token.setAttribute("aria-label", token.title);
	    return token
	  }

	  // Build up the DOM representation for a single token, and add it to
	  // the line map. Takes care to render special characters separately.
	  function buildToken(builder, text, style, startStyle, endStyle, css, attributes) {
	    if (!text) { return }
	    var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text;
	    var special = builder.cm.state.specialChars, mustWrap = false;
	    var content;
	    if (!special.test(text)) {
	      builder.col += text.length;
	      content = document.createTextNode(displayText);
	      builder.map.push(builder.pos, builder.pos + text.length, content);
	      if (ie && ie_version < 9) { mustWrap = true; }
	      builder.pos += text.length;
	    } else {
	      content = document.createDocumentFragment();
	      var pos = 0;
	      while (true) {
	        special.lastIndex = pos;
	        var m = special.exec(text);
	        var skipped = m ? m.index - pos : text.length - pos;
	        if (skipped) {
	          var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
	          if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); }
	          else { content.appendChild(txt); }
	          builder.map.push(builder.pos, builder.pos + skipped, txt);
	          builder.col += skipped;
	          builder.pos += skipped;
	        }
	        if (!m) { break }
	        pos += skipped + 1;
	        var txt$1 = (void 0);
	        if (m[0] == "\t") {
	          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
	          txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
	          txt$1.setAttribute("role", "presentation");
	          txt$1.setAttribute("cm-text", "\t");
	          builder.col += tabWidth;
	        } else if (m[0] == "\r" || m[0] == "\n") {
	          txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
	          txt$1.setAttribute("cm-text", m[0]);
	          builder.col += 1;
	        } else {
	          txt$1 = builder.cm.options.specialCharPlaceholder(m[0]);
	          txt$1.setAttribute("cm-text", m[0]);
	          if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); }
	          else { content.appendChild(txt$1); }
	          builder.col += 1;
	        }
	        builder.map.push(builder.pos, builder.pos + 1, txt$1);
	        builder.pos++;
	      }
	    }
	    builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;
	    if (style || startStyle || endStyle || mustWrap || css) {
	      var fullStyle = style || "";
	      if (startStyle) { fullStyle += startStyle; }
	      if (endStyle) { fullStyle += endStyle; }
	      var token = elt("span", [content], fullStyle, css);
	      if (attributes) {
	        for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class")
	          { token.setAttribute(attr, attributes[attr]); } }
	      }
	      return builder.content.appendChild(token)
	    }
	    builder.content.appendChild(content);
	  }

	  // Change some spaces to NBSP to prevent the browser from collapsing
	  // trailing spaces at the end of a line when rendering text (issue #1362).
	  function splitSpaces(text, trailingBefore) {
	    if (text.length > 1 && !/  /.test(text)) { return text }
	    var spaceBefore = trailingBefore, result = "";
	    for (var i = 0; i < text.length; i++) {
	      var ch = text.charAt(i);
	      if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
	        { ch = "\u00a0"; }
	      result += ch;
	      spaceBefore = ch == " ";
	    }
	    return result
	  }

	  // Work around nonsense dimensions being reported for stretches of
	  // right-to-left text.
	  function buildTokenBadBidi(inner, order) {
	    return function (builder, text, style, startStyle, endStyle, css, attributes) {
	      style = style ? style + " cm-force-border" : "cm-force-border";
	      var start = builder.pos, end = start + text.length;
	      for (;;) {
	        // Find the part that overlaps with the start of this text
	        var part = (void 0);
	        for (var i = 0; i < order.length; i++) {
	          part = order[i];
	          if (part.to > start && part.from <= start) { break }
	        }
	        if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) }
	        inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes);
	        startStyle = null;
	        text = text.slice(part.to - start);
	        start = part.to;
	      }
	    }
	  }

	  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
	    var widget = !ignoreWidget && marker.widgetNode;
	    if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); }
	    if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
	      if (!widget)
	        { widget = builder.content.appendChild(document.createElement("span")); }
	      widget.setAttribute("cm-marker", marker.id);
	    }
	    if (widget) {
	      builder.cm.display.input.setUneditable(widget);
	      builder.content.appendChild(widget);
	    }
	    builder.pos += size;
	    builder.trailingSpace = false;
	  }

	  // Outputs a number of spans to make up a line, taking highlighting
	  // and marked text into account.
	  function insertLineContent(line, builder, styles) {
	    var spans = line.markedSpans, allText = line.text, at = 0;
	    if (!spans) {
	      for (var i$1 = 1; i$1 < styles.length; i$1+=2)
	        { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); }
	      return
	    }

	    var len = allText.length, pos = 0, i = 1, text = "", style, css;
	    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes;
	    for (;;) {
	      if (nextChange == pos) { // Update current marker set
	        spanStyle = spanEndStyle = spanStartStyle = css = "";
	        attributes = null;
	        collapsed = null; nextChange = Infinity;
	        var foundBookmarks = [], endStyles = (void 0);
	        for (var j = 0; j < spans.length; ++j) {
	          var sp = spans[j], m = sp.marker;
	          if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
	            foundBookmarks.push(m);
	          } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
	            if (sp.to != null && sp.to != pos && nextChange > sp.to) {
	              nextChange = sp.to;
	              spanEndStyle = "";
	            }
	            if (m.className) { spanStyle += " " + m.className; }
	            if (m.css) { css = (css ? css + ";" : "") + m.css; }
	            if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; }
	            if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); }
	            // support for the old title property
	            // https://github.com/codemirror/CodeMirror/pull/5673
	            if (m.title) { (attributes || (attributes = {})).title = m.title; }
	            if (m.attributes) {
	              for (var attr in m.attributes)
	                { (attributes || (attributes = {}))[attr] = m.attributes[attr]; }
	            }
	            if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
	              { collapsed = sp; }
	          } else if (sp.from > pos && nextChange > sp.from) {
	            nextChange = sp.from;
	          }
	        }
	        if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)
	          { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } }

	        if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)
	          { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } }
	        if (collapsed && (collapsed.from || 0) == pos) {
	          buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
	                             collapsed.marker, collapsed.from == null);
	          if (collapsed.to == null) { return }
	          if (collapsed.to == pos) { collapsed = false; }
	        }
	      }
	      if (pos >= len) { break }

	      var upto = Math.min(len, nextChange);
	      while (true) {
	        if (text) {
	          var end = pos + text.length;
	          if (!collapsed) {
	            var tokenText = end > upto ? text.slice(0, upto - pos) : text;
	            builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
	                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes);
	          }
	          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
	          pos = end;
	          spanStartStyle = "";
	        }
	        text = allText.slice(at, at = styles[i++]);
	        style = interpretTokenStyle(styles[i++], builder.cm.options);
	      }
	    }
	  }


	  // These objects are used to represent the visible (currently drawn)
	  // part of the document. A LineView may correspond to multiple
	  // logical lines, if those are connected by collapsed ranges.
	  function LineView(doc, line, lineN) {
	    // The starting line
	    this.line = line;
	    // Continuing lines, if any
	    this.rest = visualLineContinued(line);
	    // Number of logical lines in this visual line
	    this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
	    this.node = this.text = null;
	    this.hidden = lineIsHidden(doc, line);
	  }

	  // Create a range of LineView objects for the given lines.
	  function buildViewArray(cm, from, to) {
	    var array = [], nextPos;
	    for (var pos = from; pos < to; pos = nextPos) {
	      var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
	      nextPos = pos + view.size;
	      array.push(view);
	    }
	    return array
	  }

	  var operationGroup = null;

	  function pushOperation(op) {
	    if (operationGroup) {
	      operationGroup.ops.push(op);
	    } else {
	      op.ownsGroup = operationGroup = {
	        ops: [op],
	        delayedCallbacks: []
	      };
	    }
	  }

	  function fireCallbacksForOps(group) {
	    // Calls delayed callbacks and cursorActivity handlers until no
	    // new ones appear
	    var callbacks = group.delayedCallbacks, i = 0;
	    do {
	      for (; i < callbacks.length; i++)
	        { callbacks[i].call(null); }
	      for (var j = 0; j < group.ops.length; j++) {
	        var op = group.ops[j];
	        if (op.cursorActivityHandlers)
	          { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
	            { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } }
	      }
	    } while (i < callbacks.length)
	  }

	  function finishOperation(op, endCb) {
	    var group = op.ownsGroup;
	    if (!group) { return }

	    try { fireCallbacksForOps(group); }
	    finally {
	      operationGroup = null;
	      endCb(group);
	    }
	  }

	  var orphanDelayedCallbacks = null;

	  // Often, we want to signal events at a point where we are in the
	  // middle of some work, but don't want the handler to start calling
	  // other methods on the editor, which might be in an inconsistent
	  // state or simply not expect any other events to happen.
	  // signalLater looks whether there are any handlers, and schedules
	  // them to be executed when the last operation ends, or, if no
	  // operation is active, when a timeout fires.
	  function signalLater(emitter, type /*, values...*/) {
	    var arr = getHandlers(emitter, type);
	    if (!arr.length) { return }
	    var args = Array.prototype.slice.call(arguments, 2), list;
	    if (operationGroup) {
	      list = operationGroup.delayedCallbacks;
	    } else if (orphanDelayedCallbacks) {
	      list = orphanDelayedCallbacks;
	    } else {
	      list = orphanDelayedCallbacks = [];
	      setTimeout(fireOrphanDelayed, 0);
	    }
	    var loop = function ( i ) {
	      list.push(function () { return arr[i].apply(null, args); });
	    };

	    for (var i = 0; i < arr.length; ++i)
	      loop( i );
	  }

	  function fireOrphanDelayed() {
	    var delayed = orphanDelayedCallbacks;
	    orphanDelayedCallbacks = null;
	    for (var i = 0; i < delayed.length; ++i) { delayed[i](); }
	  }

	  // When an aspect of a line changes, a string is added to
	  // lineView.changes. This updates the relevant part of the line's
	  // DOM structure.
	  function updateLineForChanges(cm, lineView, lineN, dims) {
	    for (var j = 0; j < lineView.changes.length; j++) {
	      var type = lineView.changes[j];
	      if (type == "text") { updateLineText(cm, lineView); }
	      else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); }
	      else if (type == "class") { updateLineClasses(cm, lineView); }
	      else if (type == "widget") { updateLineWidgets(cm, lineView, dims); }
	    }
	    lineView.changes = null;
	  }

	  // Lines with gutter elements, widgets or a background class need to
	  // be wrapped, and have the extra elements added to the wrapper div
	  function ensureLineWrapped(lineView) {
	    if (lineView.node == lineView.text) {
	      lineView.node = elt("div", null, null, "position: relative");
	      if (lineView.text.parentNode)
	        { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); }
	      lineView.node.appendChild(lineView.text);
	      if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; }
	    }
	    return lineView.node
	  }

	  function updateLineBackground(cm, lineView) {
	    var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
	    if (cls) { cls += " CodeMirror-linebackground"; }
	    if (lineView.background) {
	      if (cls) { lineView.background.className = cls; }
	      else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
	    } else if (cls) {
	      var wrap = ensureLineWrapped(lineView);
	      lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
	      cm.display.input.setUneditable(lineView.background);
	    }
	  }

	  // Wrapper around buildLineContent which will reuse the structure
	  // in display.externalMeasured when possible.
	  function getLineContent(cm, lineView) {
	    var ext = cm.display.externalMeasured;
	    if (ext && ext.line == lineView.line) {
	      cm.display.externalMeasured = null;
	      lineView.measure = ext.measure;
	      return ext.built
	    }
	    return buildLineContent(cm, lineView)
	  }

	  // Redraw the line's text. Interacts with the background and text
	  // classes because the mode may output tokens that influence these
	  // classes.
	  function updateLineText(cm, lineView) {
	    var cls = lineView.text.className;
	    var built = getLineContent(cm, lineView);
	    if (lineView.text == lineView.node) { lineView.node = built.pre; }
	    lineView.text.parentNode.replaceChild(built.pre, lineView.text);
	    lineView.text = built.pre;
	    if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
	      lineView.bgClass = built.bgClass;
	      lineView.textClass = built.textClass;
	      updateLineClasses(cm, lineView);
	    } else if (cls) {
	      lineView.text.className = cls;
	    }
	  }

	  function updateLineClasses(cm, lineView) {
	    updateLineBackground(cm, lineView);
	    if (lineView.line.wrapClass)
	      { ensureLineWrapped(lineView).className = lineView.line.wrapClass; }
	    else if (lineView.node != lineView.text)
	      { lineView.node.className = ""; }
	    var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
	    lineView.text.className = textClass || "";
	  }

	  function updateLineGutter(cm, lineView, lineN, dims) {
	    if (lineView.gutter) {
	      lineView.node.removeChild(lineView.gutter);
	      lineView.gutter = null;
	    }
	    if (lineView.gutterBackground) {
	      lineView.node.removeChild(lineView.gutterBackground);
	      lineView.gutterBackground = null;
	    }
	    if (lineView.line.gutterClass) {
	      var wrap = ensureLineWrapped(lineView);
	      lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
	                                      ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px"));
	      cm.display.input.setUneditable(lineView.gutterBackground);
	      wrap.insertBefore(lineView.gutterBackground, lineView.text);
	    }
	    var markers = lineView.line.gutterMarkers;
	    if (cm.options.lineNumbers || markers) {
	      var wrap$1 = ensureLineWrapped(lineView);
	      var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"));
	      cm.display.input.setUneditable(gutterWrap);
	      wrap$1.insertBefore(gutterWrap, lineView.text);
	      if (lineView.line.gutterClass)
	        { gutterWrap.className += " " + lineView.line.gutterClass; }
	      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
	        { lineView.lineNumber = gutterWrap.appendChild(
	          elt("div", lineNumberFor(cm.options, lineN),
	              "CodeMirror-linenumber CodeMirror-gutter-elt",
	              ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); }
	      if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) {
	        var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
	        if (found)
	          { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt",
	                                     ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); }
	      } }
	    }
	  }

	  function updateLineWidgets(cm, lineView, dims) {
	    if (lineView.alignable) { lineView.alignable = null; }
	    for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {
	      next = node.nextSibling;
	      if (node.className == "CodeMirror-linewidget")
	        { lineView.node.removeChild(node); }
	    }
	    insertLineWidgets(cm, lineView, dims);
	  }

	  // Build a line's DOM representation from scratch
	  function buildLineElement(cm, lineView, lineN, dims) {
	    var built = getLineContent(cm, lineView);
	    lineView.text = lineView.node = built.pre;
	    if (built.bgClass) { lineView.bgClass = built.bgClass; }
	    if (built.textClass) { lineView.textClass = built.textClass; }

	    updateLineClasses(cm, lineView);
	    updateLineGutter(cm, lineView, lineN, dims);
	    insertLineWidgets(cm, lineView, dims);
	    return lineView.node
	  }

	  // A lineView may contain multiple logical lines (when merged by
	  // collapsed spans). The widgets for all of them need to be drawn.
	  function insertLineWidgets(cm, lineView, dims) {
	    insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
	    if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
	      { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } }
	  }

	  function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
	    if (!line.widgets) { return }
	    var wrap = ensureLineWrapped(lineView);
	    for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
	      var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
	      if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); }
	      positionLineWidget(widget, node, lineView, dims);
	      cm.display.input.setUneditable(node);
	      if (allowAbove && widget.above)
	        { wrap.insertBefore(node, lineView.gutter || lineView.text); }
	      else
	        { wrap.appendChild(node); }
	      signalLater(widget, "redraw");
	    }
	  }

	  function positionLineWidget(widget, node, lineView, dims) {
	    if (widget.noHScroll) {
	  (lineView.alignable || (lineView.alignable = [])).push(node);
	      var width = dims.wrapperWidth;
	      node.style.left = dims.fixedPos + "px";
	      if (!widget.coverGutter) {
	        width -= dims.gutterTotalWidth;
	        node.style.paddingLeft = dims.gutterTotalWidth + "px";
	      }
	      node.style.width = width + "px";
	    }
	    if (widget.coverGutter) {
	      node.style.zIndex = 5;
	      node.style.position = "relative";
	      if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; }
	    }
	  }

	  function widgetHeight(widget) {
	    if (widget.height != null) { return widget.height }
	    var cm = widget.doc.cm;
	    if (!cm) { return 0 }
	    if (!contains(document.body, widget.node)) {
	      var parentStyle = "position: relative;";
	      if (widget.coverGutter)
	        { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; }
	      if (widget.noHScroll)
	        { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; }
	      removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
	    }
	    return widget.height = widget.node.parentNode.offsetHeight
	  }

	  // Return true when the given mouse event happened in a widget
	  function eventInWidget(display, e) {
	    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
	      if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
	          (n.parentNode == display.sizer && n != display.mover))
	        { return true }
	    }
	  }

	  // POSITION MEASUREMENT

	  function paddingTop(display) {return display.lineSpace.offsetTop}
	  function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}
	  function paddingH(display) {
	    if (display.cachedPaddingH) { return display.cachedPaddingH }
	    var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
	    var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
	    var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
	    if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; }
	    return data
	  }

	  function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }
	  function displayWidth(cm) {
	    return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth
	  }
	  function displayHeight(cm) {
	    return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight
	  }

	  // Ensure the lineView.wrapping.heights array is populated. This is
	  // an array of bottom offsets for the lines that make up a drawn
	  // line. When lineWrapping is on, there might be more than one
	  // height.
	  function ensureLineHeights(cm, lineView, rect) {
	    var wrapping = cm.options.lineWrapping;
	    var curWidth = wrapping && displayWidth(cm);
	    if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
	      var heights = lineView.measure.heights = [];
	      if (wrapping) {
	        lineView.measure.width = curWidth;
	        var rects = lineView.text.firstChild.getClientRects();
	        for (var i = 0; i < rects.length - 1; i++) {
	          var cur = rects[i], next = rects[i + 1];
	          if (Math.abs(cur.bottom - next.bottom) > 2)
	            { heights.push((cur.bottom + next.top) / 2 - rect.top); }
	        }
	      }
	      heights.push(rect.bottom - rect.top);
	    }
	  }

	  // Find a line map (mapping character offsets to text nodes) and a
	  // measurement cache for the given line number. (A line view might
	  // contain multiple lines when collapsed ranges are present.)
	  function mapFromLineView(lineView, line, lineN) {
	    if (lineView.line == line)
	      { return {map: lineView.measure.map, cache: lineView.measure.cache} }
	    for (var i = 0; i < lineView.rest.length; i++)
	      { if (lineView.rest[i] == line)
	        { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
	    for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
	      { if (lineNo(lineView.rest[i$1]) > lineN)
	        { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
	  }

	  // Render a line into the hidden node display.externalMeasured. Used
	  // when measurement is needed for a line that's not in the viewport.
	  function updateExternalMeasurement(cm, line) {
	    line = visualLine(line);
	    var lineN = lineNo(line);
	    var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
	    view.lineN = lineN;
	    var built = view.built = buildLineContent(cm, view);
	    view.text = built.pre;
	    removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
	    return view
	  }

	  // Get a {top, bottom, left, right} box (in line-local coordinates)
	  // for a given character.
	  function measureChar(cm, line, ch, bias) {
	    return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)
	  }

	  // Find a line view that corresponds to the given line number.
	  function findViewForLine(cm, lineN) {
	    if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
	      { return cm.display.view[findViewIndex(cm, lineN)] }
	    var ext = cm.display.externalMeasured;
	    if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
	      { return ext }
	  }

	  // Measurement can be split in two steps, the set-up work that
	  // applies to the whole line, and the measurement of the actual
	  // character. Functions like coordsChar, that need to do a lot of
	  // measurements in a row, can thus ensure that the set-up work is
	  // only done once.
	  function prepareMeasureForLine(cm, line) {
	    var lineN = lineNo(line);
	    var view = findViewForLine(cm, lineN);
	    if (view && !view.text) {
	      view = null;
	    } else if (view && view.changes) {
	      updateLineForChanges(cm, view, lineN, getDimensions(cm));
	      cm.curOp.forceUpdate = true;
	    }
	    if (!view)
	      { view = updateExternalMeasurement(cm, line); }

	    var info = mapFromLineView(view, line, lineN);
	    return {
	      line: line, view: view, rect: null,
	      map: info.map, cache: info.cache, before: info.before,
	      hasHeights: false
	    }
	  }

	  // Given a prepared measurement object, measures the position of an
	  // actual character (or fetches it from the cache).
	  function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
	    if (prepared.before) { ch = -1; }
	    var key = ch + (bias || ""), found;
	    if (prepared.cache.hasOwnProperty(key)) {
	      found = prepared.cache[key];
	    } else {
	      if (!prepared.rect)
	        { prepared.rect = prepared.view.text.getBoundingClientRect(); }
	      if (!prepared.hasHeights) {
	        ensureLineHeights(cm, prepared.view, prepared.rect);
	        prepared.hasHeights = true;
	      }
	      found = measureCharInner(cm, prepared, ch, bias);
	      if (!found.bogus) { prepared.cache[key] = found; }
	    }
	    return {left: found.left, right: found.right,
	            top: varHeight ? found.rtop : found.top,
	            bottom: varHeight ? found.rbottom : found.bottom}
	  }

	  var nullRect = {left: 0, right: 0, top: 0, bottom: 0};

	  function nodeAndOffsetInLineMap(map$$1, ch, bias) {
	    var node, start, end, collapse, mStart, mEnd;
	    // First, search the line map for the text node corresponding to,
	    // or closest to, the target character.
	    for (var i = 0; i < map$$1.length; i += 3) {
	      mStart = map$$1[i];
	      mEnd = map$$1[i + 1];
	      if (ch < mStart) {
	        start = 0; end = 1;
	        collapse = "left";
	      } else if (ch < mEnd) {
	        start = ch - mStart;
	        end = start + 1;
	      } else if (i == map$$1.length - 3 || ch == mEnd && map$$1[i + 3] > ch) {
	        end = mEnd - mStart;
	        start = end - 1;
	        if (ch >= mEnd) { collapse = "right"; }
	      }
	      if (start != null) {
	        node = map$$1[i + 2];
	        if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
	          { collapse = bias; }
	        if (bias == "left" && start == 0)
	          { while (i && map$$1[i - 2] == map$$1[i - 3] && map$$1[i - 1].insertLeft) {
	            node = map$$1[(i -= 3) + 2];
	            collapse = "left";
	          } }
	        if (bias == "right" && start == mEnd - mStart)
	          { while (i < map$$1.length - 3 && map$$1[i + 3] == map$$1[i + 4] && !map$$1[i + 5].insertLeft) {
	            node = map$$1[(i += 3) + 2];
	            collapse = "right";
	          } }
	        break
	      }
	    }
	    return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}
	  }

	  function getUsefulRect(rects, bias) {
	    var rect = nullRect;
	    if (bias == "left") { for (var i = 0; i < rects.length; i++) {
	      if ((rect = rects[i]).left != rect.right) { break }
	    } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {
	      if ((rect = rects[i$1]).left != rect.right) { break }
	    } }
	    return rect
	  }

	  function measureCharInner(cm, prepared, ch, bias) {
	    var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
	    var node = place.node, start = place.start, end = place.end, collapse = place.collapse;

	    var rect;
	    if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
	      for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned
	        while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; }
	        while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; }
	        if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
	          { rect = node.parentNode.getBoundingClientRect(); }
	        else
	          { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); }
	        if (rect.left || rect.right || start == 0) { break }
	        end = start;
	        start = start - 1;
	        collapse = "right";
	      }
	      if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); }
	    } else { // If it is a widget, simply get the box for the whole widget.
	      if (start > 0) { collapse = bias = "right"; }
	      var rects;
	      if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
	        { rect = rects[bias == "right" ? rects.length - 1 : 0]; }
	      else
	        { rect = node.getBoundingClientRect(); }
	    }
	    if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
	      var rSpan = node.parentNode.getClientRects()[0];
	      if (rSpan)
	        { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; }
	      else
	        { rect = nullRect; }
	    }

	    var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
	    var mid = (rtop + rbot) / 2;
	    var heights = prepared.view.measure.heights;
	    var i = 0;
	    for (; i < heights.length - 1; i++)
	      { if (mid < heights[i]) { break } }
	    var top = i ? heights[i - 1] : 0, bot = heights[i];
	    var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
	                  right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
	                  top: top, bottom: bot};
	    if (!rect.left && !rect.right) { result.bogus = true; }
	    if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }

	    return result
	  }

	  // Work around problem with bounding client rects on ranges being
	  // returned incorrectly when zoomed on IE10 and below.
	  function maybeUpdateRectForZooming(measure, rect) {
	    if (!window.screen || screen.logicalXDPI == null ||
	        screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
	      { return rect }
	    var scaleX = screen.logicalXDPI / screen.deviceXDPI;
	    var scaleY = screen.logicalYDPI / screen.deviceYDPI;
	    return {left: rect.left * scaleX, right: rect.right * scaleX,
	            top: rect.top * scaleY, bottom: rect.bottom * scaleY}
	  }

	  function clearLineMeasurementCacheFor(lineView) {
	    if (lineView.measure) {
	      lineView.measure.cache = {};
	      lineView.measure.heights = null;
	      if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
	        { lineView.measure.caches[i] = {}; } }
	    }
	  }

	  function clearLineMeasurementCache(cm) {
	    cm.display.externalMeasure = null;
	    removeChildren(cm.display.lineMeasure);
	    for (var i = 0; i < cm.display.view.length; i++)
	      { clearLineMeasurementCacheFor(cm.display.view[i]); }
	  }

	  function clearCaches(cm) {
	    clearLineMeasurementCache(cm);
	    cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
	    if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; }
	    cm.display.lineNumChars = null;
	  }

	  function pageScrollX() {
	    // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206
	    // which causes page_Offset and bounding client rects to use
	    // different reference viewports and invalidate our calculations.
	    if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) }
	    return window.pageXOffset || (document.documentElement || document.body).scrollLeft
	  }
	  function pageScrollY() {
	    if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) }
	    return window.pageYOffset || (document.documentElement || document.body).scrollTop
	  }

	  function widgetTopHeight(lineObj) {
	    var height = 0;
	    if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above)
	      { height += widgetHeight(lineObj.widgets[i]); } } }
	    return height
	  }

	  // Converts a {top, bottom, left, right} box from line-local
	  // coordinates into another coordinate system. Context may be one of
	  // "line", "div" (display.lineDiv), "local"./null (editor), "window",
	  // or "page".
	  function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
	    if (!includeWidgets) {
	      var height = widgetTopHeight(lineObj);
	      rect.top += height; rect.bottom += height;
	    }
	    if (context == "line") { return rect }
	    if (!context) { context = "local"; }
	    var yOff = heightAtLine(lineObj);
	    if (context == "local") { yOff += paddingTop(cm.display); }
	    else { yOff -= cm.display.viewOffset; }
	    if (context == "page" || context == "window") {
	      var lOff = cm.display.lineSpace.getBoundingClientRect();
	      yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
	      var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
	      rect.left += xOff; rect.right += xOff;
	    }
	    rect.top += yOff; rect.bottom += yOff;
	    return rect
	  }

	  // Coverts a box from "div" coords to another coordinate system.
	  // Context may be "window", "page", "div", or "local"./null.
	  function fromCoordSystem(cm, coords, context) {
	    if (context == "div") { return coords }
	    var left = coords.left, top = coords.top;
	    // First move into "page" coordinate system
	    if (context == "page") {
	      left -= pageScrollX();
	      top -= pageScrollY();
	    } else if (context == "local" || !context) {
	      var localBox = cm.display.sizer.getBoundingClientRect();
	      left += localBox.left;
	      top += localBox.top;
	    }

	    var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
	    return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}
	  }

	  function charCoords(cm, pos, context, lineObj, bias) {
	    if (!lineObj) { lineObj = getLine(cm.doc, pos.line); }
	    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)
	  }

	  // Returns a box for a given cursor position, which may have an
	  // 'other' property containing the position of the secondary cursor
	  // on a bidi boundary.
	  // A cursor Pos(line, char, "before") is on the same visual line as `char - 1`
	  // and after `char - 1` in writing order of `char - 1`
	  // A cursor Pos(line, char, "after") is on the same visual line as `char`
	  // and before `char` in writing order of `char`
	  // Examples (upper-case letters are RTL, lower-case are LTR):
	  //     Pos(0, 1, ...)
	  //     before   after
	  // ab     a|b     a|b
	  // aB     a|B     aB|
	  // Ab     |Ab     A|b
	  // AB     B|A     B|A
	  // Every position after the last character on a line is considered to stick
	  // to the last character on the line.
	  function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
	    lineObj = lineObj || getLine(cm.doc, pos.line);
	    if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
	    function get(ch, right) {
	      var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
	      if (right) { m.left = m.right; } else { m.right = m.left; }
	      return intoCoordSystem(cm, lineObj, m, context)
	    }
	    var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky;
	    if (ch >= lineObj.text.length) {
	      ch = lineObj.text.length;
	      sticky = "before";
	    } else if (ch <= 0) {
	      ch = 0;
	      sticky = "after";
	    }
	    if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") }

	    function getBidi(ch, partPos, invert) {
	      var part = order[partPos], right = part.level == 1;
	      return get(invert ? ch - 1 : ch, right != invert)
	    }
	    var partPos = getBidiPartAt(order, ch, sticky);
	    var other = bidiOther;
	    var val = getBidi(ch, partPos, sticky == "before");
	    if (other != null) { val.other = getBidi(ch, other, sticky != "before"); }
	    return val
	  }

	  // Used to cheaply estimate the coordinates for a position. Used for
	  // intermediate scroll updates.
	  function estimateCoords(cm, pos) {
	    var left = 0;
	    pos = clipPos(cm.doc, pos);
	    if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; }
	    var lineObj = getLine(cm.doc, pos.line);
	    var top = heightAtLine(lineObj) + paddingTop(cm.display);
	    return {left: left, right: left, top: top, bottom: top + lineObj.height}
	  }

	  // Positions returned by coordsChar contain some extra information.
	  // xRel is the relative x position of the input coordinates compared
	  // to the found position (so xRel > 0 means the coordinates are to
	  // the right of the character position, for example). When outside
	  // is true, that means the coordinates lie outside the line's
	  // vertical range.
	  function PosWithInfo(line, ch, sticky, outside, xRel) {
	    var pos = Pos(line, ch, sticky);
	    pos.xRel = xRel;
	    if (outside) { pos.outside = true; }
	    return pos
	  }

	  // Compute the character position closest to the given coordinates.
	  // Input must be lineSpace-local ("div" coordinate system).
	  function coordsChar(cm, x, y) {
	    var doc = cm.doc;
	    y += cm.display.viewOffset;
	    if (y < 0) { return PosWithInfo(doc.first, 0, null, true, -1) }
	    var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
	    if (lineN > last)
	      { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, true, 1) }
	    if (x < 0) { x = 0; }

	    var lineObj = getLine(doc, lineN);
	    for (;;) {
	      var found = coordsCharInner(cm, lineObj, lineN, x, y);
	      var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 ? 1 : 0));
	      if (!collapsed) { return found }
	      var rangeEnd = collapsed.find(1);
	      if (rangeEnd.line == lineN) { return rangeEnd }
	      lineObj = getLine(doc, lineN = rangeEnd.line);
	    }
	  }

	  function wrappedLineExtent(cm, lineObj, preparedMeasure, y) {
	    y -= widgetTopHeight(lineObj);
	    var end = lineObj.text.length;
	    var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0);
	    end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end);
	    return {begin: begin, end: end}
	  }

	  function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) {
	    if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
	    var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top;
	    return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop)
	  }

	  // Returns true if the given side of a box is after the given
	  // coordinates, in top-to-bottom, left-to-right order.
	  function boxIsAfter(box, x, y, left) {
	    return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x
	  }

	  function coordsCharInner(cm, lineObj, lineNo$$1, x, y) {
	    // Move y into line-local coordinate space
	    y -= heightAtLine(lineObj);
	    var preparedMeasure = prepareMeasureForLine(cm, lineObj);
	    // When directly calling `measureCharPrepared`, we have to adjust
	    // for the widgets at this line.
	    var widgetHeight$$1 = widgetTopHeight(lineObj);
	    var begin = 0, end = lineObj.text.length, ltr = true;

	    var order = getOrder(lineObj, cm.doc.direction);
	    // If the line isn't plain left-to-right text, first figure out
	    // which bidi section the coordinates fall into.
	    if (order) {
	      var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart)
	                   (cm, lineObj, lineNo$$1, preparedMeasure, order, x, y);
	      ltr = part.level != 1;
	      // The awkward -1 offsets are needed because findFirst (called
	      // on these below) will treat its first bound as inclusive,
	      // second as exclusive, but we want to actually address the
	      // characters in the part's range
	      begin = ltr ? part.from : part.to - 1;
	      end = ltr ? part.to : part.from - 1;
	    }

	    // A binary search to find the first character whose bounding box
	    // starts after the coordinates. If we run across any whose box wrap
	    // the coordinates, store that.
	    var chAround = null, boxAround = null;
	    var ch = findFirst(function (ch) {
	      var box = measureCharPrepared(cm, preparedMeasure, ch);
	      box.top += widgetHeight$$1; box.bottom += widgetHeight$$1;
	      if (!boxIsAfter(box, x, y, false)) { return false }
	      if (box.top <= y && box.left <= x) {
	        chAround = ch;
	        boxAround = box;
	      }
	      return true
	    }, begin, end);

	    var baseX, sticky, outside = false;
	    // If a box around the coordinates was found, use that
	    if (boxAround) {
	      // Distinguish coordinates nearer to the left or right side of the box
	      var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr;
	      ch = chAround + (atStart ? 0 : 1);
	      sticky = atStart ? "after" : "before";
	      baseX = atLeft ? boxAround.left : boxAround.right;
	    } else {
	      // (Adjust for extended bound, if necessary.)
	      if (!ltr && (ch == end || ch == begin)) { ch++; }
	      // To determine which side to associate with, get the box to the
	      // left of the character and compare it's vertical position to the
	      // coordinates
	      sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" :
	        (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight$$1 <= y) == ltr ?
	        "after" : "before";
	      // Now get accurate coordinates for this place, in order to get a
	      // base X position
	      var coords = cursorCoords(cm, Pos(lineNo$$1, ch, sticky), "line", lineObj, preparedMeasure);
	      baseX = coords.left;
	      outside = y < coords.top || y >= coords.bottom;
	    }

	    ch = skipExtendingChars(lineObj.text, ch, 1);
	    return PosWithInfo(lineNo$$1, ch, sticky, outside, x - baseX)
	  }

	  function coordsBidiPart(cm, lineObj, lineNo$$1, preparedMeasure, order, x, y) {
	    // Bidi parts are sorted left-to-right, and in a non-line-wrapping
	    // situation, we can take this ordering to correspond to the visual
	    // ordering. This finds the first part whose end is after the given
	    // coordinates.
	    var index = findFirst(function (i) {
	      var part = order[i], ltr = part.level != 1;
	      return boxIsAfter(cursorCoords(cm, Pos(lineNo$$1, ltr ? part.to : part.from, ltr ? "before" : "after"),
	                                     "line", lineObj, preparedMeasure), x, y, true)
	    }, 0, order.length - 1);
	    var part = order[index];
	    // If this isn't the first part, the part's start is also after
	    // the coordinates, and the coordinates aren't on the same line as
	    // that start, move one part back.
	    if (index > 0) {
	      var ltr = part.level != 1;
	      var start = cursorCoords(cm, Pos(lineNo$$1, ltr ? part.from : part.to, ltr ? "after" : "before"),
	                               "line", lineObj, preparedMeasure);
	      if (boxIsAfter(start, x, y, true) && start.top > y)
	        { part = order[index - 1]; }
	    }
	    return part
	  }

	  function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) {
	    // In a wrapped line, rtl text on wrapping boundaries can do things
	    // that don't correspond to the ordering in our `order` array at
	    // all, so a binary search doesn't work, and we want to return a
	    // part that only spans one line so that the binary search in
	    // coordsCharInner is safe. As such, we first find the extent of the
	    // wrapped line, and then do a flat search in which we discard any
	    // spans that aren't on the line.
	    var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y);
	    var begin = ref.begin;
	    var end = ref.end;
	    if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; }
	    var part = null, closestDist = null;
	    for (var i = 0; i < order.length; i++) {
	      var p = order[i];
	      if (p.from >= end || p.to <= begin) { continue }
	      var ltr = p.level != 1;
	      var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right;
	      // Weigh against spans ending before this, so that they are only
	      // picked if nothing ends after
	      var dist = endX < x ? x - endX + 1e9 : endX - x;
	      if (!part || closestDist > dist) {
	        part = p;
	        closestDist = dist;
	      }
	    }
	    if (!part) { part = order[order.length - 1]; }
	    // Clip the part to the wrapped line.
	    if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; }
	    if (part.to > end) { part = {from: part.from, to: end, level: part.level}; }
	    return part
	  }

	  var measureText;
	  // Compute the default text height.
	  function textHeight(display) {
	    if (display.cachedTextHeight != null) { return display.cachedTextHeight }
	    if (measureText == null) {
	      measureText = elt("pre");
	      // Measure a bunch of lines, for browsers that compute
	      // fractional heights.
	      for (var i = 0; i < 49; ++i) {
	        measureText.appendChild(document.createTextNode("x"));
	        measureText.appendChild(elt("br"));
	      }
	      measureText.appendChild(document.createTextNode("x"));
	    }
	    removeChildrenAndAdd(display.measure, measureText);
	    var height = measureText.offsetHeight / 50;
	    if (height > 3) { display.cachedTextHeight = height; }
	    removeChildren(display.measure);
	    return height || 1
	  }

	  // Compute the default character width.
	  function charWidth(display) {
	    if (display.cachedCharWidth != null) { return display.cachedCharWidth }
	    var anchor = elt("span", "xxxxxxxxxx");
	    var pre = elt("pre", [anchor]);
	    removeChildrenAndAdd(display.measure, pre);
	    var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
	    if (width > 2) { display.cachedCharWidth = width; }
	    return width || 10
	  }

	  // Do a bulk-read of the DOM positions and sizes needed to draw the
	  // view, so that we don't interleave reading and writing to the DOM.
	  function getDimensions(cm) {
	    var d = cm.display, left = {}, width = {};
	    var gutterLeft = d.gutters.clientLeft;
	    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
	      left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
	      width[cm.options.gutters[i]] = n.clientWidth;
	    }
	    return {fixedPos: compensateForHScroll(d),
	            gutterTotalWidth: d.gutters.offsetWidth,
	            gutterLeft: left,
	            gutterWidth: width,
	            wrapperWidth: d.wrapper.clientWidth}
	  }

	  // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
	  // but using getBoundingClientRect to get a sub-pixel-accurate
	  // result.
	  function compensateForHScroll(display) {
	    return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left
	  }

	  // Returns a function that estimates the height of a line, to use as
	  // first approximation until the line becomes visible (and is thus
	  // properly measurable).
	  function estimateHeight(cm) {
	    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
	    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
	    return function (line) {
	      if (lineIsHidden(cm.doc, line)) { return 0 }

	      var widgetsHeight = 0;
	      if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {
	        if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; }
	      } }

	      if (wrapping)
	        { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }
	      else
	        { return widgetsHeight + th }
	    }
	  }

	  function estimateLineHeights(cm) {
	    var doc = cm.doc, est = estimateHeight(cm);
	    doc.iter(function (line) {
	      var estHeight = est(line);
	      if (estHeight != line.height) { updateLineHeight(line, estHeight); }
	    });
	  }

	  // Given a mouse event, find the corresponding position. If liberal
	  // is false, it checks whether a gutter or scrollbar was clicked,
	  // and returns null if it was. forRect is used by rectangular
	  // selections, and tries to estimate a character position even for
	  // coordinates beyond the right of the text.
	  function posFromMouse(cm, e, liberal, forRect) {
	    var display = cm.display;
	    if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null }

	    var x, y, space = display.lineSpace.getBoundingClientRect();
	    // Fails unpredictably on IE[67] when mouse is dragged around quickly.
	    try { x = e.clientX - space.left; y = e.clientY - space.top; }
	    catch (e) { return null }
	    var coords = coordsChar(cm, x, y), line;
	    if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
	      var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
	      coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
	    }
	    return coords
	  }

	  // Find the view element corresponding to a given line. Return null
	  // when the line isn't visible.
	  function findViewIndex(cm, n) {
	    if (n >= cm.display.viewTo) { return null }
	    n -= cm.display.viewFrom;
	    if (n < 0) { return null }
	    var view = cm.display.view;
	    for (var i = 0; i < view.length; i++) {
	      n -= view[i].size;
	      if (n < 0) { return i }
	    }
	  }

	  function updateSelection(cm) {
	    cm.display.input.showSelection(cm.display.input.prepareSelection());
	  }

	  function prepareSelection(cm, primary) {
	    if ( primary === void 0 ) primary = true;

	    var doc = cm.doc, result = {};
	    var curFragment = result.cursors = document.createDocumentFragment();
	    var selFragment = result.selection = document.createDocumentFragment();

	    for (var i = 0; i < doc.sel.ranges.length; i++) {
	      if (!primary && i == doc.sel.primIndex) { continue }
	      var range$$1 = doc.sel.ranges[i];
	      if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { continue }
	      var collapsed = range$$1.empty();
	      if (collapsed || cm.options.showCursorWhenSelecting)
	        { drawSelectionCursor(cm, range$$1.head, curFragment); }
	      if (!collapsed)
	        { drawSelectionRange(cm, range$$1, selFragment); }
	    }
	    return result
	  }

	  // Draws a cursor for the given range
	  function drawSelectionCursor(cm, head, output) {
	    var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);

	    var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
	    cursor.style.left = pos.left + "px";
	    cursor.style.top = pos.top + "px";
	    cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";

	    if (pos.other) {
	      // Secondary cursor, shown when on a 'jump' in bi-directional text
	      var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
	      otherCursor.style.display = "";
	      otherCursor.style.left = pos.other.left + "px";
	      otherCursor.style.top = pos.other.top + "px";
	      otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
	    }
	  }

	  function cmpCoords(a, b) { return a.top - b.top || a.left - b.left }

	  // Draws the given range as a highlighted selection
	  function drawSelectionRange(cm, range$$1, output) {
	    var display = cm.display, doc = cm.doc;
	    var fragment = document.createDocumentFragment();
	    var padding = paddingH(cm.display), leftSide = padding.left;
	    var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
	    var docLTR = doc.direction == "ltr";

	    function add(left, top, width, bottom) {
	      if (top < 0) { top = 0; }
	      top = Math.round(top);
	      bottom = Math.round(bottom);
	      fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n                             top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n                             height: " + (bottom - top) + "px")));
	    }

	    function drawForLine(line, fromArg, toArg) {
	      var lineObj = getLine(doc, line);
	      var lineLen = lineObj.text.length;
	      var start, end;
	      function coords(ch, bias) {
	        return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
	      }

	      function wrapX(pos, dir, side) {
	        var extent = wrappedLineExtentChar(cm, lineObj, null, pos);
	        var prop = (dir == "ltr") == (side == "after") ? "left" : "right";
	        var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1);
	        return coords(ch, prop)[prop]
	      }

	      var order = getOrder(lineObj, doc.direction);
	      iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) {
	        var ltr = dir == "ltr";
	        var fromPos = coords(from, ltr ? "left" : "right");
	        var toPos = coords(to - 1, ltr ? "right" : "left");

	        var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen;
	        var first = i == 0, last = !order || i == order.length - 1;
	        if (toPos.top - fromPos.top <= 3) { // Single line
	          var openLeft = (docLTR ? openStart : openEnd) && first;
	          var openRight = (docLTR ? openEnd : openStart) && last;
	          var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left;
	          var right = openRight ? rightSide : (ltr ? toPos : fromPos).right;
	          add(left, fromPos.top, right - left, fromPos.bottom);
	        } else { // Multiple lines
	          var topLeft, topRight, botLeft, botRight;
	          if (ltr) {
	            topLeft = docLTR && openStart && first ? leftSide : fromPos.left;
	            topRight = docLTR ? rightSide : wrapX(from, dir, "before");
	            botLeft = docLTR ? leftSide : wrapX(to, dir, "after");
	            botRight = docLTR && openEnd && last ? rightSide : toPos.right;
	          } else {
	            topLeft = !docLTR ? leftSide : wrapX(from, dir, "before");
	            topRight = !docLTR && openStart && first ? rightSide : fromPos.right;
	            botLeft = !docLTR && openEnd && last ? leftSide : toPos.left;
	            botRight = !docLTR ? rightSide : wrapX(to, dir, "after");
	          }
	          add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom);
	          if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); }
	          add(botLeft, toPos.top, botRight - botLeft, toPos.bottom);
	        }

	        if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; }
	        if (cmpCoords(toPos, start) < 0) { start = toPos; }
	        if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; }
	        if (cmpCoords(toPos, end) < 0) { end = toPos; }
	      });
	      return {start: start, end: end}
	    }

	    var sFrom = range$$1.from(), sTo = range$$1.to();
	    if (sFrom.line == sTo.line) {
	      drawForLine(sFrom.line, sFrom.ch, sTo.ch);
	    } else {
	      var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
	      var singleVLine = visualLine(fromLine) == visualLine(toLine);
	      var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
	      var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
	      if (singleVLine) {
	        if (leftEnd.top < rightStart.top - 2) {
	          add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
	          add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
	        } else {
	          add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
	        }
	      }
	      if (leftEnd.bottom < rightStart.top)
	        { add(leftSide, leftEnd.bottom, null, rightStart.top); }
	    }

	    output.appendChild(fragment);
	  }

	  // Cursor-blinking
	  function restartBlink(cm) {
	    if (!cm.state.focused) { return }
	    var display = cm.display;
	    clearInterval(display.blinker);
	    var on = true;
	    display.cursorDiv.style.visibility = "";
	    if (cm.options.cursorBlinkRate > 0)
	      { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; },
	        cm.options.cursorBlinkRate); }
	    else if (cm.options.cursorBlinkRate < 0)
	      { display.cursorDiv.style.visibility = "hidden"; }
	  }

	  function ensureFocus(cm) {
	    if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
	  }

	  function delayBlurEvent(cm) {
	    cm.state.delayingBlurEvent = true;
	    setTimeout(function () { if (cm.state.delayingBlurEvent) {
	      cm.state.delayingBlurEvent = false;
	      onBlur(cm);
	    } }, 100);
	  }

	  function onFocus(cm, e) {
	    if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; }

	    if (cm.options.readOnly == "nocursor") { return }
	    if (!cm.state.focused) {
	      signal(cm, "focus", cm, e);
	      cm.state.focused = true;
	      addClass(cm.display.wrapper, "CodeMirror-focused");
	      // This test prevents this from firing when a context
	      // menu is closed (since the input reset would kill the
	      // select-all detection hack)
	      if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
	        cm.display.input.reset();
	        if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730
	      }
	      cm.display.input.receivedFocus();
	    }
	    restartBlink(cm);
	  }
	  function onBlur(cm, e) {
	    if (cm.state.delayingBlurEvent) { return }

	    if (cm.state.focused) {
	      signal(cm, "blur", cm, e);
	      cm.state.focused = false;
	      rmClass(cm.display.wrapper, "CodeMirror-focused");
	    }
	    clearInterval(cm.display.blinker);
	    setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150);
	  }

	  // Read the actual heights of the rendered lines, and update their
	  // stored heights to match.
	  function updateHeightsInViewport(cm) {
	    var display = cm.display;
	    var prevBottom = display.lineDiv.offsetTop;
	    for (var i = 0; i < display.view.length; i++) {
	      var cur = display.view[i], wrapping = cm.options.lineWrapping;
	      var height = (void 0), width = 0;
	      if (cur.hidden) { continue }
	      if (ie && ie_version < 8) {
	        var bot = cur.node.offsetTop + cur.node.offsetHeight;
	        height = bot - prevBottom;
	        prevBottom = bot;
	      } else {
	        var box = cur.node.getBoundingClientRect();
	        height = box.bottom - box.top;
	        // Check that lines don't extend past the right of the current
	        // editor width
	        if (!wrapping && cur.text.firstChild)
	          { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; }
	      }
	      var diff = cur.line.height - height;
	      if (height < 2) { height = textHeight(display); }
	      if (diff > .005 || diff < -.005) {
	        updateLineHeight(cur.line, height);
	        updateWidgetHeight(cur.line);
	        if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
	          { updateWidgetHeight(cur.rest[j]); } }
	      }
	      if (width > cm.display.sizerWidth) {
	        var chWidth = Math.ceil(width / charWidth(cm.display));
	        if (chWidth > cm.display.maxLineLength) {
	          cm.display.maxLineLength = chWidth;
	          cm.display.maxLine = cur.line;
	          cm.display.maxLineChanged = true;
	        }
	      }
	    }
	  }

	  // Read and store the height of line widgets associated with the
	  // given line.
	  function updateWidgetHeight(line) {
	    if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) {
	      var w = line.widgets[i], parent = w.node.parentNode;
	      if (parent) { w.height = parent.offsetHeight; }
	    } }
	  }

	  // Compute the lines that are visible in a given viewport (defaults
	  // the the current scroll position). viewport may contain top,
	  // height, and ensure (see op.scrollToPos) properties.
	  function visibleLines(display, doc, viewport) {
	    var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
	    top = Math.floor(top - paddingTop(display));
	    var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;

	    var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
	    // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
	    // forces those lines into the viewport (if possible).
	    if (viewport && viewport.ensure) {
	      var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
	      if (ensureFrom < from) {
	        from = ensureFrom;
	        to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
	      } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
	        from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
	        to = ensureTo;
	      }
	    }
	    return {from: from, to: Math.max(to, from + 1)}
	  }

	  // Re-align line numbers and gutter marks to compensate for
	  // horizontal scrolling.
	  function alignHorizontally(cm) {
	    var display = cm.display, view = display.view;
	    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
	    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
	    var gutterW = display.gutters.offsetWidth, left = comp + "px";
	    for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
	      if (cm.options.fixedGutter) {
	        if (view[i].gutter)
	          { view[i].gutter.style.left = left; }
	        if (view[i].gutterBackground)
	          { view[i].gutterBackground.style.left = left; }
	      }
	      var align = view[i].alignable;
	      if (align) { for (var j = 0; j < align.length; j++)
	        { align[j].style.left = left; } }
	    } }
	    if (cm.options.fixedGutter)
	      { display.gutters.style.left = (comp + gutterW) + "px"; }
	  }

	  // Used to ensure that the line number gutter is still the right
	  // size for the current document size. Returns true when an update
	  // is needed.
	  function maybeUpdateLineNumberWidth(cm) {
	    if (!cm.options.lineNumbers) { return false }
	    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
	    if (last.length != display.lineNumChars) {
	      var test = display.measure.appendChild(elt("div", [elt("div", last)],
	                                                 "CodeMirror-linenumber CodeMirror-gutter-elt"));
	      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
	      display.lineGutter.style.width = "";
	      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
	      display.lineNumWidth = display.lineNumInnerWidth + padding;
	      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
	      display.lineGutter.style.width = display.lineNumWidth + "px";
	      updateGutterSpace(cm);
	      return true
	    }
	    return false
	  }

	  // SCROLLING THINGS INTO VIEW

	  // If an editor sits on the top or bottom of the window, partially
	  // scrolled out of view, this ensures that the cursor is visible.
	  function maybeScrollWindow(cm, rect) {
	    if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }

	    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
	    if (rect.top + box.top < 0) { doScroll = true; }
	    else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; }
	    if (doScroll != null && !phantom) {
	      var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n                         top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n                         height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n                         left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;"));
	      cm.display.lineSpace.appendChild(scrollNode);
	      scrollNode.scrollIntoView(doScroll);
	      cm.display.lineSpace.removeChild(scrollNode);
	    }
	  }

	  // Scroll a given position into view (immediately), verifying that
	  // it actually became visible (as line heights are accurately
	  // measured, the position of something may 'drift' during drawing).
	  function scrollPosIntoView(cm, pos, end, margin) {
	    if (margin == null) { margin = 0; }
	    var rect;
	    if (!cm.options.lineWrapping && pos == end) {
	      // Set pos and end to the cursor positions around the character pos sticks to
	      // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch
	      // If pos == Pos(_, 0, "before"), pos and end are unchanged
	      pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
	      end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos;
	    }
	    for (var limit = 0; limit < 5; limit++) {
	      var changed = false;
	      var coords = cursorCoords(cm, pos);
	      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
	      rect = {left: Math.min(coords.left, endCoords.left),
	              top: Math.min(coords.top, endCoords.top) - margin,
	              right: Math.max(coords.left, endCoords.left),
	              bottom: Math.max(coords.bottom, endCoords.bottom) + margin};
	      var scrollPos = calculateScrollPos(cm, rect);
	      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
	      if (scrollPos.scrollTop != null) {
	        updateScrollTop(cm, scrollPos.scrollTop);
	        if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; }
	      }
	      if (scrollPos.scrollLeft != null) {
	        setScrollLeft(cm, scrollPos.scrollLeft);
	        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; }
	      }
	      if (!changed) { break }
	    }
	    return rect
	  }

	  // Scroll a given set of coordinates into view (immediately).
	  function scrollIntoView(cm, rect) {
	    var scrollPos = calculateScrollPos(cm, rect);
	    if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); }
	    if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); }
	  }

	  // Calculate a new scroll position needed to scroll the given
	  // rectangle into view. Returns an object with scrollTop and
	  // scrollLeft properties. When these are undefined, the
	  // vertical/horizontal position does not need to be adjusted.
	  function calculateScrollPos(cm, rect) {
	    var display = cm.display, snapMargin = textHeight(cm.display);
	    if (rect.top < 0) { rect.top = 0; }
	    var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
	    var screen = displayHeight(cm), result = {};
	    if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; }
	    var docBottom = cm.doc.height + paddingVert(display);
	    var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin;
	    if (rect.top < screentop) {
	      result.scrollTop = atTop ? 0 : rect.top;
	    } else if (rect.bottom > screentop + screen) {
	      var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
	      if (newTop != screentop) { result.scrollTop = newTop; }
	    }

	    var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
	    var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
	    var tooWide = rect.right - rect.left > screenw;
	    if (tooWide) { rect.right = rect.left + screenw; }
	    if (rect.left < 10)
	      { result.scrollLeft = 0; }
	    else if (rect.left < screenleft)
	      { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); }
	    else if (rect.right > screenw + screenleft - 3)
	      { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
	    return result
	  }

	  // Store a relative adjustment to the scroll position in the current
	  // operation (to be applied when the operation finishes).
	  function addToScrollTop(cm, top) {
	    if (top == null) { return }
	    resolveScrollToPos(cm);
	    cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
	  }

	  // Make sure that at the end of the operation the current cursor is
	  // shown.
	  function ensureCursorVisible(cm) {
	    resolveScrollToPos(cm);
	    var cur = cm.getCursor();
	    cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin};
	  }

	  function scrollToCoords(cm, x, y) {
	    if (x != null || y != null) { resolveScrollToPos(cm); }
	    if (x != null) { cm.curOp.scrollLeft = x; }
	    if (y != null) { cm.curOp.scrollTop = y; }
	  }

	  function scrollToRange(cm, range$$1) {
	    resolveScrollToPos(cm);
	    cm.curOp.scrollToPos = range$$1;
	  }

	  // When an operation has its scrollToPos property set, and another
	  // scroll action is applied before the end of the operation, this
	  // 'simulates' scrolling that position into view in a cheap way, so
	  // that the effect of intermediate scroll commands is not ignored.
	  function resolveScrollToPos(cm) {
	    var range$$1 = cm.curOp.scrollToPos;
	    if (range$$1) {
	      cm.curOp.scrollToPos = null;
	      var from = estimateCoords(cm, range$$1.from), to = estimateCoords(cm, range$$1.to);
	      scrollToCoordsRange(cm, from, to, range$$1.margin);
	    }
	  }

	  function scrollToCoordsRange(cm, from, to, margin) {
	    var sPos = calculateScrollPos(cm, {
	      left: Math.min(from.left, to.left),
	      top: Math.min(from.top, to.top) - margin,
	      right: Math.max(from.right, to.right),
	      bottom: Math.max(from.bottom, to.bottom) + margin
	    });
	    scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop);
	  }

	  // Sync the scrollable area and scrollbars, ensure the viewport
	  // covers the visible area.
	  function updateScrollTop(cm, val) {
	    if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
	    if (!gecko) { updateDisplaySimple(cm, {top: val}); }
	    setScrollTop(cm, val, true);
	    if (gecko) { updateDisplaySimple(cm); }
	    startWorker(cm, 100);
	  }

	  function setScrollTop(cm, val, forceScroll) {
	    val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val);
	    if (cm.display.scroller.scrollTop == val && !forceScroll) { return }
	    cm.doc.scrollTop = val;
	    cm.display.scrollbars.setScrollTop(val);
	    if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; }
	  }

	  // Sync scroller and scrollbar, ensure the gutter elements are
	  // aligned.
	  function setScrollLeft(cm, val, isScroller, forceScroll) {
	    val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
	    if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return }
	    cm.doc.scrollLeft = val;
	    alignHorizontally(cm);
	    if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; }
	    cm.display.scrollbars.setScrollLeft(val);
	  }

	  // SCROLLBARS

	  // Prepare DOM reads needed to update the scrollbars. Done in one
	  // shot to minimize update/measure roundtrips.
	  function measureForScrollbars(cm) {
	    var d = cm.display, gutterW = d.gutters.offsetWidth;
	    var docH = Math.round(cm.doc.height + paddingVert(cm.display));
	    return {
	      clientHeight: d.scroller.clientHeight,
	      viewHeight: d.wrapper.clientHeight,
	      scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
	      viewWidth: d.wrapper.clientWidth,
	      barLeft: cm.options.fixedGutter ? gutterW : 0,
	      docHeight: docH,
	      scrollHeight: docH + scrollGap(cm) + d.barHeight,
	      nativeBarWidth: d.nativeBarWidth,
	      gutterWidth: gutterW
	    }
	  }

	  var NativeScrollbars = function(place, scroll, cm) {
	    this.cm = cm;
	    var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
	    var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
	    vert.tabIndex = horiz.tabIndex = -1;
	    place(vert); place(horiz);

	    on(vert, "scroll", function () {
	      if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); }
	    });
	    on(horiz, "scroll", function () {
	      if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); }
	    });

	    this.checkedZeroWidth = false;
	    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
	    if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; }
	  };

	  NativeScrollbars.prototype.update = function (measure) {
	    var needsH = measure.scrollWidth > measure.clientWidth + 1;
	    var needsV = measure.scrollHeight > measure.clientHeight + 1;
	    var sWidth = measure.nativeBarWidth;

	    if (needsV) {
	      this.vert.style.display = "block";
	      this.vert.style.bottom = needsH ? sWidth + "px" : "0";
	      var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
	      // A bug in IE8 can cause this value to be negative, so guard it.
	      this.vert.firstChild.style.height =
	        Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
	    } else {
	      this.vert.style.display = "";
	      this.vert.firstChild.style.height = "0";
	    }

	    if (needsH) {
	      this.horiz.style.display = "block";
	      this.horiz.style.right = needsV ? sWidth + "px" : "0";
	      this.horiz.style.left = measure.barLeft + "px";
	      var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
	      this.horiz.firstChild.style.width =
	        Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
	    } else {
	      this.horiz.style.display = "";
	      this.horiz.firstChild.style.width = "0";
	    }

	    if (!this.checkedZeroWidth && measure.clientHeight > 0) {
	      if (sWidth == 0) { this.zeroWidthHack(); }
	      this.checkedZeroWidth = true;
	    }

	    return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}
	  };

	  NativeScrollbars.prototype.setScrollLeft = function (pos) {
	    if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; }
	    if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); }
	  };

	  NativeScrollbars.prototype.setScrollTop = function (pos) {
	    if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; }
	    if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); }
	  };

	  NativeScrollbars.prototype.zeroWidthHack = function () {
	    var w = mac && !mac_geMountainLion ? "12px" : "18px";
	    this.horiz.style.height = this.vert.style.width = w;
	    this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none";
	    this.disableHoriz = new Delayed;
	    this.disableVert = new Delayed;
	  };

	  NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) {
	    bar.style.pointerEvents = "auto";
	    function maybeDisable() {
	      // To find out whether the scrollbar is still visible, we
	      // check whether the element under the pixel in the bottom
	      // right corner of the scrollbar box is the scrollbar box
	      // itself (when the bar is still visible) or its filler child
	      // (when the bar is hidden). If it is still visible, we keep
	      // it enabled, if it's hidden, we disable pointer events.
	      var box = bar.getBoundingClientRect();
	      var elt$$1 = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2)
	          : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1);
	      if (elt$$1 != bar) { bar.style.pointerEvents = "none"; }
	      else { delay.set(1000, maybeDisable); }
	    }
	    delay.set(1000, maybeDisable);
	  };

	  NativeScrollbars.prototype.clear = function () {
	    var parent = this.horiz.parentNode;
	    parent.removeChild(this.horiz);
	    parent.removeChild(this.vert);
	  };

	  var NullScrollbars = function () {};

	  NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };
	  NullScrollbars.prototype.setScrollLeft = function () {};
	  NullScrollbars.prototype.setScrollTop = function () {};
	  NullScrollbars.prototype.clear = function () {};

	  function updateScrollbars(cm, measure) {
	    if (!measure) { measure = measureForScrollbars(cm); }
	    var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
	    updateScrollbarsInner(cm, measure);
	    for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
	      if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
	        { updateHeightsInViewport(cm); }
	      updateScrollbarsInner(cm, measureForScrollbars(cm));
	      startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
	    }
	  }

	  // Re-synchronize the fake scrollbars with the actual size of the
	  // content.
	  function updateScrollbarsInner(cm, measure) {
	    var d = cm.display;
	    var sizes = d.scrollbars.update(measure);

	    d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
	    d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
	    d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent";

	    if (sizes.right && sizes.bottom) {
	      d.scrollbarFiller.style.display = "block";
	      d.scrollbarFiller.style.height = sizes.bottom + "px";
	      d.scrollbarFiller.style.width = sizes.right + "px";
	    } else { d.scrollbarFiller.style.display = ""; }
	    if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
	      d.gutterFiller.style.display = "block";
	      d.gutterFiller.style.height = sizes.bottom + "px";
	      d.gutterFiller.style.width = measure.gutterWidth + "px";
	    } else { d.gutterFiller.style.display = ""; }
	  }

	  var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};

	  function initScrollbars(cm) {
	    if (cm.display.scrollbars) {
	      cm.display.scrollbars.clear();
	      if (cm.display.scrollbars.addClass)
	        { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
	    }

	    cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {
	      cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
	      // Prevent clicks in the scrollbars from killing focus
	      on(node, "mousedown", function () {
	        if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); }
	      });
	      node.setAttribute("cm-not-content", "true");
	    }, function (pos, axis) {
	      if (axis == "horizontal") { setScrollLeft(cm, pos); }
	      else { updateScrollTop(cm, pos); }
	    }, cm);
	    if (cm.display.scrollbars.addClass)
	      { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
	  }

	  // Operations are used to wrap a series of changes to the editor
	  // state in such a way that each change won't have to update the
	  // cursor and display (which would be awkward, slow, and
	  // error-prone). Instead, display updates are batched and then all
	  // combined and executed at once.

	  var nextOpId = 0;
	  // Start a new operation.
	  function startOperation(cm) {
	    cm.curOp = {
	      cm: cm,
	      viewChanged: false,      // Flag that indicates that lines might need to be redrawn
	      startHeight: cm.doc.height, // Used to detect need to update scrollbar
	      forceUpdate: false,      // Used to force a redraw
	      updateInput: 0,       // Whether to reset the input textarea
	      typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
	      changeObjs: null,        // Accumulated changes, for firing change events
	      cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
	      cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
	      selectionChanged: false, // Whether the selection needs to be redrawn
	      updateMaxLine: false,    // Set when the widest line needs to be determined anew
	      scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
	      scrollToPos: null,       // Used to scroll to a specific position
	      focus: false,
	      id: ++nextOpId           // Unique ID
	    };
	    pushOperation(cm.curOp);
	  }

	  // Finish an operation, updating the display and signalling delayed events
	  function endOperation(cm) {
	    var op = cm.curOp;
	    if (op) { finishOperation(op, function (group) {
	      for (var i = 0; i < group.ops.length; i++)
	        { group.ops[i].cm.curOp = null; }
	      endOperations(group);
	    }); }
	  }

	  // The DOM updates done when an operation finishes are batched so
	  // that the minimum number of relayouts are required.
	  function endOperations(group) {
	    var ops = group.ops;
	    for (var i = 0; i < ops.length; i++) // Read DOM
	      { endOperation_R1(ops[i]); }
	    for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)
	      { endOperation_W1(ops[i$1]); }
	    for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM
	      { endOperation_R2(ops[i$2]); }
	    for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)
	      { endOperation_W2(ops[i$3]); }
	    for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM
	      { endOperation_finish(ops[i$4]); }
	  }

	  function endOperation_R1(op) {
	    var cm = op.cm, display = cm.display;
	    maybeClipScrollbars(cm);
	    if (op.updateMaxLine) { findMaxLine(cm); }

	    op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
	      op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
	                         op.scrollToPos.to.line >= display.viewTo) ||
	      display.maxLineChanged && cm.options.lineWrapping;
	    op.update = op.mustUpdate &&
	      new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
	  }

	  function endOperation_W1(op) {
	    op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
	  }

	  function endOperation_R2(op) {
	    var cm = op.cm, display = cm.display;
	    if (op.updatedDisplay) { updateHeightsInViewport(cm); }

	    op.barMeasure = measureForScrollbars(cm);

	    // If the max line changed since it was last measured, measure it,
	    // and ensure the document's width matches it.
	    // updateDisplay_W2 will use these properties to do the actual resizing
	    if (display.maxLineChanged && !cm.options.lineWrapping) {
	      op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
	      cm.display.sizerWidth = op.adjustWidthTo;
	      op.barMeasure.scrollWidth =
	        Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
	      op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
	    }

	    if (op.updatedDisplay || op.selectionChanged)
	      { op.preparedSelection = display.input.prepareSelection(); }
	  }

	  function endOperation_W2(op) {
	    var cm = op.cm;

	    if (op.adjustWidthTo != null) {
	      cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
	      if (op.maxScrollLeft < cm.doc.scrollLeft)
	        { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); }
	      cm.display.maxLineChanged = false;
	    }

	    var takeFocus = op.focus && op.focus == activeElt();
	    if (op.preparedSelection)
	      { cm.display.input.showSelection(op.preparedSelection, takeFocus); }
	    if (op.updatedDisplay || op.startHeight != cm.doc.height)
	      { updateScrollbars(cm, op.barMeasure); }
	    if (op.updatedDisplay)
	      { setDocumentHeight(cm, op.barMeasure); }

	    if (op.selectionChanged) { restartBlink(cm); }

	    if (cm.state.focused && op.updateInput)
	      { cm.display.input.reset(op.typing); }
	    if (takeFocus) { ensureFocus(op.cm); }
	  }

	  function endOperation_finish(op) {
	    var cm = op.cm, display = cm.display, doc = cm.doc;

	    if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); }

	    // Abort mouse wheel delta measurement, when scrolling explicitly
	    if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
	      { display.wheelStartX = display.wheelStartY = null; }

	    // Propagate the scroll position to the actual DOM scroller
	    if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); }

	    if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); }
	    // If we need to scroll a specific position into view, do so.
	    if (op.scrollToPos) {
	      var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
	                                   clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
	      maybeScrollWindow(cm, rect);
	    }

	    // Fire events for markers that are hidden/unidden by editing or
	    // undoing
	    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
	    if (hidden) { for (var i = 0; i < hidden.length; ++i)
	      { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } }
	    if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)
	      { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } }

	    if (display.wrapper.offsetHeight)
	      { doc.scrollTop = cm.display.scroller.scrollTop; }

	    // Fire change events, and delayed event handlers
	    if (op.changeObjs)
	      { signal(cm, "changes", cm, op.changeObjs); }
	    if (op.update)
	      { op.update.finish(); }
	  }

	  // Run the given function in an operation
	  function runInOp(cm, f) {
	    if (cm.curOp) { return f() }
	    startOperation(cm);
	    try { return f() }
	    finally { endOperation(cm); }
	  }
	  // Wraps a function in an operation. Returns the wrapped function.
	  function operation(cm, f) {
	    return function() {
	      if (cm.curOp) { return f.apply(cm, arguments) }
	      startOperation(cm);
	      try { return f.apply(cm, arguments) }
	      finally { endOperation(cm); }
	    }
	  }
	  // Used to add methods to editor and doc instances, wrapping them in
	  // operations.
	  function methodOp(f) {
	    return function() {
	      if (this.curOp) { return f.apply(this, arguments) }
	      startOperation(this);
	      try { return f.apply(this, arguments) }
	      finally { endOperation(this); }
	    }
	  }
	  function docMethodOp(f) {
	    return function() {
	      var cm = this.cm;
	      if (!cm || cm.curOp) { return f.apply(this, arguments) }
	      startOperation(cm);
	      try { return f.apply(this, arguments) }
	      finally { endOperation(cm); }
	    }
	  }

	  // Updates the display.view data structure for a given change to the
	  // document. From and to are in pre-change coordinates. Lendiff is
	  // the amount of lines added or subtracted by the change. This is
	  // used for changes that span multiple lines, or change the way
	  // lines are divided into visual lines. regLineChange (below)
	  // registers single-line changes.
	  function regChange(cm, from, to, lendiff) {
	    if (from == null) { from = cm.doc.first; }
	    if (to == null) { to = cm.doc.first + cm.doc.size; }
	    if (!lendiff) { lendiff = 0; }

	    var display = cm.display;
	    if (lendiff && to < display.viewTo &&
	        (display.updateLineNumbers == null || display.updateLineNumbers > from))
	      { display.updateLineNumbers = from; }

	    cm.curOp.viewChanged = true;

	    if (from >= display.viewTo) { // Change after
	      if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
	        { resetView(cm); }
	    } else if (to <= display.viewFrom) { // Change before
	      if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
	        resetView(cm);
	      } else {
	        display.viewFrom += lendiff;
	        display.viewTo += lendiff;
	      }
	    } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
	      resetView(cm);
	    } else if (from <= display.viewFrom) { // Top overlap
	      var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
	      if (cut) {
	        display.view = display.view.slice(cut.index);
	        display.viewFrom = cut.lineN;
	        display.viewTo += lendiff;
	      } else {
	        resetView(cm);
	      }
	    } else if (to >= display.viewTo) { // Bottom overlap
	      var cut$1 = viewCuttingPoint(cm, from, from, -1);
	      if (cut$1) {
	        display.view = display.view.slice(0, cut$1.index);
	        display.viewTo = cut$1.lineN;
	      } else {
	        resetView(cm);
	      }
	    } else { // Gap in the middle
	      var cutTop = viewCuttingPoint(cm, from, from, -1);
	      var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
	      if (cutTop && cutBot) {
	        display.view = display.view.slice(0, cutTop.index)
	          .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
	          .concat(display.view.slice(cutBot.index));
	        display.viewTo += lendiff;
	      } else {
	        resetView(cm);
	      }
	    }

	    var ext = display.externalMeasured;
	    if (ext) {
	      if (to < ext.lineN)
	        { ext.lineN += lendiff; }
	      else if (from < ext.lineN + ext.size)
	        { display.externalMeasured = null; }
	    }
	  }

	  // Register a change to a single line. Type must be one of "text",
	  // "gutter", "class", "widget"
	  function regLineChange(cm, line, type) {
	    cm.curOp.viewChanged = true;
	    var display = cm.display, ext = cm.display.externalMeasured;
	    if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
	      { display.externalMeasured = null; }

	    if (line < display.viewFrom || line >= display.viewTo) { return }
	    var lineView = display.view[findViewIndex(cm, line)];
	    if (lineView.node == null) { return }
	    var arr = lineView.changes || (lineView.changes = []);
	    if (indexOf(arr, type) == -1) { arr.push(type); }
	  }

	  // Clear the view.
	  function resetView(cm) {
	    cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
	    cm.display.view = [];
	    cm.display.viewOffset = 0;
	  }

	  function viewCuttingPoint(cm, oldN, newN, dir) {
	    var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
	    if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
	      { return {index: index, lineN: newN} }
	    var n = cm.display.viewFrom;
	    for (var i = 0; i < index; i++)
	      { n += view[i].size; }
	    if (n != oldN) {
	      if (dir > 0) {
	        if (index == view.length - 1) { return null }
	        diff = (n + view[index].size) - oldN;
	        index++;
	      } else {
	        diff = n - oldN;
	      }
	      oldN += diff; newN += diff;
	    }
	    while (visualLineNo(cm.doc, newN) != newN) {
	      if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
	      newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
	      index += dir;
	    }
	    return {index: index, lineN: newN}
	  }

	  // Force the view to cover a given range, adding empty view element
	  // or clipping off existing ones as needed.
	  function adjustView(cm, from, to) {
	    var display = cm.display, view = display.view;
	    if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
	      display.view = buildViewArray(cm, from, to);
	      display.viewFrom = from;
	    } else {
	      if (display.viewFrom > from)
	        { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); }
	      else if (display.viewFrom < from)
	        { display.view = display.view.slice(findViewIndex(cm, from)); }
	      display.viewFrom = from;
	      if (display.viewTo < to)
	        { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); }
	      else if (display.viewTo > to)
	        { display.view = display.view.slice(0, findViewIndex(cm, to)); }
	    }
	    display.viewTo = to;
	  }

	  // Count the number of lines in the view whose DOM representation is
	  // out of date (or nonexistent).
	  function countDirtyView(cm) {
	    var view = cm.display.view, dirty = 0;
	    for (var i = 0; i < view.length; i++) {
	      var lineView = view[i];
	      if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; }
	    }
	    return dirty
	  }

	  // HIGHLIGHT WORKER

	  function startWorker(cm, time) {
	    if (cm.doc.highlightFrontier < cm.display.viewTo)
	      { cm.state.highlight.set(time, bind(highlightWorker, cm)); }
	  }

	  function highlightWorker(cm) {
	    var doc = cm.doc;
	    if (doc.highlightFrontier >= cm.display.viewTo) { return }
	    var end = +new Date + cm.options.workTime;
	    var context = getContextBefore(cm, doc.highlightFrontier);
	    var changedLines = [];

	    doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
	      if (context.line >= cm.display.viewFrom) { // Visible
	        var oldStyles = line.styles;
	        var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null;
	        var highlighted = highlightLine(cm, line, context, true);
	        if (resetState) { context.state = resetState; }
	        line.styles = highlighted.styles;
	        var oldCls = line.styleClasses, newCls = highlighted.classes;
	        if (newCls) { line.styleClasses = newCls; }
	        else if (oldCls) { line.styleClasses = null; }
	        var ischange = !oldStyles || oldStyles.length != line.styles.length ||
	          oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
	        for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; }
	        if (ischange) { changedLines.push(context.line); }
	        line.stateAfter = context.save();
	        context.nextLine();
	      } else {
	        if (line.text.length <= cm.options.maxHighlightLength)
	          { processLine(cm, line.text, context); }
	        line.stateAfter = context.line % 5 == 0 ? context.save() : null;
	        context.nextLine();
	      }
	      if (+new Date > end) {
	        startWorker(cm, cm.options.workDelay);
	        return true
	      }
	    });
	    doc.highlightFrontier = context.line;
	    doc.modeFrontier = Math.max(doc.modeFrontier, context.line);
	    if (changedLines.length) { runInOp(cm, function () {
	      for (var i = 0; i < changedLines.length; i++)
	        { regLineChange(cm, changedLines[i], "text"); }
	    }); }
	  }

	  // DISPLAY DRAWING

	  var DisplayUpdate = function(cm, viewport, force) {
	    var display = cm.display;

	    this.viewport = viewport;
	    // Store some values that we'll need later (but don't want to force a relayout for)
	    this.visible = visibleLines(display, cm.doc, viewport);
	    this.editorIsHidden = !display.wrapper.offsetWidth;
	    this.wrapperHeight = display.wrapper.clientHeight;
	    this.wrapperWidth = display.wrapper.clientWidth;
	    this.oldDisplayWidth = displayWidth(cm);
	    this.force = force;
	    this.dims = getDimensions(cm);
	    this.events = [];
	  };

	  DisplayUpdate.prototype.signal = function (emitter, type) {
	    if (hasHandler(emitter, type))
	      { this.events.push(arguments); }
	  };
	  DisplayUpdate.prototype.finish = function () {
	      var this$1 = this;

	    for (var i = 0; i < this.events.length; i++)
	      { signal.apply(null, this$1.events[i]); }
	  };

	  function maybeClipScrollbars(cm) {
	    var display = cm.display;
	    if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
	      display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
	      display.heightForcer.style.height = scrollGap(cm) + "px";
	      display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
	      display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
	      display.scrollbarsClipped = true;
	    }
	  }

	  function selectionSnapshot(cm) {
	    if (cm.hasFocus()) { return null }
	    var active = activeElt();
	    if (!active || !contains(cm.display.lineDiv, active)) { return null }
	    var result = {activeElt: active};
	    if (window.getSelection) {
	      var sel = window.getSelection();
	      if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) {
	        result.anchorNode = sel.anchorNode;
	        result.anchorOffset = sel.anchorOffset;
	        result.focusNode = sel.focusNode;
	        result.focusOffset = sel.focusOffset;
	      }
	    }
	    return result
	  }

	  function restoreSelection(snapshot) {
	    if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return }
	    snapshot.activeElt.focus();
	    if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {
	      var sel = window.getSelection(), range$$1 = document.createRange();
	      range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset);
	      range$$1.collapse(false);
	      sel.removeAllRanges();
	      sel.addRange(range$$1);
	      sel.extend(snapshot.focusNode, snapshot.focusOffset);
	    }
	  }

	  // Does the actual updating of the line display. Bails out
	  // (returning false) when there is nothing to be done and forced is
	  // false.
	  function updateDisplayIfNeeded(cm, update) {
	    var display = cm.display, doc = cm.doc;

	    if (update.editorIsHidden) {
	      resetView(cm);
	      return false
	    }

	    // Bail out if the visible area is already rendered and nothing changed.
	    if (!update.force &&
	        update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
	        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
	        display.renderedView == display.view && countDirtyView(cm) == 0)
	      { return false }

	    if (maybeUpdateLineNumberWidth(cm)) {
	      resetView(cm);
	      update.dims = getDimensions(cm);
	    }

	    // Compute a suitable new viewport (from & to)
	    var end = doc.first + doc.size;
	    var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
	    var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
	    if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); }
	    if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); }
	    if (sawCollapsedSpans) {
	      from = visualLineNo(cm.doc, from);
	      to = visualLineEndNo(cm.doc, to);
	    }

	    var different = from != display.viewFrom || to != display.viewTo ||
	      display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
	    adjustView(cm, from, to);

	    display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
	    // Position the mover div to align with the current scroll position
	    cm.display.mover.style.top = display.viewOffset + "px";

	    var toUpdate = countDirtyView(cm);
	    if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
	        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
	      { return false }

	    // For big changes, we hide the enclosing element during the
	    // update, since that speeds up the operations on most browsers.
	    var selSnapshot = selectionSnapshot(cm);
	    if (toUpdate > 4) { display.lineDiv.style.display = "none"; }
	    patchDisplay(cm, display.updateLineNumbers, update.dims);
	    if (toUpdate > 4) { display.lineDiv.style.display = ""; }
	    display.renderedView = display.view;
	    // There might have been a widget with a focused element that got
	    // hidden or updated, if so re-focus it.
	    restoreSelection(selSnapshot);

	    // Prevent selection and cursors from interfering with the scroll
	    // width and height.
	    removeChildren(display.cursorDiv);
	    removeChildren(display.selectionDiv);
	    display.gutters.style.height = display.sizer.style.minHeight = 0;

	    if (different) {
	      display.lastWrapHeight = update.wrapperHeight;
	      display.lastWrapWidth = update.wrapperWidth;
	      startWorker(cm, 400);
	    }

	    display.updateLineNumbers = null;

	    return true
	  }

	  function postUpdateDisplay(cm, update) {
	    var viewport = update.viewport;

	    for (var first = true;; first = false) {
	      if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
	        // Clip forced viewport to actual scrollable area.
	        if (viewport && viewport.top != null)
	          { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; }
	        // Updated line heights might result in the drawn area not
	        // actually covering the viewport. Keep looping until it does.
	        update.visible = visibleLines(cm.display, cm.doc, viewport);
	        if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
	          { break }
	      }
	      if (!updateDisplayIfNeeded(cm, update)) { break }
	      updateHeightsInViewport(cm);
	      var barMeasure = measureForScrollbars(cm);
	      updateSelection(cm);
	      updateScrollbars(cm, barMeasure);
	      setDocumentHeight(cm, barMeasure);
	      update.force = false;
	    }

	    update.signal(cm, "update", cm);
	    if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
	      update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
	      cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
	    }
	  }

	  function updateDisplaySimple(cm, viewport) {
	    var update = new DisplayUpdate(cm, viewport);
	    if (updateDisplayIfNeeded(cm, update)) {
	      updateHeightsInViewport(cm);
	      postUpdateDisplay(cm, update);
	      var barMeasure = measureForScrollbars(cm);
	      updateSelection(cm);
	      updateScrollbars(cm, barMeasure);
	      setDocumentHeight(cm, barMeasure);
	      update.finish();
	    }
	  }

	  // Sync the actual display DOM structure with display.view, removing
	  // nodes for lines that are no longer in view, and creating the ones
	  // that are not there yet, and updating the ones that are out of
	  // date.
	  function patchDisplay(cm, updateNumbersFrom, dims) {
	    var display = cm.display, lineNumbers = cm.options.lineNumbers;
	    var container = display.lineDiv, cur = container.firstChild;

	    function rm(node) {
	      var next = node.nextSibling;
	      // Works around a throw-scroll bug in OS X Webkit
	      if (webkit && mac && cm.display.currentWheelTarget == node)
	        { node.style.display = "none"; }
	      else
	        { node.parentNode.removeChild(node); }
	      return next
	    }

	    var view = display.view, lineN = display.viewFrom;
	    // Loop over the elements in the view, syncing cur (the DOM nodes
	    // in display.lineDiv) with the view as we go.
	    for (var i = 0; i < view.length; i++) {
	      var lineView = view[i];
	      if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
	        var node = buildLineElement(cm, lineView, lineN, dims);
	        container.insertBefore(node, cur);
	      } else { // Already drawn
	        while (cur != lineView.node) { cur = rm(cur); }
	        var updateNumber = lineNumbers && updateNumbersFrom != null &&
	          updateNumbersFrom <= lineN && lineView.lineNumber;
	        if (lineView.changes) {
	          if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; }
	          updateLineForChanges(cm, lineView, lineN, dims);
	        }
	        if (updateNumber) {
	          removeChildren(lineView.lineNumber);
	          lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
	        }
	        cur = lineView.node.nextSibling;
	      }
	      lineN += lineView.size;
	    }
	    while (cur) { cur = rm(cur); }
	  }

	  function updateGutterSpace(cm) {
	    var width = cm.display.gutters.offsetWidth;
	    cm.display.sizer.style.marginLeft = width + "px";
	  }

	  function setDocumentHeight(cm, measure) {
	    cm.display.sizer.style.minHeight = measure.docHeight + "px";
	    cm.display.heightForcer.style.top = measure.docHeight + "px";
	    cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px";
	  }

	  // Rebuild the gutter elements, ensure the margin to the left of the
	  // code matches their width.
	  function updateGutters(cm) {
	    var gutters = cm.display.gutters, specs = cm.options.gutters;
	    removeChildren(gutters);
	    var i = 0;
	    for (; i < specs.length; ++i) {
	      var gutterClass = specs[i];
	      var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
	      if (gutterClass == "CodeMirror-linenumbers") {
	        cm.display.lineGutter = gElt;
	        gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
	      }
	    }
	    gutters.style.display = i ? "" : "none";
	    updateGutterSpace(cm);
	  }

	  // Make sure the gutters options contains the element
	  // "CodeMirror-linenumbers" when the lineNumbers option is true.
	  function setGuttersForLineNumbers(options) {
	    var found = indexOf(options.gutters, "CodeMirror-linenumbers");
	    if (found == -1 && options.lineNumbers) {
	      options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
	    } else if (found > -1 && !options.lineNumbers) {
	      options.gutters = options.gutters.slice(0);
	      options.gutters.splice(found, 1);
	    }
	  }

	  // Since the delta values reported on mouse wheel events are
	  // unstandardized between browsers and even browser versions, and
	  // generally horribly unpredictable, this code starts by measuring
	  // the scroll effect that the first few mouse wheel events have,
	  // and, from that, detects the way it can convert deltas to pixel
	  // offsets afterwards.
	  //
	  // The reason we want to know the amount a wheel event will scroll
	  // is that it gives us a chance to update the display before the
	  // actual scrolling happens, reducing flickering.

	  var wheelSamples = 0, wheelPixelsPerUnit = null;
	  // Fill in a browser-detected starting value on browsers where we
	  // know one. These don't have to be accurate -- the result of them
	  // being wrong would just be a slight flicker on the first wheel
	  // scroll (if it is large enough).
	  if (ie) { wheelPixelsPerUnit = -.53; }
	  else if (gecko) { wheelPixelsPerUnit = 15; }
	  else if (chrome) { wheelPixelsPerUnit = -.7; }
	  else if (safari) { wheelPixelsPerUnit = -1/3; }

	  function wheelEventDelta(e) {
	    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
	    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; }
	    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; }
	    else if (dy == null) { dy = e.wheelDelta; }
	    return {x: dx, y: dy}
	  }
	  function wheelEventPixels(e) {
	    var delta = wheelEventDelta(e);
	    delta.x *= wheelPixelsPerUnit;
	    delta.y *= wheelPixelsPerUnit;
	    return delta
	  }

	  function onScrollWheel(cm, e) {
	    var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;

	    var display = cm.display, scroll = display.scroller;
	    // Quit if there's nothing to scroll here
	    var canScrollX = scroll.scrollWidth > scroll.clientWidth;
	    var canScrollY = scroll.scrollHeight > scroll.clientHeight;
	    if (!(dx && canScrollX || dy && canScrollY)) { return }

	    // Webkit browsers on OS X abort momentum scrolls when the target
	    // of the scroll event is removed from the scrollable element.
	    // This hack (see related code in patchDisplay) makes sure the
	    // element is kept around.
	    if (dy && mac && webkit) {
	      outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
	        for (var i = 0; i < view.length; i++) {
	          if (view[i].node == cur) {
	            cm.display.currentWheelTarget = cur;
	            break outer
	          }
	        }
	      }
	    }

	    // On some browsers, horizontal scrolling will cause redraws to
	    // happen before the gutter has been realigned, causing it to
	    // wriggle around in a most unseemly way. When we have an
	    // estimated pixels/delta value, we just handle horizontal
	    // scrolling entirely here. It'll be slightly off from native, but
	    // better than glitching out.
	    if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
	      if (dy && canScrollY)
	        { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); }
	      setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit));
	      // Only prevent default scrolling if vertical scrolling is
	      // actually possible. Otherwise, it causes vertical scroll
	      // jitter on OSX trackpads when deltaX is small and deltaY
	      // is large (issue #3579)
	      if (!dy || (dy && canScrollY))
	        { e_preventDefault(e); }
	      display.wheelStartX = null; // Abort measurement, if in progress
	      return
	    }

	    // 'Project' the visible viewport to cover the area that is being
	    // scrolled into view (if we know enough to estimate it).
	    if (dy && wheelPixelsPerUnit != null) {
	      var pixels = dy * wheelPixelsPerUnit;
	      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
	      if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
	      else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
	      updateDisplaySimple(cm, {top: top, bottom: bot});
	    }

	    if (wheelSamples < 20) {
	      if (display.wheelStartX == null) {
	        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
	        display.wheelDX = dx; display.wheelDY = dy;
	        setTimeout(function () {
	          if (display.wheelStartX == null) { return }
	          var movedX = scroll.scrollLeft - display.wheelStartX;
	          var movedY = scroll.scrollTop - display.wheelStartY;
	          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
	            (movedX && display.wheelDX && movedX / display.wheelDX);
	          display.wheelStartX = display.wheelStartY = null;
	          if (!sample) { return }
	          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
	          ++wheelSamples;
	        }, 200);
	      } else {
	        display.wheelDX += dx; display.wheelDY += dy;
	      }
	    }
	  }

	  // Selection objects are immutable. A new one is created every time
	  // the selection changes. A selection is one or more non-overlapping
	  // (and non-touching) ranges, sorted, and an integer that indicates
	  // which one is the primary selection (the one that's scrolled into
	  // view, that getCursor returns, etc).
	  var Selection = function(ranges, primIndex) {
	    this.ranges = ranges;
	    this.primIndex = primIndex;
	  };

	  Selection.prototype.primary = function () { return this.ranges[this.primIndex] };

	  Selection.prototype.equals = function (other) {
	      var this$1 = this;

	    if (other == this) { return true }
	    if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
	    for (var i = 0; i < this.ranges.length; i++) {
	      var here = this$1.ranges[i], there = other.ranges[i];
	      if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false }
	    }
	    return true
	  };

	  Selection.prototype.deepCopy = function () {
	      var this$1 = this;

	    var out = [];
	    for (var i = 0; i < this.ranges.length; i++)
	      { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)); }
	    return new Selection(out, this.primIndex)
	  };

	  Selection.prototype.somethingSelected = function () {
	      var this$1 = this;

	    for (var i = 0; i < this.ranges.length; i++)
	      { if (!this$1.ranges[i].empty()) { return true } }
	    return false
	  };

	  Selection.prototype.contains = function (pos, end) {
	      var this$1 = this;

	    if (!end) { end = pos; }
	    for (var i = 0; i < this.ranges.length; i++) {
	      var range = this$1.ranges[i];
	      if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
	        { return i }
	    }
	    return -1
	  };

	  var Range = function(anchor, head) {
	    this.anchor = anchor; this.head = head;
	  };

	  Range.prototype.from = function () { return minPos(this.anchor, this.head) };
	  Range.prototype.to = function () { return maxPos(this.anchor, this.head) };
	  Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch };

	  // Take an unsorted, potentially overlapping set of ranges, and
	  // build a selection out of it. 'Consumes' ranges array (modifying
	  // it).
	  function normalizeSelection(cm, ranges, primIndex) {
	    var mayTouch = cm && cm.options.selectionsMayTouch;
	    var prim = ranges[primIndex];
	    ranges.sort(function (a, b) { return cmp(a.from(), b.from()); });
	    primIndex = indexOf(ranges, prim);
	    for (var i = 1; i < ranges.length; i++) {
	      var cur = ranges[i], prev = ranges[i - 1];
	      var diff = cmp(prev.to(), cur.from());
	      if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) {
	        var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
	        var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
	        if (i <= primIndex) { --primIndex; }
	        ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
	      }
	    }
	    return new Selection(ranges, primIndex)
	  }

	  function simpleSelection(anchor, head) {
	    return new Selection([new Range(anchor, head || anchor)], 0)
	  }

	  // Compute the position of the end of a change (its 'to' property
	  // refers to the pre-change end).
	  function changeEnd(change) {
	    if (!change.text) { return change.to }
	    return Pos(change.from.line + change.text.length - 1,
	               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))
	  }

	  // Adjust a position to refer to the post-change position of the
	  // same text, or the end of the change if the change covers it.
	  function adjustForChange(pos, change) {
	    if (cmp(pos, change.from) < 0) { return pos }
	    if (cmp(pos, change.to) <= 0) { return changeEnd(change) }

	    var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
	    if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; }
	    return Pos(line, ch)
	  }

	  function computeSelAfterChange(doc, change) {
	    var out = [];
	    for (var i = 0; i < doc.sel.ranges.length; i++) {
	      var range = doc.sel.ranges[i];
	      out.push(new Range(adjustForChange(range.anchor, change),
	                         adjustForChange(range.head, change)));
	    }
	    return normalizeSelection(doc.cm, out, doc.sel.primIndex)
	  }

	  function offsetPos(pos, old, nw) {
	    if (pos.line == old.line)
	      { return Pos(nw.line, pos.ch - old.ch + nw.ch) }
	    else
	      { return Pos(nw.line + (pos.line - old.line), pos.ch) }
	  }

	  // Used by replaceSelections to allow moving the selection to the
	  // start or around the replaced test. Hint may be "start" or "around".
	  function computeReplacedSel(doc, changes, hint) {
	    var out = [];
	    var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
	    for (var i = 0; i < changes.length; i++) {
	      var change = changes[i];
	      var from = offsetPos(change.from, oldPrev, newPrev);
	      var to = offsetPos(changeEnd(change), oldPrev, newPrev);
	      oldPrev = change.to;
	      newPrev = to;
	      if (hint == "around") {
	        var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
	        out[i] = new Range(inv ? to : from, inv ? from : to);
	      } else {
	        out[i] = new Range(from, from);
	      }
	    }
	    return new Selection(out, doc.sel.primIndex)
	  }

	  // Used to get the editor into a consistent state again when options change.

	  function loadMode(cm) {
	    cm.doc.mode = getMode(cm.options, cm.doc.modeOption);
	    resetModeState(cm);
	  }

	  function resetModeState(cm) {
	    cm.doc.iter(function (line) {
	      if (line.stateAfter) { line.stateAfter = null; }
	      if (line.styles) { line.styles = null; }
	    });
	    cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first;
	    startWorker(cm, 100);
	    cm.state.modeGen++;
	    if (cm.curOp) { regChange(cm); }
	  }

	  // DOCUMENT DATA STRUCTURE

	  // By default, updates that start and end at the beginning of a line
	  // are treated specially, in order to make the association of line
	  // widgets and marker elements with the text behave more intuitive.
	  function isWholeLineUpdate(doc, change) {
	    return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
	      (!doc.cm || doc.cm.options.wholeLineUpdateBefore)
	  }

	  // Perform a change on the document data structure.
	  function updateDoc(doc, change, markedSpans, estimateHeight$$1) {
	    function spansFor(n) {return markedSpans ? markedSpans[n] : null}
	    function update(line, text, spans) {
	      updateLine(line, text, spans, estimateHeight$$1);
	      signalLater(line, "change", line, change);
	    }
	    function linesFor(start, end) {
	      var result = [];
	      for (var i = start; i < end; ++i)
	        { result.push(new Line(text[i], spansFor(i), estimateHeight$$1)); }
	      return result
	    }

	    var from = change.from, to = change.to, text = change.text;
	    var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
	    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;

	    // Adjust the line structure
	    if (change.full) {
	      doc.insert(0, linesFor(0, text.length));
	      doc.remove(text.length, doc.size - text.length);
	    } else if (isWholeLineUpdate(doc, change)) {
	      // This is a whole-line replace. Treated specially to make
	      // sure line objects move the way they are supposed to.
	      var added = linesFor(0, text.length - 1);
	      update(lastLine, lastLine.text, lastSpans);
	      if (nlines) { doc.remove(from.line, nlines); }
	      if (added.length) { doc.insert(from.line, added); }
	    } else if (firstLine == lastLine) {
	      if (text.length == 1) {
	        update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
	      } else {
	        var added$1 = linesFor(1, text.length - 1);
	        added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight$$1));
	        update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
	        doc.insert(from.line + 1, added$1);
	      }
	    } else if (text.length == 1) {
	      update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
	      doc.remove(from.line + 1, nlines);
	    } else {
	      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
	      update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
	      var added$2 = linesFor(1, text.length - 1);
	      if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); }
	      doc.insert(from.line + 1, added$2);
	    }

	    signalLater(doc, "change", doc, change);
	  }

	  // Call f for all linked documents.
	  function linkedDocs(doc, f, sharedHistOnly) {
	    function propagate(doc, skip, sharedHist) {
	      if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {
	        var rel = doc.linked[i];
	        if (rel.doc == skip) { continue }
	        var shared = sharedHist && rel.sharedHist;
	        if (sharedHistOnly && !shared) { continue }
	        f(rel.doc, shared);
	        propagate(rel.doc, doc, shared);
	      } }
	    }
	    propagate(doc, null, true);
	  }

	  // Attach a document to an editor.
	  function attachDoc(cm, doc) {
	    if (doc.cm) { throw new Error("This document is already in use.") }
	    cm.doc = doc;
	    doc.cm = cm;
	    estimateLineHeights(cm);
	    loadMode(cm);
	    setDirectionClass(cm);
	    if (!cm.options.lineWrapping) { findMaxLine(cm); }
	    cm.options.mode = doc.modeOption;
	    regChange(cm);
	  }

	  function setDirectionClass(cm) {
	  (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl");
	  }

	  function directionChanged(cm) {
	    runInOp(cm, function () {
	      setDirectionClass(cm);
	      regChange(cm);
	    });
	  }

	  function History(startGen) {
	    // Arrays of change events and selections. Doing something adds an
	    // event to done and clears undo. Undoing moves events from done
	    // to undone, redoing moves them in the other direction.
	    this.done = []; this.undone = [];
	    this.undoDepth = Infinity;
	    // Used to track when changes can be merged into a single undo
	    // event
	    this.lastModTime = this.lastSelTime = 0;
	    this.lastOp = this.lastSelOp = null;
	    this.lastOrigin = this.lastSelOrigin = null;
	    // Used by the isClean() method
	    this.generation = this.maxGeneration = startGen || 1;
	  }

	  // Create a history change event from an updateDoc-style change
	  // object.
	  function historyChangeFromChange(doc, change) {
	    var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
	    attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
	    linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true);
	    return histChange
	  }

	  // Pop all selection events off the end of a history array. Stop at
	  // a change event.
	  function clearSelectionEvents(array) {
	    while (array.length) {
	      var last = lst(array);
	      if (last.ranges) { array.pop(); }
	      else { break }
	    }
	  }

	  // Find the top change event in the history. Pop off selection
	  // events that are in the way.
	  function lastChangeEvent(hist, force) {
	    if (force) {
	      clearSelectionEvents(hist.done);
	      return lst(hist.done)
	    } else if (hist.done.length && !lst(hist.done).ranges) {
	      return lst(hist.done)
	    } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
	      hist.done.pop();
	      return lst(hist.done)
	    }
	  }

	  // Register a change in the history. Merges changes that are within
	  // a single operation, or are close together with an origin that
	  // allows merging (starting with "+") into a single event.
	  function addChangeToHistory(doc, change, selAfter, opId) {
	    var hist = doc.history;
	    hist.undone.length = 0;
	    var time = +new Date, cur;
	    var last;

	    if ((hist.lastOp == opId ||
	         hist.lastOrigin == change.origin && change.origin &&
	         ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
	          change.origin.charAt(0) == "*")) &&
	        (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
	      // Merge this change into the last event
	      last = lst(cur.changes);
	      if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
	        // Optimized case for simple insertion -- don't want to add
	        // new changesets for every character typed
	        last.to = changeEnd(change);
	      } else {
	        // Add new sub-event
	        cur.changes.push(historyChangeFromChange(doc, change));
	      }
	    } else {
	      // Can not be merged, start a new event.
	      var before = lst(hist.done);
	      if (!before || !before.ranges)
	        { pushSelectionToHistory(doc.sel, hist.done); }
	      cur = {changes: [historyChangeFromChange(doc, change)],
	             generation: hist.generation};
	      hist.done.push(cur);
	      while (hist.done.length > hist.undoDepth) {
	        hist.done.shift();
	        if (!hist.done[0].ranges) { hist.done.shift(); }
	      }
	    }
	    hist.done.push(selAfter);
	    hist.generation = ++hist.maxGeneration;
	    hist.lastModTime = hist.lastSelTime = time;
	    hist.lastOp = hist.lastSelOp = opId;
	    hist.lastOrigin = hist.lastSelOrigin = change.origin;

	    if (!last) { signal(doc, "historyAdded"); }
	  }

	  function selectionEventCanBeMerged(doc, origin, prev, sel) {
	    var ch = origin.charAt(0);
	    return ch == "*" ||
	      ch == "+" &&
	      prev.ranges.length == sel.ranges.length &&
	      prev.somethingSelected() == sel.somethingSelected() &&
	      new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
	  }

	  // Called whenever the selection changes, sets the new selection as
	  // the pending selection in the history, and pushes the old pending
	  // selection into the 'done' array when it was significantly
	  // different (in number of selected ranges, emptiness, or time).
	  function addSelectionToHistory(doc, sel, opId, options) {
	    var hist = doc.history, origin = options && options.origin;

	    // A new event is started when the previous origin does not match
	    // the current, or the origins don't allow matching. Origins
	    // starting with * are always merged, those starting with + are
	    // merged when similar and close together in time.
	    if (opId == hist.lastSelOp ||
	        (origin && hist.lastSelOrigin == origin &&
	         (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
	          selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
	      { hist.done[hist.done.length - 1] = sel; }
	    else
	      { pushSelectionToHistory(sel, hist.done); }

	    hist.lastSelTime = +new Date;
	    hist.lastSelOrigin = origin;
	    hist.lastSelOp = opId;
	    if (options && options.clearRedo !== false)
	      { clearSelectionEvents(hist.undone); }
	  }

	  function pushSelectionToHistory(sel, dest) {
	    var top = lst(dest);
	    if (!(top && top.ranges && top.equals(sel)))
	      { dest.push(sel); }
	  }

	  // Used to store marked span information in the history.
	  function attachLocalSpans(doc, change, from, to) {
	    var existing = change["spans_" + doc.id], n = 0;
	    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {
	      if (line.markedSpans)
	        { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; }
	      ++n;
	    });
	  }

	  // When un/re-doing restores text containing marked spans, those
	  // that have been explicitly cleared should not be restored.
	  function removeClearedSpans(spans) {
	    if (!spans) { return null }
	    var out;
	    for (var i = 0; i < spans.length; ++i) {
	      if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } }
	      else if (out) { out.push(spans[i]); }
	    }
	    return !out ? spans : out.length ? out : null
	  }

	  // Retrieve and filter the old marked spans stored in a change event.
	  function getOldSpans(doc, change) {
	    var found = change["spans_" + doc.id];
	    if (!found) { return null }
	    var nw = [];
	    for (var i = 0; i < change.text.length; ++i)
	      { nw.push(removeClearedSpans(found[i])); }
	    return nw
	  }

	  // Used for un/re-doing changes from the history. Combines the
	  // result of computing the existing spans with the set of spans that
	  // existed in the history (so that deleting around a span and then
	  // undoing brings back the span).
	  function mergeOldSpans(doc, change) {
	    var old = getOldSpans(doc, change);
	    var stretched = stretchSpansOverChange(doc, change);
	    if (!old) { return stretched }
	    if (!stretched) { return old }

	    for (var i = 0; i < old.length; ++i) {
	      var oldCur = old[i], stretchCur = stretched[i];
	      if (oldCur && stretchCur) {
	        spans: for (var j = 0; j < stretchCur.length; ++j) {
	          var span = stretchCur[j];
	          for (var k = 0; k < oldCur.length; ++k)
	            { if (oldCur[k].marker == span.marker) { continue spans } }
	          oldCur.push(span);
	        }
	      } else if (stretchCur) {
	        old[i] = stretchCur;
	      }
	    }
	    return old
	  }

	  // Used both to provide a JSON-safe object in .getHistory, and, when
	  // detaching a document, to split the history in two
	  function copyHistoryArray(events, newGroup, instantiateSel) {
	    var copy = [];
	    for (var i = 0; i < events.length; ++i) {
	      var event = events[i];
	      if (event.ranges) {
	        copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
	        continue
	      }
	      var changes = event.changes, newChanges = [];
	      copy.push({changes: newChanges});
	      for (var j = 0; j < changes.length; ++j) {
	        var change = changes[j], m = (void 0);
	        newChanges.push({from: change.from, to: change.to, text: change.text});
	        if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) {
	          if (indexOf(newGroup, Number(m[1])) > -1) {
	            lst(newChanges)[prop] = change[prop];
	            delete change[prop];
	          }
	        } } }
	      }
	    }
	    return copy
	  }

	  // The 'scroll' parameter given to many of these indicated whether
	  // the new cursor position should be scrolled into view after
	  // modifying the selection.

	  // If shift is held or the extend flag is set, extends a range to
	  // include a given position (and optionally a second position).
	  // Otherwise, simply returns the range between the given positions.
	  // Used for cursor motion and such.
	  function extendRange(range, head, other, extend) {
	    if (extend) {
	      var anchor = range.anchor;
	      if (other) {
	        var posBefore = cmp(head, anchor) < 0;
	        if (posBefore != (cmp(other, anchor) < 0)) {
	          anchor = head;
	          head = other;
	        } else if (posBefore != (cmp(head, other) < 0)) {
	          head = other;
	        }
	      }
	      return new Range(anchor, head)
	    } else {
	      return new Range(other || head, head)
	    }
	  }

	  // Extend the primary selection range, discard the rest.
	  function extendSelection(doc, head, other, options, extend) {
	    if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); }
	    setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options);
	  }

	  // Extend all selections (pos is an array of selections with length
	  // equal the number of selections)
	  function extendSelections(doc, heads, options) {
	    var out = [];
	    var extend = doc.cm && (doc.cm.display.shift || doc.extend);
	    for (var i = 0; i < doc.sel.ranges.length; i++)
	      { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); }
	    var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex);
	    setSelection(doc, newSel, options);
	  }

	  // Updates a single range in the selection.
	  function replaceOneSelection(doc, i, range, options) {
	    var ranges = doc.sel.ranges.slice(0);
	    ranges[i] = range;
	    setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options);
	  }

	  // Reset the selection to a single range.
	  function setSimpleSelection(doc, anchor, head, options) {
	    setSelection(doc, simpleSelection(anchor, head), options);
	  }

	  // Give beforeSelectionChange handlers a change to influence a
	  // selection update.
	  function filterSelectionChange(doc, sel, options) {
	    var obj = {
	      ranges: sel.ranges,
	      update: function(ranges) {
	        var this$1 = this;

	        this.ranges = [];
	        for (var i = 0; i < ranges.length; i++)
	          { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
	                                     clipPos(doc, ranges[i].head)); }
	      },
	      origin: options && options.origin
	    };
	    signal(doc, "beforeSelectionChange", doc, obj);
	    if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); }
	    if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) }
	    else { return sel }
	  }

	  function setSelectionReplaceHistory(doc, sel, options) {
	    var done = doc.history.done, last = lst(done);
	    if (last && last.ranges) {
	      done[done.length - 1] = sel;
	      setSelectionNoUndo(doc, sel, options);
	    } else {
	      setSelection(doc, sel, options);
	    }
	  }

	  // Set a new selection.
	  function setSelection(doc, sel, options) {
	    setSelectionNoUndo(doc, sel, options);
	    addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
	  }

	  function setSelectionNoUndo(doc, sel, options) {
	    if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
	      { sel = filterSelectionChange(doc, sel, options); }

	    var bias = options && options.bias ||
	      (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
	    setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));

	    if (!(options && options.scroll === false) && doc.cm)
	      { ensureCursorVisible(doc.cm); }
	  }

	  function setSelectionInner(doc, sel) {
	    if (sel.equals(doc.sel)) { return }

	    doc.sel = sel;

	    if (doc.cm) {
	      doc.cm.curOp.updateInput = 1;
	      doc.cm.curOp.selectionChanged = true;
	      signalCursorActivity(doc.cm);
	    }
	    signalLater(doc, "cursorActivity", doc);
	  }

	  // Verify that the selection does not partially select any atomic
	  // marked ranges.
	  function reCheckSelection(doc) {
	    setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false));
	  }

	  // Return a selection that does not partially select any atomic
	  // ranges.
	  function skipAtomicInSelection(doc, sel, bias, mayClear) {
	    var out;
	    for (var i = 0; i < sel.ranges.length; i++) {
	      var range = sel.ranges[i];
	      var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
	      var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
	      var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);
	      if (out || newAnchor != range.anchor || newHead != range.head) {
	        if (!out) { out = sel.ranges.slice(0, i); }
	        out[i] = new Range(newAnchor, newHead);
	      }
	    }
	    return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel
	  }

	  function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
	    var line = getLine(doc, pos.line);
	    if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
	      var sp = line.markedSpans[i], m = sp.marker;
	      if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
	          (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
	        if (mayClear) {
	          signal(m, "beforeCursorEnter");
	          if (m.explicitlyCleared) {
	            if (!line.markedSpans) { break }
	            else {--i; continue}
	          }
	        }
	        if (!m.atomic) { continue }

	        if (oldPos) {
	          var near = m.find(dir < 0 ? 1 : -1), diff = (void 0);
	          if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft)
	            { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); }
	          if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
	            { return skipAtomicInner(doc, near, pos, dir, mayClear) }
	        }

	        var far = m.find(dir < 0 ? -1 : 1);
	        if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight)
	          { far = movePos(doc, far, dir, far.line == pos.line ? line : null); }
	        return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null
	      }
	    } }
	    return pos
	  }

	  // Ensure a given position is not inside an atomic range.
	  function skipAtomic(doc, pos, oldPos, bias, mayClear) {
	    var dir = bias || 1;
	    var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
	        (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
	        skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
	        (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));
	    if (!found) {
	      doc.cantEdit = true;
	      return Pos(doc.first, 0)
	    }
	    return found
	  }

	  function movePos(doc, pos, dir, line) {
	    if (dir < 0 && pos.ch == 0) {
	      if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }
	      else { return null }
	    } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
	      if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }
	      else { return null }
	    } else {
	      return new Pos(pos.line, pos.ch + dir)
	    }
	  }

	  function selectAll(cm) {
	    cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);
	  }

	  // UPDATING

	  // Allow "beforeChange" event handlers to influence a change
	  function filterChange(doc, change, update) {
	    var obj = {
	      canceled: false,
	      from: change.from,
	      to: change.to,
	      text: change.text,
	      origin: change.origin,
	      cancel: function () { return obj.canceled = true; }
	    };
	    if (update) { obj.update = function (from, to, text, origin) {
	      if (from) { obj.from = clipPos(doc, from); }
	      if (to) { obj.to = clipPos(doc, to); }
	      if (text) { obj.text = text; }
	      if (origin !== undefined) { obj.origin = origin; }
	    }; }
	    signal(doc, "beforeChange", doc, obj);
	    if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); }

	    if (obj.canceled) {
	      if (doc.cm) { doc.cm.curOp.updateInput = 2; }
	      return null
	    }
	    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}
	  }

	  // Apply a change to a document, and add it to the document's
	  // history, and propagating it to all linked documents.
	  function makeChange(doc, change, ignoreReadOnly) {
	    if (doc.cm) {
	      if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }
	      if (doc.cm.state.suppressEdits) { return }
	    }

	    if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
	      change = filterChange(doc, change, true);
	      if (!change) { return }
	    }

	    // Possibly split or suppress the update based on the presence
	    // of read-only spans in its range.
	    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
	    if (split) {
	      for (var i = split.length - 1; i >= 0; --i)
	        { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); }
	    } else {
	      makeChangeInner(doc, change);
	    }
	  }

	  function makeChangeInner(doc, change) {
	    if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return }
	    var selAfter = computeSelAfterChange(doc, change);
	    addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);

	    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
	    var rebased = [];

	    linkedDocs(doc, function (doc, sharedHist) {
	      if (!sharedHist && indexOf(rebased, doc.history) == -1) {
	        rebaseHist(doc.history, change);
	        rebased.push(doc.history);
	      }
	      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
	    });
	  }

	  // Revert a change stored in a document's history.
	  function makeChangeFromHistory(doc, type, allowSelectionOnly) {
	    var suppress = doc.cm && doc.cm.state.suppressEdits;
	    if (suppress && !allowSelectionOnly) { return }

	    var hist = doc.history, event, selAfter = doc.sel;
	    var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;

	    // Verify that there is a useable event (so that ctrl-z won't
	    // needlessly clear selection events)
	    var i = 0;
	    for (; i < source.length; i++) {
	      event = source[i];
	      if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
	        { break }
	    }
	    if (i == source.length) { return }
	    hist.lastOrigin = hist.lastSelOrigin = null;

	    for (;;) {
	      event = source.pop();
	      if (event.ranges) {
	        pushSelectionToHistory(event, dest);
	        if (allowSelectionOnly && !event.equals(doc.sel)) {
	          setSelection(doc, event, {clearRedo: false});
	          return
	        }
	        selAfter = event;
	      } else if (suppress) {
	        source.push(event);
	        return
	      } else { break }
	    }

	    // Build up a reverse change object to add to the opposite history
	    // stack (redo when undoing, and vice versa).
	    var antiChanges = [];
	    pushSelectionToHistory(selAfter, dest);
	    dest.push({changes: antiChanges, generation: hist.generation});
	    hist.generation = event.generation || ++hist.maxGeneration;

	    var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");

	    var loop = function ( i ) {
	      var change = event.changes[i];
	      change.origin = type;
	      if (filter && !filterChange(doc, change, false)) {
	        source.length = 0;
	        return {}
	      }

	      antiChanges.push(historyChangeFromChange(doc, change));

	      var after = i ? computeSelAfterChange(doc, change) : lst(source);
	      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
	      if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); }
	      var rebased = [];

	      // Propagate to the linked documents
	      linkedDocs(doc, function (doc, sharedHist) {
	        if (!sharedHist && indexOf(rebased, doc.history) == -1) {
	          rebaseHist(doc.history, change);
	          rebased.push(doc.history);
	        }
	        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
	      });
	    };

	    for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {
	      var returned = loop( i$1 );

	      if ( returned ) return returned.v;
	    }
	  }

	  // Sub-views need their line numbers shifted when text is added
	  // above or below them in the parent document.
	  function shiftDoc(doc, distance) {
	    if (distance == 0) { return }
	    doc.first += distance;
	    doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(
	      Pos(range.anchor.line + distance, range.anchor.ch),
	      Pos(range.head.line + distance, range.head.ch)
	    ); }), doc.sel.primIndex);
	    if (doc.cm) {
	      regChange(doc.cm, doc.first, doc.first - distance, distance);
	      for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
	        { regLineChange(doc.cm, l, "gutter"); }
	    }
	  }

	  // More lower-level change function, handling only a single document
	  // (not linked ones).
	  function makeChangeSingleDoc(doc, change, selAfter, spans) {
	    if (doc.cm && !doc.cm.curOp)
	      { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }

	    if (change.to.line < doc.first) {
	      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
	      return
	    }
	    if (change.from.line > doc.lastLine()) { return }

	    // Clip the change to the size of this doc
	    if (change.from.line < doc.first) {
	      var shift = change.text.length - 1 - (doc.first - change.from.line);
	      shiftDoc(doc, shift);
	      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
	                text: [lst(change.text)], origin: change.origin};
	    }
	    var last = doc.lastLine();
	    if (change.to.line > last) {
	      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
	                text: [change.text[0]], origin: change.origin};
	    }

	    change.removed = getBetween(doc, change.from, change.to);

	    if (!selAfter) { selAfter = computeSelAfterChange(doc, change); }
	    if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); }
	    else { updateDoc(doc, change, spans); }
	    setSelectionNoUndo(doc, selAfter, sel_dontScroll);
	  }

	  // Handle the interaction of a change to a document with the editor
	  // that this document is part of.
	  function makeChangeSingleDocInEditor(cm, change, spans) {
	    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;

	    var recomputeMaxLength = false, checkWidthStart = from.line;
	    if (!cm.options.lineWrapping) {
	      checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
	      doc.iter(checkWidthStart, to.line + 1, function (line) {
	        if (line == display.maxLine) {
	          recomputeMaxLength = true;
	          return true
	        }
	      });
	    }

	    if (doc.sel.contains(change.from, change.to) > -1)
	      { signalCursorActivity(cm); }

	    updateDoc(doc, change, spans, estimateHeight(cm));

	    if (!cm.options.lineWrapping) {
	      doc.iter(checkWidthStart, from.line + change.text.length, function (line) {
	        var len = lineLength(line);
	        if (len > display.maxLineLength) {
	          display.maxLine = line;
	          display.maxLineLength = len;
	          display.maxLineChanged = true;
	          recomputeMaxLength = false;
	        }
	      });
	      if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; }
	    }

	    retreatFrontier(doc, from.line);
	    startWorker(cm, 400);

	    var lendiff = change.text.length - (to.line - from.line) - 1;
	    // Remember that these lines changed, for updating the display
	    if (change.full)
	      { regChange(cm); }
	    else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
	      { regLineChange(cm, from.line, "text"); }
	    else
	      { regChange(cm, from.line, to.line + 1, lendiff); }

	    var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
	    if (changeHandler || changesHandler) {
	      var obj = {
	        from: from, to: to,
	        text: change.text,
	        removed: change.removed,
	        origin: change.origin
	      };
	      if (changeHandler) { signalLater(cm, "change", cm, obj); }
	      if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); }
	    }
	    cm.display.selForContextMenu = null;
	  }

	  function replaceRange(doc, code, from, to, origin) {
	    var assign;

	    if (!to) { to = from; }
	    if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); }
	    if (typeof code == "string") { code = doc.splitLines(code); }
	    makeChange(doc, {from: from, to: to, text: code, origin: origin});
	  }

	  // Rebasing/resetting history to deal with externally-sourced changes

	  function rebaseHistSelSingle(pos, from, to, diff) {
	    if (to < pos.line) {
	      pos.line += diff;
	    } else if (from < pos.line) {
	      pos.line = from;
	      pos.ch = 0;
	    }
	  }

	  // Tries to rebase an array of history events given a change in the
	  // document. If the change touches the same lines as the event, the
	  // event, and everything 'behind' it, is discarded. If the change is
	  // before the event, the event's positions are updated. Uses a
	  // copy-on-write scheme for the positions, to avoid having to
	  // reallocate them all on every rebase, but also avoid problems with
	  // shared position objects being unsafely updated.
	  function rebaseHistArray(array, from, to, diff) {
	    for (var i = 0; i < array.length; ++i) {
	      var sub = array[i], ok = true;
	      if (sub.ranges) {
	        if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
	        for (var j = 0; j < sub.ranges.length; j++) {
	          rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
	          rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
	        }
	        continue
	      }
	      for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {
	        var cur = sub.changes[j$1];
	        if (to < cur.from.line) {
	          cur.from = Pos(cur.from.line + diff, cur.from.ch);
	          cur.to = Pos(cur.to.line + diff, cur.to.ch);
	        } else if (from <= cur.to.line) {
	          ok = false;
	          break
	        }
	      }
	      if (!ok) {
	        array.splice(0, i + 1);
	        i = 0;
	      }
	    }
	  }

	  function rebaseHist(hist, change) {
	    var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
	    rebaseHistArray(hist.done, from, to, diff);
	    rebaseHistArray(hist.undone, from, to, diff);
	  }

	  // Utility for applying a change to a line by handle or number,
	  // returning the number and optionally registering the line as
	  // changed.
	  function changeLine(doc, handle, changeType, op) {
	    var no = handle, line = handle;
	    if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); }
	    else { no = lineNo(handle); }
	    if (no == null) { return null }
	    if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); }
	    return line
	  }

	  // The document is represented as a BTree consisting of leaves, with
	  // chunk of lines in them, and branches, with up to ten leaves or
	  // other branch nodes below them. The top node is always a branch
	  // node, and is the document object itself (meaning it has
	  // additional methods and properties).
	  //
	  // All nodes have parent links. The tree is used both to go from
	  // line numbers to line objects, and to go from objects to numbers.
	  // It also indexes by height, and is used to convert between height
	  // and line object, and to find the total height of the document.
	  //
	  // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html

	  function LeafChunk(lines) {
	    var this$1 = this;

	    this.lines = lines;
	    this.parent = null;
	    var height = 0;
	    for (var i = 0; i < lines.length; ++i) {
	      lines[i].parent = this$1;
	      height += lines[i].height;
	    }
	    this.height = height;
	  }

	  LeafChunk.prototype = {
	    chunkSize: function() { return this.lines.length },

	    // Remove the n lines at offset 'at'.
	    removeInner: function(at, n) {
	      var this$1 = this;

	      for (var i = at, e = at + n; i < e; ++i) {
	        var line = this$1.lines[i];
	        this$1.height -= line.height;
	        cleanUpLine(line);
	        signalLater(line, "delete");
	      }
	      this.lines.splice(at, n);
	    },

	    // Helper used to collapse a small branch into a single leaf.
	    collapse: function(lines) {
	      lines.push.apply(lines, this.lines);
	    },

	    // Insert the given array of lines at offset 'at', count them as
	    // having the given height.
	    insertInner: function(at, lines, height) {
	      var this$1 = this;

	      this.height += height;
	      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
	      for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1; }
	    },

	    // Used to iterate over a part of the tree.
	    iterN: function(at, n, op) {
	      var this$1 = this;

	      for (var e = at + n; at < e; ++at)
	        { if (op(this$1.lines[at])) { return true } }
	    }
	  };

	  function BranchChunk(children) {
	    var this$1 = this;

	    this.children = children;
	    var size = 0, height = 0;
	    for (var i = 0; i < children.length; ++i) {
	      var ch = children[i];
	      size += ch.chunkSize(); height += ch.height;
	      ch.parent = this$1;
	    }
	    this.size = size;
	    this.height = height;
	    this.parent = null;
	  }

	  BranchChunk.prototype = {
	    chunkSize: function() { return this.size },

	    removeInner: function(at, n) {
	      var this$1 = this;

	      this.size -= n;
	      for (var i = 0; i < this.children.length; ++i) {
	        var child = this$1.children[i], sz = child.chunkSize();
	        if (at < sz) {
	          var rm = Math.min(n, sz - at), oldHeight = child.height;
	          child.removeInner(at, rm);
	          this$1.height -= oldHeight - child.height;
	          if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null; }
	          if ((n -= rm) == 0) { break }
	          at = 0;
	        } else { at -= sz; }
	      }
	      // If the result is smaller than 25 lines, ensure that it is a
	      // single leaf node.
	      if (this.size - n < 25 &&
	          (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
	        var lines = [];
	        this.collapse(lines);
	        this.children = [new LeafChunk(lines)];
	        this.children[0].parent = this;
	      }
	    },

	    collapse: function(lines) {
	      var this$1 = this;

	      for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines); }
	    },

	    insertInner: function(at, lines, height) {
	      var this$1 = this;

	      this.size += lines.length;
	      this.height += height;
	      for (var i = 0; i < this.children.length; ++i) {
	        var child = this$1.children[i], sz = child.chunkSize();
	        if (at <= sz) {
	          child.insertInner(at, lines, height);
	          if (child.lines && child.lines.length > 50) {
	            // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
	            // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
	            var remaining = child.lines.length % 25 + 25;
	            for (var pos = remaining; pos < child.lines.length;) {
	              var leaf = new LeafChunk(child.lines.slice(pos, pos += 25));
	              child.height -= leaf.height;
	              this$1.children.splice(++i, 0, leaf);
	              leaf.parent = this$1;
	            }
	            child.lines = child.lines.slice(0, remaining);
	            this$1.maybeSpill();
	          }
	          break
	        }
	        at -= sz;
	      }
	    },

	    // When a node has grown, check whether it should be split.
	    maybeSpill: function() {
	      if (this.children.length <= 10) { return }
	      var me = this;
	      do {
	        var spilled = me.children.splice(me.children.length - 5, 5);
	        var sibling = new BranchChunk(spilled);
	        if (!me.parent) { // Become the parent node
	          var copy = new BranchChunk(me.children);
	          copy.parent = me;
	          me.children = [copy, sibling];
	          me = copy;
	       } else {
	          me.size -= sibling.size;
	          me.height -= sibling.height;
	          var myIndex = indexOf(me.parent.children, me);
	          me.parent.children.splice(myIndex + 1, 0, sibling);
	        }
	        sibling.parent = me.parent;
	      } while (me.children.length > 10)
	      me.parent.maybeSpill();
	    },

	    iterN: function(at, n, op) {
	      var this$1 = this;

	      for (var i = 0; i < this.children.length; ++i) {
	        var child = this$1.children[i], sz = child.chunkSize();
	        if (at < sz) {
	          var used = Math.min(n, sz - at);
	          if (child.iterN(at, used, op)) { return true }
	          if ((n -= used) == 0) { break }
	          at = 0;
	        } else { at -= sz; }
	      }
	    }
	  };

	  // Line widgets are block elements displayed above or below a line.

	  var LineWidget = function(doc, node, options) {
	    var this$1 = this;

	    if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
	      { this$1[opt] = options[opt]; } } }
	    this.doc = doc;
	    this.node = node;
	  };

	  LineWidget.prototype.clear = function () {
	      var this$1 = this;

	    var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
	    if (no == null || !ws) { return }
	    for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1); } }
	    if (!ws.length) { line.widgets = null; }
	    var height = widgetHeight(this);
	    updateLineHeight(line, Math.max(0, line.height - height));
	    if (cm) {
	      runInOp(cm, function () {
	        adjustScrollWhenAboveVisible(cm, line, -height);
	        regLineChange(cm, no, "widget");
	      });
	      signalLater(cm, "lineWidgetCleared", cm, this, no);
	    }
	  };

	  LineWidget.prototype.changed = function () {
	      var this$1 = this;

	    var oldH = this.height, cm = this.doc.cm, line = this.line;
	    this.height = null;
	    var diff = widgetHeight(this) - oldH;
	    if (!diff) { return }
	    if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); }
	    if (cm) {
	      runInOp(cm, function () {
	        cm.curOp.forceUpdate = true;
	        adjustScrollWhenAboveVisible(cm, line, diff);
	        signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line));
	      });
	    }
	  };
	  eventMixin(LineWidget);

	  function adjustScrollWhenAboveVisible(cm, line, diff) {
	    if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
	      { addToScrollTop(cm, diff); }
	  }

	  function addLineWidget(doc, handle, node, options) {
	    var widget = new LineWidget(doc, node, options);
	    var cm = doc.cm;
	    if (cm && widget.noHScroll) { cm.display.alignWidgets = true; }
	    changeLine(doc, handle, "widget", function (line) {
	      var widgets = line.widgets || (line.widgets = []);
	      if (widget.insertAt == null) { widgets.push(widget); }
	      else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); }
	      widget.line = line;
	      if (cm && !lineIsHidden(doc, line)) {
	        var aboveVisible = heightAtLine(line) < doc.scrollTop;
	        updateLineHeight(line, line.height + widgetHeight(widget));
	        if (aboveVisible) { addToScrollTop(cm, widget.height); }
	        cm.curOp.forceUpdate = true;
	      }
	      return true
	    });
	    if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); }
	    return widget
	  }

	  // TEXTMARKERS

	  // Created with markText and setBookmark methods. A TextMarker is a
	  // handle that can be used to clear or find a marked position in the
	  // document. Line objects hold arrays (markedSpans) containing
	  // {from, to, marker} object pointing to such marker objects, and
	  // indicating that such a marker is present on that line. Multiple
	  // lines may point to the same marker when it spans across lines.
	  // The spans will have null for their from/to properties when the
	  // marker continues beyond the start/end of the line. Markers have
	  // links back to the lines they currently touch.

	  // Collapsed markers have unique ids, in order to be able to order
	  // them, which is needed for uniquely determining an outer marker
	  // when they overlap (they may nest, but not partially overlap).
	  var nextMarkerId = 0;

	  var TextMarker = function(doc, type) {
	    this.lines = [];
	    this.type = type;
	    this.doc = doc;
	    this.id = ++nextMarkerId;
	  };

	  // Clear the marker.
	  TextMarker.prototype.clear = function () {
	      var this$1 = this;

	    if (this.explicitlyCleared) { return }
	    var cm = this.doc.cm, withOp = cm && !cm.curOp;
	    if (withOp) { startOperation(cm); }
	    if (hasHandler(this, "clear")) {
	      var found = this.find();
	      if (found) { signalLater(this, "clear", found.from, found.to); }
	    }
	    var min = null, max = null;
	    for (var i = 0; i < this.lines.length; ++i) {
	      var line = this$1.lines[i];
	      var span = getMarkedSpanFor(line.markedSpans, this$1);
	      if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text"); }
	      else if (cm) {
	        if (span.to != null) { max = lineNo(line); }
	        if (span.from != null) { min = lineNo(line); }
	      }
	      line.markedSpans = removeMarkedSpan(line.markedSpans, span);
	      if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm)
	        { updateLineHeight(line, textHeight(cm.display)); }
	    }
	    if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
	      var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual);
	      if (len > cm.display.maxLineLength) {
	        cm.display.maxLine = visual;
	        cm.display.maxLineLength = len;
	        cm.display.maxLineChanged = true;
	      }
	    } }

	    if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); }
	    this.lines.length = 0;
	    this.explicitlyCleared = true;
	    if (this.atomic && this.doc.cantEdit) {
	      this.doc.cantEdit = false;
	      if (cm) { reCheckSelection(cm.doc); }
	    }
	    if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); }
	    if (withOp) { endOperation(cm); }
	    if (this.parent) { this.parent.clear(); }
	  };

	  // Find the position of the marker in the document. Returns a {from,
	  // to} object by default. Side can be passed to get a specific side
	  // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
	  // Pos objects returned contain a line object, rather than a line
	  // number (used to prevent looking up the same line twice).
	  TextMarker.prototype.find = function (side, lineObj) {
	      var this$1 = this;

	    if (side == null && this.type == "bookmark") { side = 1; }
	    var from, to;
	    for (var i = 0; i < this.lines.length; ++i) {
	      var line = this$1.lines[i];
	      var span = getMarkedSpanFor(line.markedSpans, this$1);
	      if (span.from != null) {
	        from = Pos(lineObj ? line : lineNo(line), span.from);
	        if (side == -1) { return from }
	      }
	      if (span.to != null) {
	        to = Pos(lineObj ? line : lineNo(line), span.to);
	        if (side == 1) { return to }
	      }
	    }
	    return from && {from: from, to: to}
	  };

	  // Signals that the marker's widget changed, and surrounding layout
	  // should be recomputed.
	  TextMarker.prototype.changed = function () {
	      var this$1 = this;

	    var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
	    if (!pos || !cm) { return }
	    runInOp(cm, function () {
	      var line = pos.line, lineN = lineNo(pos.line);
	      var view = findViewForLine(cm, lineN);
	      if (view) {
	        clearLineMeasurementCacheFor(view);
	        cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
	      }
	      cm.curOp.updateMaxLine = true;
	      if (!lineIsHidden(widget.doc, line) && widget.height != null) {
	        var oldHeight = widget.height;
	        widget.height = null;
	        var dHeight = widgetHeight(widget) - oldHeight;
	        if (dHeight)
	          { updateLineHeight(line, line.height + dHeight); }
	      }
	      signalLater(cm, "markerChanged", cm, this$1);
	    });
	  };

	  TextMarker.prototype.attachLine = function (line) {
	    if (!this.lines.length && this.doc.cm) {
	      var op = this.doc.cm.curOp;
	      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
	        { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); }
	    }
	    this.lines.push(line);
	  };

	  TextMarker.prototype.detachLine = function (line) {
	    this.lines.splice(indexOf(this.lines, line), 1);
	    if (!this.lines.length && this.doc.cm) {
	      var op = this.doc.cm.curOp
	      ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
	    }
	  };
	  eventMixin(TextMarker);

	  // Create a marker, wire it up to the right lines, and
	  function markText(doc, from, to, options, type) {
	    // Shared markers (across linked documents) are handled separately
	    // (markTextShared will call out to this again, once per
	    // document).
	    if (options && options.shared) { return markTextShared(doc, from, to, options, type) }
	    // Ensure we are in an operation.
	    if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }

	    var marker = new TextMarker(doc, type), diff = cmp(from, to);
	    if (options) { copyObj(options, marker, false); }
	    // Don't connect empty markers unless clearWhenEmpty is false
	    if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
	      { return marker }
	    if (marker.replacedWith) {
	      // Showing up as a widget implies collapsed (widget replaces text)
	      marker.collapsed = true;
	      marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget");
	      if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); }
	      if (options.insertLeft) { marker.widgetNode.insertLeft = true; }
	    }
	    if (marker.collapsed) {
	      if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
	          from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
	        { throw new Error("Inserting collapsed marker partially overlapping an existing one") }
	      seeCollapsedSpans();
	    }

	    if (marker.addToHistory)
	      { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); }

	    var curLine = from.line, cm = doc.cm, updateMaxLine;
	    doc.iter(curLine, to.line + 1, function (line) {
	      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
	        { updateMaxLine = true; }
	      if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }
	      addMarkedSpan(line, new MarkedSpan(marker,
	                                         curLine == from.line ? from.ch : null,
	                                         curLine == to.line ? to.ch : null));
	      ++curLine;
	    });
	    // lineIsHidden depends on the presence of the spans, so needs a second pass
	    if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
	      if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); }
	    }); }

	    if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); }

	    if (marker.readOnly) {
	      seeReadOnlySpans();
	      if (doc.history.done.length || doc.history.undone.length)
	        { doc.clearHistory(); }
	    }
	    if (marker.collapsed) {
	      marker.id = ++nextMarkerId;
	      marker.atomic = true;
	    }
	    if (cm) {
	      // Sync editor state
	      if (updateMaxLine) { cm.curOp.updateMaxLine = true; }
	      if (marker.collapsed)
	        { regChange(cm, from.line, to.line + 1); }
	      else if (marker.className || marker.startStyle || marker.endStyle || marker.css ||
	               marker.attributes || marker.title)
	        { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } }
	      if (marker.atomic) { reCheckSelection(cm.doc); }
	      signalLater(cm, "markerAdded", cm, marker);
	    }
	    return marker
	  }

	  // SHARED TEXTMARKERS

	  // A shared marker spans multiple linked documents. It is
	  // implemented as a meta-marker-object controlling multiple normal
	  // markers.
	  var SharedTextMarker = function(markers, primary) {
	    var this$1 = this;

	    this.markers = markers;
	    this.primary = primary;
	    for (var i = 0; i < markers.length; ++i)
	      { markers[i].parent = this$1; }
	  };

	  SharedTextMarker.prototype.clear = function () {
	      var this$1 = this;

	    if (this.explicitlyCleared) { return }
	    this.explicitlyCleared = true;
	    for (var i = 0; i < this.markers.length; ++i)
	      { this$1.markers[i].clear(); }
	    signalLater(this, "clear");
	  };

	  SharedTextMarker.prototype.find = function (side, lineObj) {
	    return this.primary.find(side, lineObj)
	  };
	  eventMixin(SharedTextMarker);

	  function markTextShared(doc, from, to, options, type) {
	    options = copyObj(options);
	    options.shared = false;
	    var markers = [markText(doc, from, to, options, type)], primary = markers[0];
	    var widget = options.widgetNode;
	    linkedDocs(doc, function (doc) {
	      if (widget) { options.widgetNode = widget.cloneNode(true); }
	      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
	      for (var i = 0; i < doc.linked.length; ++i)
	        { if (doc.linked[i].isParent) { return } }
	      primary = lst(markers);
	    });
	    return new SharedTextMarker(markers, primary)
	  }

	  function findSharedMarkers(doc) {
	    return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })
	  }

	  function copySharedMarkers(doc, markers) {
	    for (var i = 0; i < markers.length; i++) {
	      var marker = markers[i], pos = marker.find();
	      var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
	      if (cmp(mFrom, mTo)) {
	        var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
	        marker.markers.push(subMark);
	        subMark.parent = marker;
	      }
	    }
	  }

	  function detachSharedMarkers(markers) {
	    var loop = function ( i ) {
	      var marker = markers[i], linked = [marker.primary.doc];
	      linkedDocs(marker.primary.doc, function (d) { return linked.push(d); });
	      for (var j = 0; j < marker.markers.length; j++) {
	        var subMarker = marker.markers[j];
	        if (indexOf(linked, subMarker.doc) == -1) {
	          subMarker.parent = null;
	          marker.markers.splice(j--, 1);
	        }
	      }
	    };

	    for (var i = 0; i < markers.length; i++) loop( i );
	  }

	  var nextDocId = 0;
	  var Doc = function(text, mode, firstLine, lineSep, direction) {
	    if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) }
	    if (firstLine == null) { firstLine = 0; }

	    BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
	    this.first = firstLine;
	    this.scrollTop = this.scrollLeft = 0;
	    this.cantEdit = false;
	    this.cleanGeneration = 1;
	    this.modeFrontier = this.highlightFrontier = firstLine;
	    var start = Pos(firstLine, 0);
	    this.sel = simpleSelection(start);
	    this.history = new History(null);
	    this.id = ++nextDocId;
	    this.modeOption = mode;
	    this.lineSep = lineSep;
	    this.direction = (direction == "rtl") ? "rtl" : "ltr";
	    this.extend = false;

	    if (typeof text == "string") { text = this.splitLines(text); }
	    updateDoc(this, {from: start, to: start, text: text});
	    setSelection(this, simpleSelection(start), sel_dontScroll);
	  };

	  Doc.prototype = createObj(BranchChunk.prototype, {
	    constructor: Doc,
	    // Iterate over the document. Supports two forms -- with only one
	    // argument, it calls that for each line in the document. With
	    // three, it iterates over the range given by the first two (with
	    // the second being non-inclusive).
	    iter: function(from, to, op) {
	      if (op) { this.iterN(from - this.first, to - from, op); }
	      else { this.iterN(this.first, this.first + this.size, from); }
	    },

	    // Non-public interface for adding and removing lines.
	    insert: function(at, lines) {
	      var height = 0;
	      for (var i = 0; i < lines.length; ++i) { height += lines[i].height; }
	      this.insertInner(at - this.first, lines, height);
	    },
	    remove: function(at, n) { this.removeInner(at - this.first, n); },

	    // From here, the methods are part of the public interface. Most
	    // are also available from CodeMirror (editor) instances.

	    getValue: function(lineSep) {
	      var lines = getLines(this, this.first, this.first + this.size);
	      if (lineSep === false) { return lines }
	      return lines.join(lineSep || this.lineSeparator())
	    },
	    setValue: docMethodOp(function(code) {
	      var top = Pos(this.first, 0), last = this.first + this.size - 1;
	      makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
	                        text: this.splitLines(code), origin: "setValue", full: true}, true);
	      if (this.cm) { scrollToCoords(this.cm, 0, 0); }
	      setSelection(this, simpleSelection(top), sel_dontScroll);
	    }),
	    replaceRange: function(code, from, to, origin) {
	      from = clipPos(this, from);
	      to = to ? clipPos(this, to) : from;
	      replaceRange(this, code, from, to, origin);
	    },
	    getRange: function(from, to, lineSep) {
	      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
	      if (lineSep === false) { return lines }
	      return lines.join(lineSep || this.lineSeparator())
	    },

	    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},

	    getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},
	    getLineNumber: function(line) {return lineNo(line)},

	    getLineHandleVisualStart: function(line) {
	      if (typeof line == "number") { line = getLine(this, line); }
	      return visualLine(line)
	    },

	    lineCount: function() {return this.size},
	    firstLine: function() {return this.first},
	    lastLine: function() {return this.first + this.size - 1},

	    clipPos: function(pos) {return clipPos(this, pos)},

	    getCursor: function(start) {
	      var range$$1 = this.sel.primary(), pos;
	      if (start == null || start == "head") { pos = range$$1.head; }
	      else if (start == "anchor") { pos = range$$1.anchor; }
	      else if (start == "end" || start == "to" || start === false) { pos = range$$1.to(); }
	      else { pos = range$$1.from(); }
	      return pos
	    },
	    listSelections: function() { return this.sel.ranges },
	    somethingSelected: function() {return this.sel.somethingSelected()},

	    setCursor: docMethodOp(function(line, ch, options) {
	      setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
	    }),
	    setSelection: docMethodOp(function(anchor, head, options) {
	      setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
	    }),
	    extendSelection: docMethodOp(function(head, other, options) {
	      extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
	    }),
	    extendSelections: docMethodOp(function(heads, options) {
	      extendSelections(this, clipPosArray(this, heads), options);
	    }),
	    extendSelectionsBy: docMethodOp(function(f, options) {
	      var heads = map(this.sel.ranges, f);
	      extendSelections(this, clipPosArray(this, heads), options);
	    }),
	    setSelections: docMethodOp(function(ranges, primary, options) {
	      var this$1 = this;

	      if (!ranges.length) { return }
	      var out = [];
	      for (var i = 0; i < ranges.length; i++)
	        { out[i] = new Range(clipPos(this$1, ranges[i].anchor),
	                           clipPos(this$1, ranges[i].head)); }
	      if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }
	      setSelection(this, normalizeSelection(this.cm, out, primary), options);
	    }),
	    addSelection: docMethodOp(function(anchor, head, options) {
	      var ranges = this.sel.ranges.slice(0);
	      ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
	      setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options);
	    }),

	    getSelection: function(lineSep) {
	      var this$1 = this;

	      var ranges = this.sel.ranges, lines;
	      for (var i = 0; i < ranges.length; i++) {
	        var sel = getBetween(this$1, ranges[i].from(), ranges[i].to());
	        lines = lines ? lines.concat(sel) : sel;
	      }
	      if (lineSep === false) { return lines }
	      else { return lines.join(lineSep || this.lineSeparator()) }
	    },
	    getSelections: function(lineSep) {
	      var this$1 = this;

	      var parts = [], ranges = this.sel.ranges;
	      for (var i = 0; i < ranges.length; i++) {
	        var sel = getBetween(this$1, ranges[i].from(), ranges[i].to());
	        if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()); }
	        parts[i] = sel;
	      }
	      return parts
	    },
	    replaceSelection: function(code, collapse, origin) {
	      var dup = [];
	      for (var i = 0; i < this.sel.ranges.length; i++)
	        { dup[i] = code; }
	      this.replaceSelections(dup, collapse, origin || "+input");
	    },
	    replaceSelections: docMethodOp(function(code, collapse, origin) {
	      var this$1 = this;

	      var changes = [], sel = this.sel;
	      for (var i = 0; i < sel.ranges.length; i++) {
	        var range$$1 = sel.ranges[i];
	        changes[i] = {from: range$$1.from(), to: range$$1.to(), text: this$1.splitLines(code[i]), origin: origin};
	      }
	      var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
	      for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
	        { makeChange(this$1, changes[i$1]); }
	      if (newSel) { setSelectionReplaceHistory(this, newSel); }
	      else if (this.cm) { ensureCursorVisible(this.cm); }
	    }),
	    undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
	    redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
	    undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
	    redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),

	    setExtending: function(val) {this.extend = val;},
	    getExtending: function() {return this.extend},

	    historySize: function() {
	      var hist = this.history, done = 0, undone = 0;
	      for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } }
	      for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } }
	      return {undo: done, redo: undone}
	    },
	    clearHistory: function() {this.history = new History(this.history.maxGeneration);},

	    markClean: function() {
	      this.cleanGeneration = this.changeGeneration(true);
	    },
	    changeGeneration: function(forceSplit) {
	      if (forceSplit)
	        { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; }
	      return this.history.generation
	    },
	    isClean: function (gen) {
	      return this.history.generation == (gen || this.cleanGeneration)
	    },

	    getHistory: function() {
	      return {done: copyHistoryArray(this.history.done),
	              undone: copyHistoryArray(this.history.undone)}
	    },
	    setHistory: function(histData) {
	      var hist = this.history = new History(this.history.maxGeneration);
	      hist.done = copyHistoryArray(histData.done.slice(0), null, true);
	      hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
	    },

	    setGutterMarker: docMethodOp(function(line, gutterID, value) {
	      return changeLine(this, line, "gutter", function (line) {
	        var markers = line.gutterMarkers || (line.gutterMarkers = {});
	        markers[gutterID] = value;
	        if (!value && isEmpty(markers)) { line.gutterMarkers = null; }
	        return true
	      })
	    }),

	    clearGutter: docMethodOp(function(gutterID) {
	      var this$1 = this;

	      this.iter(function (line) {
	        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
	          changeLine(this$1, line, "gutter", function () {
	            line.gutterMarkers[gutterID] = null;
	            if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; }
	            return true
	          });
	        }
	      });
	    }),

	    lineInfo: function(line) {
	      var n;
	      if (typeof line == "number") {
	        if (!isLine(this, line)) { return null }
	        n = line;
	        line = getLine(this, line);
	        if (!line) { return null }
	      } else {
	        n = lineNo(line);
	        if (n == null) { return null }
	      }
	      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
	              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
	              widgets: line.widgets}
	    },

	    addLineClass: docMethodOp(function(handle, where, cls) {
	      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
	        var prop = where == "text" ? "textClass"
	                 : where == "background" ? "bgClass"
	                 : where == "gutter" ? "gutterClass" : "wrapClass";
	        if (!line[prop]) { line[prop] = cls; }
	        else if (classTest(cls).test(line[prop])) { return false }
	        else { line[prop] += " " + cls; }
	        return true
	      })
	    }),
	    removeLineClass: docMethodOp(function(handle, where, cls) {
	      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
	        var prop = where == "text" ? "textClass"
	                 : where == "background" ? "bgClass"
	                 : where == "gutter" ? "gutterClass" : "wrapClass";
	        var cur = line[prop];
	        if (!cur) { return false }
	        else if (cls == null) { line[prop] = null; }
	        else {
	          var found = cur.match(classTest(cls));
	          if (!found) { return false }
	          var end = found.index + found[0].length;
	          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
	        }
	        return true
	      })
	    }),

	    addLineWidget: docMethodOp(function(handle, node, options) {
	      return addLineWidget(this, handle, node, options)
	    }),
	    removeLineWidget: function(widget) { widget.clear(); },

	    markText: function(from, to, options) {
	      return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range")
	    },
	    setBookmark: function(pos, options) {
	      var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
	                      insertLeft: options && options.insertLeft,
	                      clearWhenEmpty: false, shared: options && options.shared,
	                      handleMouseEvents: options && options.handleMouseEvents};
	      pos = clipPos(this, pos);
	      return markText(this, pos, pos, realOpts, "bookmark")
	    },
	    findMarksAt: function(pos) {
	      pos = clipPos(this, pos);
	      var markers = [], spans = getLine(this, pos.line).markedSpans;
	      if (spans) { for (var i = 0; i < spans.length; ++i) {
	        var span = spans[i];
	        if ((span.from == null || span.from <= pos.ch) &&
	            (span.to == null || span.to >= pos.ch))
	          { markers.push(span.marker.parent || span.marker); }
	      } }
	      return markers
	    },
	    findMarks: function(from, to, filter) {
	      from = clipPos(this, from); to = clipPos(this, to);
	      var found = [], lineNo$$1 = from.line;
	      this.iter(from.line, to.line + 1, function (line) {
	        var spans = line.markedSpans;
	        if (spans) { for (var i = 0; i < spans.length; i++) {
	          var span = spans[i];
	          if (!(span.to != null && lineNo$$1 == from.line && from.ch >= span.to ||
	                span.from == null && lineNo$$1 != from.line ||
	                span.from != null && lineNo$$1 == to.line && span.from >= to.ch) &&
	              (!filter || filter(span.marker)))
	            { found.push(span.marker.parent || span.marker); }
	        } }
	        ++lineNo$$1;
	      });
	      return found
	    },
	    getAllMarks: function() {
	      var markers = [];
	      this.iter(function (line) {
	        var sps = line.markedSpans;
	        if (sps) { for (var i = 0; i < sps.length; ++i)
	          { if (sps[i].from != null) { markers.push(sps[i].marker); } } }
	      });
	      return markers
	    },

	    posFromIndex: function(off) {
	      var ch, lineNo$$1 = this.first, sepSize = this.lineSeparator().length;
	      this.iter(function (line) {
	        var sz = line.text.length + sepSize;
	        if (sz > off) { ch = off; return true }
	        off -= sz;
	        ++lineNo$$1;
	      });
	      return clipPos(this, Pos(lineNo$$1, ch))
	    },
	    indexFromPos: function (coords) {
	      coords = clipPos(this, coords);
	      var index = coords.ch;
	      if (coords.line < this.first || coords.ch < 0) { return 0 }
	      var sepSize = this.lineSeparator().length;
	      this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value
	        index += line.text.length + sepSize;
	      });
	      return index
	    },

	    copy: function(copyHistory) {
	      var doc = new Doc(getLines(this, this.first, this.first + this.size),
	                        this.modeOption, this.first, this.lineSep, this.direction);
	      doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
	      doc.sel = this.sel;
	      doc.extend = false;
	      if (copyHistory) {
	        doc.history.undoDepth = this.history.undoDepth;
	        doc.setHistory(this.getHistory());
	      }
	      return doc
	    },

	    linkedDoc: function(options) {
	      if (!options) { options = {}; }
	      var from = this.first, to = this.first + this.size;
	      if (options.from != null && options.from > from) { from = options.from; }
	      if (options.to != null && options.to < to) { to = options.to; }
	      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction);
	      if (options.sharedHist) { copy.history = this.history
	      ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
	      copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
	      copySharedMarkers(copy, findSharedMarkers(this));
	      return copy
	    },
	    unlinkDoc: function(other) {
	      var this$1 = this;

	      if (other instanceof CodeMirror) { other = other.doc; }
	      if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
	        var link = this$1.linked[i];
	        if (link.doc != other) { continue }
	        this$1.linked.splice(i, 1);
	        other.unlinkDoc(this$1);
	        detachSharedMarkers(findSharedMarkers(this$1));
	        break
	      } }
	      // If the histories were shared, split them again
	      if (other.history == this.history) {
	        var splitIds = [other.id];
	        linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true);
	        other.history = new History(null);
	        other.history.done = copyHistoryArray(this.history.done, splitIds);
	        other.history.undone = copyHistoryArray(this.history.undone, splitIds);
	      }
	    },
	    iterLinkedDocs: function(f) {linkedDocs(this, f);},

	    getMode: function() {return this.mode},
	    getEditor: function() {return this.cm},

	    splitLines: function(str) {
	      if (this.lineSep) { return str.split(this.lineSep) }
	      return splitLinesAuto(str)
	    },
	    lineSeparator: function() { return this.lineSep || "\n" },

	    setDirection: docMethodOp(function (dir) {
	      if (dir != "rtl") { dir = "ltr"; }
	      if (dir == this.direction) { return }
	      this.direction = dir;
	      this.iter(function (line) { return line.order = null; });
	      if (this.cm) { directionChanged(this.cm); }
	    })
	  });

	  // Public alias.
	  Doc.prototype.eachLine = Doc.prototype.iter;

	  // Kludge to work around strange IE behavior where it'll sometimes
	  // re-fire a series of drag-related events right after the drop (#1551)
	  var lastDrop = 0;

	  function onDrop(e) {
	    var cm = this;
	    clearDragCursor(cm);
	    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
	      { return }
	    e_preventDefault(e);
	    if (ie) { lastDrop = +new Date; }
	    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
	    if (!pos || cm.isReadOnly()) { return }
	    // Might be a file drop, in which case we simply extract the text
	    // and insert it.
	    if (files && files.length && window.FileReader && window.File) {
	      var n = files.length, text = Array(n), read = 0;
	      var loadFile = function (file, i) {
	        if (cm.options.allowDropFileTypes &&
	            indexOf(cm.options.allowDropFileTypes, file.type) == -1)
	          { return }

	        var reader = new FileReader;
	        reader.onload = operation(cm, function () {
	          var content = reader.result;
	          if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = ""; }
	          text[i] = content;
	          if (++read == n) {
	            pos = clipPos(cm.doc, pos);
	            var change = {from: pos, to: pos,
	                          text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
	                          origin: "paste"};
	            makeChange(cm.doc, change);
	            setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
	          }
	        });
	        reader.readAsText(file);
	      };
	      for (var i = 0; i < n; ++i) { loadFile(files[i], i); }
	    } else { // Normal drop
	      // Don't do a replace if the drop happened inside of the selected text.
	      if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
	        cm.state.draggingText(e);
	        // Ensure the editor is re-focused
	        setTimeout(function () { return cm.display.input.focus(); }, 20);
	        return
	      }
	      try {
	        var text$1 = e.dataTransfer.getData("Text");
	        if (text$1) {
	          var selected;
	          if (cm.state.draggingText && !cm.state.draggingText.copy)
	            { selected = cm.listSelections(); }
	          setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
	          if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)
	            { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } }
	          cm.replaceSelection(text$1, "around", "paste");
	          cm.display.input.focus();
	        }
	      }
	      catch(e){}
	    }
	  }

	  function onDragStart(cm, e) {
	    if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
	    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }

	    e.dataTransfer.setData("Text", cm.getSelection());
	    e.dataTransfer.effectAllowed = "copyMove";

	    // Use dummy image instead of default browsers image.
	    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
	    if (e.dataTransfer.setDragImage && !safari) {
	      var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
	      img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
	      if (presto) {
	        img.width = img.height = 1;
	        cm.display.wrapper.appendChild(img);
	        // Force a relayout, or Opera won't use our image for some obscure reason
	        img._top = img.offsetTop;
	      }
	      e.dataTransfer.setDragImage(img, 0, 0);
	      if (presto) { img.parentNode.removeChild(img); }
	    }
	  }

	  function onDragOver(cm, e) {
	    var pos = posFromMouse(cm, e);
	    if (!pos) { return }
	    var frag = document.createDocumentFragment();
	    drawSelectionCursor(cm, pos, frag);
	    if (!cm.display.dragCursor) {
	      cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
	      cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
	    }
	    removeChildrenAndAdd(cm.display.dragCursor, frag);
	  }

	  function clearDragCursor(cm) {
	    if (cm.display.dragCursor) {
	      cm.display.lineSpace.removeChild(cm.display.dragCursor);
	      cm.display.dragCursor = null;
	    }
	  }

	  // These must be handled carefully, because naively registering a
	  // handler for each editor will cause the editors to never be
	  // garbage collected.

	  function forEachCodeMirror(f) {
	    if (!document.getElementsByClassName) { return }
	    var byClass = document.getElementsByClassName("CodeMirror"), editors = [];
	    for (var i = 0; i < byClass.length; i++) {
	      var cm = byClass[i].CodeMirror;
	      if (cm) { editors.push(cm); }
	    }
	    if (editors.length) { editors[0].operation(function () {
	      for (var i = 0; i < editors.length; i++) { f(editors[i]); }
	    }); }
	  }

	  var globalsRegistered = false;
	  function ensureGlobalHandlers() {
	    if (globalsRegistered) { return }
	    registerGlobalHandlers();
	    globalsRegistered = true;
	  }
	  function registerGlobalHandlers() {
	    // When the window resizes, we need to refresh active editors.
	    var resizeTimer;
	    on(window, "resize", function () {
	      if (resizeTimer == null) { resizeTimer = setTimeout(function () {
	        resizeTimer = null;
	        forEachCodeMirror(onResize);
	      }, 100); }
	    });
	    // When the window loses focus, we want to show the editor as blurred
	    on(window, "blur", function () { return forEachCodeMirror(onBlur); });
	  }
	  // Called when the window resizes
	  function onResize(cm) {
	    var d = cm.display;
	    // Might be a text scaling operation, clear size caches.
	    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
	    d.scrollbarsClipped = false;
	    cm.setSize();
	  }

	  var keyNames = {
	    3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
	    19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
	    36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
	    46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
	    106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", 145: "ScrollLock",
	    173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
	    221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
	    63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
	  };

	  // Number keys
	  for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); }
	  // Alphabetic keys
	  for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); }
	  // Function keys
	  for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; }

	  var keyMap = {};

	  keyMap.basic = {
	    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
	    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
	    "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
	    "Tab": "defaultTab", "Shift-Tab": "indentAuto",
	    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
	    "Esc": "singleSelection"
	  };
	  // Note that the save and find-related commands aren't defined by
	  // default. User code or addons can define them. Unknown commands
	  // are simply ignored.
	  keyMap.pcDefault = {
	    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
	    "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
	    "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
	    "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
	    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
	    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
	    "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
	    "fallthrough": "basic"
	  };
	  // Very basic readline/emacs-style bindings, which are standard on Mac.
	  keyMap.emacsy = {
	    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
	    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
	    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
	    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
	    "Ctrl-O": "openLine"
	  };
	  keyMap.macDefault = {
	    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
	    "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
	    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
	    "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
	    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
	    "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
	    "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
	    "fallthrough": ["basic", "emacsy"]
	  };
	  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;

	  // KEYMAP DISPATCH

	  function normalizeKeyName(name) {
	    var parts = name.split(/-(?!$)/);
	    name = parts[parts.length - 1];
	    var alt, ctrl, shift, cmd;
	    for (var i = 0; i < parts.length - 1; i++) {
	      var mod = parts[i];
	      if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; }
	      else if (/^a(lt)?$/i.test(mod)) { alt = true; }
	      else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; }
	      else if (/^s(hift)?$/i.test(mod)) { shift = true; }
	      else { throw new Error("Unrecognized modifier name: " + mod) }
	    }
	    if (alt) { name = "Alt-" + name; }
	    if (ctrl) { name = "Ctrl-" + name; }
	    if (cmd) { name = "Cmd-" + name; }
	    if (shift) { name = "Shift-" + name; }
	    return name
	  }

	  // This is a kludge to keep keymaps mostly working as raw objects
	  // (backwards compatibility) while at the same time support features
	  // like normalization and multi-stroke key bindings. It compiles a
	  // new normalized keymap, and then updates the old object to reflect
	  // this.
	  function normalizeKeyMap(keymap) {
	    var copy = {};
	    for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {
	      var value = keymap[keyname];
	      if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }
	      if (value == "...") { delete keymap[keyname]; continue }

	      var keys = map(keyname.split(" "), normalizeKeyName);
	      for (var i = 0; i < keys.length; i++) {
	        var val = (void 0), name = (void 0);
	        if (i == keys.length - 1) {
	          name = keys.join(" ");
	          val = value;
	        } else {
	          name = keys.slice(0, i + 1).join(" ");
	          val = "...";
	        }
	        var prev = copy[name];
	        if (!prev) { copy[name] = val; }
	        else if (prev != val) { throw new Error("Inconsistent bindings for " + name) }
	      }
	      delete keymap[keyname];
	    } }
	    for (var prop in copy) { keymap[prop] = copy[prop]; }
	    return keymap
	  }

	  function lookupKey(key, map$$1, handle, context) {
	    map$$1 = getKeyMap(map$$1);
	    var found = map$$1.call ? map$$1.call(key, context) : map$$1[key];
	    if (found === false) { return "nothing" }
	    if (found === "...") { return "multi" }
	    if (found != null && handle(found)) { return "handled" }

	    if (map$$1.fallthrough) {
	      if (Object.prototype.toString.call(map$$1.fallthrough) != "[object Array]")
	        { return lookupKey(key, map$$1.fallthrough, handle, context) }
	      for (var i = 0; i < map$$1.fallthrough.length; i++) {
	        var result = lookupKey(key, map$$1.fallthrough[i], handle, context);
	        if (result) { return result }
	      }
	    }
	  }

	  // Modifier key presses don't count as 'real' key presses for the
	  // purpose of keymap fallthrough.
	  function isModifierKey(value) {
	    var name = typeof value == "string" ? value : keyNames[value.keyCode];
	    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"
	  }

	  function addModifierNames(name, event, noShift) {
	    var base = name;
	    if (event.altKey && base != "Alt") { name = "Alt-" + name; }
	    if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; }
	    if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name; }
	    if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; }
	    return name
	  }

	  // Look up the name of a key as indicated by an event object.
	  function keyName(event, noShift) {
	    if (presto && event.keyCode == 34 && event["char"]) { return false }
	    var name = keyNames[event.keyCode];
	    if (name == null || event.altGraphKey) { return false }
	    // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause,
	    // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+)
	    if (event.keyCode == 3 && event.code) { name = event.code; }
	    return addModifierNames(name, event, noShift)
	  }

	  function getKeyMap(val) {
	    return typeof val == "string" ? keyMap[val] : val
	  }

	  // Helper for deleting text near the selection(s), used to implement
	  // backspace, delete, and similar functionality.
	  function deleteNearSelection(cm, compute) {
	    var ranges = cm.doc.sel.ranges, kill = [];
	    // Build up a set of ranges to kill first, merging overlapping
	    // ranges.
	    for (var i = 0; i < ranges.length; i++) {
	      var toKill = compute(ranges[i]);
	      while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
	        var replaced = kill.pop();
	        if (cmp(replaced.from, toKill.from) < 0) {
	          toKill.from = replaced.from;
	          break
	        }
	      }
	      kill.push(toKill);
	    }
	    // Next, remove those actual ranges.
	    runInOp(cm, function () {
	      for (var i = kill.length - 1; i >= 0; i--)
	        { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); }
	      ensureCursorVisible(cm);
	    });
	  }

	  function moveCharLogically(line, ch, dir) {
	    var target = skipExtendingChars(line.text, ch + dir, dir);
	    return target < 0 || target > line.text.length ? null : target
	  }

	  function moveLogically(line, start, dir) {
	    var ch = moveCharLogically(line, start.ch, dir);
	    return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before")
	  }

	  function endOfLine(visually, cm, lineObj, lineNo, dir) {
	    if (visually) {
	      var order = getOrder(lineObj, cm.doc.direction);
	      if (order) {
	        var part = dir < 0 ? lst(order) : order[0];
	        var moveInStorageOrder = (dir < 0) == (part.level == 1);
	        var sticky = moveInStorageOrder ? "after" : "before";
	        var ch;
	        // With a wrapped rtl chunk (possibly spanning multiple bidi parts),
	        // it could be that the last bidi part is not on the last visual line,
	        // since visual lines contain content order-consecutive chunks.
	        // Thus, in rtl, we are looking for the first (content-order) character
	        // in the rtl chunk that is on the last line (that is, the same line
	        // as the last (content-order) character).
	        if (part.level > 0 || cm.doc.direction == "rtl") {
	          var prep = prepareMeasureForLine(cm, lineObj);
	          ch = dir < 0 ? lineObj.text.length - 1 : 0;
	          var targetTop = measureCharPrepared(cm, prep, ch).top;
	          ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
	          if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); }
	        } else { ch = dir < 0 ? part.to : part.from; }
	        return new Pos(lineNo, ch, sticky)
	      }
	    }
	    return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after")
	  }

	  function moveVisually(cm, line, start, dir) {
	    var bidi = getOrder(line, cm.doc.direction);
	    if (!bidi) { return moveLogically(line, start, dir) }
	    if (start.ch >= line.text.length) {
	      start.ch = line.text.length;
	      start.sticky = "before";
	    } else if (start.ch <= 0) {
	      start.ch = 0;
	      start.sticky = "after";
	    }
	    var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos];
	    if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) {
	      // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines,
	      // nothing interesting happens.
	      return moveLogically(line, start, dir)
	    }

	    var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); };
	    var prep;
	    var getWrappedLineExtent = function (ch) {
	      if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} }
	      prep = prep || prepareMeasureForLine(cm, line);
	      return wrappedLineExtentChar(cm, line, prep, ch)
	    };
	    var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch);

	    if (cm.doc.direction == "rtl" || part.level == 1) {
	      var moveInStorageOrder = (part.level == 1) == (dir < 0);
	      var ch = mv(start, moveInStorageOrder ? 1 : -1);
	      if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) {
	        // Case 2: We move within an rtl part or in an rtl editor on the same visual line
	        var sticky = moveInStorageOrder ? "before" : "after";
	        return new Pos(start.line, ch, sticky)
	      }
	    }

	    // Case 3: Could not move within this bidi part in this visual line, so leave
	    // the current bidi part

	    var searchInVisualLine = function (partPos, dir, wrappedLineExtent) {
	      var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder
	        ? new Pos(start.line, mv(ch, 1), "before")
	        : new Pos(start.line, ch, "after"); };

	      for (; partPos >= 0 && partPos < bidi.length; partPos += dir) {
	        var part = bidi[partPos];
	        var moveInStorageOrder = (dir > 0) == (part.level != 1);
	        var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1);
	        if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) }
	        ch = moveInStorageOrder ? part.from : mv(part.to, -1);
	        if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) }
	      }
	    };

	    // Case 3a: Look for other bidi parts on the same visual line
	    var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent);
	    if (res) { return res }

	    // Case 3b: Look for other bidi parts on the next visual line
	    var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1);
	    if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) {
	      res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh));
	      if (res) { return res }
	    }

	    // Case 4: Nowhere to move
	    return null
	  }

	  // Commands are parameter-less actions that can be performed on an
	  // editor, mostly used for keybindings.
	  var commands = {
	    selectAll: selectAll,
	    singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); },
	    killLine: function (cm) { return deleteNearSelection(cm, function (range) {
	      if (range.empty()) {
	        var len = getLine(cm.doc, range.head.line).text.length;
	        if (range.head.ch == len && range.head.line < cm.lastLine())
	          { return {from: range.head, to: Pos(range.head.line + 1, 0)} }
	        else
	          { return {from: range.head, to: Pos(range.head.line, len)} }
	      } else {
	        return {from: range.from(), to: range.to()}
	      }
	    }); },
	    deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({
	      from: Pos(range.from().line, 0),
	      to: clipPos(cm.doc, Pos(range.to().line + 1, 0))
	    }); }); },
	    delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({
	      from: Pos(range.from().line, 0), to: range.from()
	    }); }); },
	    delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {
	      var top = cm.charCoords(range.head, "div").top + 5;
	      var leftPos = cm.coordsChar({left: 0, top: top}, "div");
	      return {from: leftPos, to: range.from()}
	    }); },
	    delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {
	      var top = cm.charCoords(range.head, "div").top + 5;
	      var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
	      return {from: range.from(), to: rightPos }
	    }); },
	    undo: function (cm) { return cm.undo(); },
	    redo: function (cm) { return cm.redo(); },
	    undoSelection: function (cm) { return cm.undoSelection(); },
	    redoSelection: function (cm) { return cm.redoSelection(); },
	    goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },
	    goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },
	    goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },
	      {origin: "+move", bias: 1}
	    ); },
	    goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },
	      {origin: "+move", bias: 1}
	    ); },
	    goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },
	      {origin: "+move", bias: -1}
	    ); },
	    goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {
	      var top = cm.cursorCoords(range.head, "div").top + 5;
	      return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
	    }, sel_move); },
	    goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {
	      var top = cm.cursorCoords(range.head, "div").top + 5;
	      return cm.coordsChar({left: 0, top: top}, "div")
	    }, sel_move); },
	    goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {
	      var top = cm.cursorCoords(range.head, "div").top + 5;
	      var pos = cm.coordsChar({left: 0, top: top}, "div");
	      if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) }
	      return pos
	    }, sel_move); },
	    goLineUp: function (cm) { return cm.moveV(-1, "line"); },
	    goLineDown: function (cm) { return cm.moveV(1, "line"); },
	    goPageUp: function (cm) { return cm.moveV(-1, "page"); },
	    goPageDown: function (cm) { return cm.moveV(1, "page"); },
	    goCharLeft: function (cm) { return cm.moveH(-1, "char"); },
	    goCharRight: function (cm) { return cm.moveH(1, "char"); },
	    goColumnLeft: function (cm) { return cm.moveH(-1, "column"); },
	    goColumnRight: function (cm) { return cm.moveH(1, "column"); },
	    goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
	    goGroupRight: function (cm) { return cm.moveH(1, "group"); },
	    goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
	    goWordRight: function (cm) { return cm.moveH(1, "word"); },
	    delCharBefore: function (cm) { return cm.deleteH(-1, "char"); },
	    delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
	    delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
	    delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
	    delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
	    delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
	    indentAuto: function (cm) { return cm.indentSelection("smart"); },
	    indentMore: function (cm) { return cm.indentSelection("add"); },
	    indentLess: function (cm) { return cm.indentSelection("subtract"); },
	    insertTab: function (cm) { return cm.replaceSelection("\t"); },
	    insertSoftTab: function (cm) {
	      var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
	      for (var i = 0; i < ranges.length; i++) {
	        var pos = ranges[i].from();
	        var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
	        spaces.push(spaceStr(tabSize - col % tabSize));
	      }
	      cm.replaceSelections(spaces);
	    },
	    defaultTab: function (cm) {
	      if (cm.somethingSelected()) { cm.indentSelection("add"); }
	      else { cm.execCommand("insertTab"); }
	    },
	    // Swap the two chars left and right of each selection's head.
	    // Move cursor behind the two swapped characters afterwards.
	    //
	    // Doesn't consider line feeds a character.
	    // Doesn't scan more than one line above to find a character.
	    // Doesn't do anything on an empty line.
	    // Doesn't do anything with non-empty selections.
	    transposeChars: function (cm) { return runInOp(cm, function () {
	      var ranges = cm.listSelections(), newSel = [];
	      for (var i = 0; i < ranges.length; i++) {
	        if (!ranges[i].empty()) { continue }
	        var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
	        if (line) {
	          if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); }
	          if (cur.ch > 0) {
	            cur = new Pos(cur.line, cur.ch + 1);
	            cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
	                            Pos(cur.line, cur.ch - 2), cur, "+transpose");
	          } else if (cur.line > cm.doc.first) {
	            var prev = getLine(cm.doc, cur.line - 1).text;
	            if (prev) {
	              cur = new Pos(cur.line, 1);
	              cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
	                              prev.charAt(prev.length - 1),
	                              Pos(cur.line - 1, prev.length - 1), cur, "+transpose");
	            }
	          }
	        }
	        newSel.push(new Range(cur, cur));
	      }
	      cm.setSelections(newSel);
	    }); },
	    newlineAndIndent: function (cm) { return runInOp(cm, function () {
	      var sels = cm.listSelections();
	      for (var i = sels.length - 1; i >= 0; i--)
	        { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); }
	      sels = cm.listSelections();
	      for (var i$1 = 0; i$1 < sels.length; i$1++)
	        { cm.indentLine(sels[i$1].from().line, null, true); }
	      ensureCursorVisible(cm);
	    }); },
	    openLine: function (cm) { return cm.replaceSelection("\n", "start"); },
	    toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }
	  };


	  function lineStart(cm, lineN) {
	    var line = getLine(cm.doc, lineN);
	    var visual = visualLine(line);
	    if (visual != line) { lineN = lineNo(visual); }
	    return endOfLine(true, cm, visual, lineN, 1)
	  }
	  function lineEnd(cm, lineN) {
	    var line = getLine(cm.doc, lineN);
	    var visual = visualLineEnd(line);
	    if (visual != line) { lineN = lineNo(visual); }
	    return endOfLine(true, cm, line, lineN, -1)
	  }
	  function lineStartSmart(cm, pos) {
	    var start = lineStart(cm, pos.line);
	    var line = getLine(cm.doc, start.line);
	    var order = getOrder(line, cm.doc.direction);
	    if (!order || order[0].level == 0) {
	      var firstNonWS = Math.max(0, line.text.search(/\S/));
	      var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
	      return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky)
	    }
	    return start
	  }

	  // Run a handler that was bound to a key.
	  function doHandleBinding(cm, bound, dropShift) {
	    if (typeof bound == "string") {
	      bound = commands[bound];
	      if (!bound) { return false }
	    }
	    // Ensure previous input has been read, so that the handler sees a
	    // consistent view of the document
	    cm.display.input.ensurePolled();
	    var prevShift = cm.display.shift, done = false;
	    try {
	      if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
	      if (dropShift) { cm.display.shift = false; }
	      done = bound(cm) != Pass;
	    } finally {
	      cm.display.shift = prevShift;
	      cm.state.suppressEdits = false;
	    }
	    return done
	  }

	  function lookupKeyForEditor(cm, name, handle) {
	    for (var i = 0; i < cm.state.keyMaps.length; i++) {
	      var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
	      if (result) { return result }
	    }
	    return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
	      || lookupKey(name, cm.options.keyMap, handle, cm)
	  }

	  // Note that, despite the name, this function is also used to check
	  // for bound mouse clicks.

	  var stopSeq = new Delayed;

	  function dispatchKey(cm, name, e, handle) {
	    var seq = cm.state.keySeq;
	    if (seq) {
	      if (isModifierKey(name)) { return "handled" }
	      if (/\'$/.test(name))
	        { cm.state.keySeq = null; }
	      else
	        { stopSeq.set(50, function () {
	          if (cm.state.keySeq == seq) {
	            cm.state.keySeq = null;
	            cm.display.input.reset();
	          }
	        }); }
	      if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true }
	    }
	    return dispatchKeyInner(cm, name, e, handle)
	  }

	  function dispatchKeyInner(cm, name, e, handle) {
	    var result = lookupKeyForEditor(cm, name, handle);

	    if (result == "multi")
	      { cm.state.keySeq = name; }
	    if (result == "handled")
	      { signalLater(cm, "keyHandled", cm, name, e); }

	    if (result == "handled" || result == "multi") {
	      e_preventDefault(e);
	      restartBlink(cm);
	    }

	    return !!result
	  }

	  // Handle a key from the keydown event.
	  function handleKeyBinding(cm, e) {
	    var name = keyName(e, true);
	    if (!name) { return false }

	    if (e.shiftKey && !cm.state.keySeq) {
	      // First try to resolve full name (including 'Shift-'). Failing
	      // that, see if there is a cursor-motion command (starting with
	      // 'go') bound to the keyname without 'Shift-'.
	      return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); })
	          || dispatchKey(cm, name, e, function (b) {
	               if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
	                 { return doHandleBinding(cm, b) }
	             })
	    } else {
	      return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })
	    }
	  }

	  // Handle a key from the keypress event
	  function handleCharBinding(cm, e, ch) {
	    return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); })
	  }

	  var lastStoppedKey = null;
	  function onKeyDown(e) {
	    var cm = this;
	    cm.curOp.focus = activeElt();
	    if (signalDOMEvent(cm, e)) { return }
	    // IE does strange things with escape.
	    if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; }
	    var code = e.keyCode;
	    cm.display.shift = code == 16 || e.shiftKey;
	    var handled = handleKeyBinding(cm, e);
	    if (presto) {
	      lastStoppedKey = handled ? code : null;
	      // Opera has no cut event... we try to at least catch the key combo
	      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
	        { cm.replaceSelection("", null, "cut"); }
	    }

	    // Turn mouse into crosshair when Alt is held on Mac.
	    if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
	      { showCrossHair(cm); }
	  }

	  function showCrossHair(cm) {
	    var lineDiv = cm.display.lineDiv;
	    addClass(lineDiv, "CodeMirror-crosshair");

	    function up(e) {
	      if (e.keyCode == 18 || !e.altKey) {
	        rmClass(lineDiv, "CodeMirror-crosshair");
	        off(document, "keyup", up);
	        off(document, "mouseover", up);
	      }
	    }
	    on(document, "keyup", up);
	    on(document, "mouseover", up);
	  }

	  function onKeyUp(e) {
	    if (e.keyCode == 16) { this.doc.sel.shift = false; }
	    signalDOMEvent(this, e);
	  }

	  function onKeyPress(e) {
	    var cm = this;
	    if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
	    var keyCode = e.keyCode, charCode = e.charCode;
	    if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
	    if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }
	    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
	    // Some browsers fire keypress events for backspace
	    if (ch == "\x08") { return }
	    if (handleCharBinding(cm, e, ch)) { return }
	    cm.display.input.onKeyPress(e);
	  }

	  var DOUBLECLICK_DELAY = 400;

	  var PastClick = function(time, pos, button) {
	    this.time = time;
	    this.pos = pos;
	    this.button = button;
	  };

	  PastClick.prototype.compare = function (time, pos, button) {
	    return this.time + DOUBLECLICK_DELAY > time &&
	      cmp(pos, this.pos) == 0 && button == this.button
	  };

	  var lastClick, lastDoubleClick;
	  function clickRepeat(pos, button) {
	    var now = +new Date;
	    if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) {
	      lastClick = lastDoubleClick = null;
	      return "triple"
	    } else if (lastClick && lastClick.compare(now, pos, button)) {
	      lastDoubleClick = new PastClick(now, pos, button);
	      lastClick = null;
	      return "double"
	    } else {
	      lastClick = new PastClick(now, pos, button);
	      lastDoubleClick = null;
	      return "single"
	    }
	  }

	  // A mouse down can be a single click, double click, triple click,
	  // start of selection drag, start of text drag, new cursor
	  // (ctrl-click), rectangle drag (alt-drag), or xwin
	  // middle-click-paste. Or it might be a click on something we should
	  // not interfere with, such as a scrollbar or widget.
	  function onMouseDown(e) {
	    var cm = this, display = cm.display;
	    if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }
	    display.input.ensurePolled();
	    display.shift = e.shiftKey;

	    if (eventInWidget(display, e)) {
	      if (!webkit) {
	        // Briefly turn off draggability, to allow widgets to do
	        // normal dragging things.
	        display.scroller.draggable = false;
	        setTimeout(function () { return display.scroller.draggable = true; }, 100);
	      }
	      return
	    }
	    if (clickInGutter(cm, e)) { return }
	    var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single";
	    window.focus();

	    // #3261: make sure, that we're not starting a second selection
	    if (button == 1 && cm.state.selectingText)
	      { cm.state.selectingText(e); }

	    if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return }

	    if (button == 1) {
	      if (pos) { leftButtonDown(cm, pos, repeat, e); }
	      else if (e_target(e) == display.scroller) { e_preventDefault(e); }
	    } else if (button == 2) {
	      if (pos) { extendSelection(cm.doc, pos); }
	      setTimeout(function () { return display.input.focus(); }, 20);
	    } else if (button == 3) {
	      if (captureRightClick) { cm.display.input.onContextMenu(e); }
	      else { delayBlurEvent(cm); }
	    }
	  }

	  function handleMappedButton(cm, button, pos, repeat, event) {
	    var name = "Click";
	    if (repeat == "double") { name = "Double" + name; }
	    else if (repeat == "triple") { name = "Triple" + name; }
	    name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name;

	    return dispatchKey(cm,  addModifierNames(name, event), event, function (bound) {
	      if (typeof bound == "string") { bound = commands[bound]; }
	      if (!bound) { return false }
	      var done = false;
	      try {
	        if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
	        done = bound(cm, pos) != Pass;
	      } finally {
	        cm.state.suppressEdits = false;
	      }
	      return done
	    })
	  }

	  function configureMouse(cm, repeat, event) {
	    var option = cm.getOption("configureMouse");
	    var value = option ? option(cm, repeat, event) : {};
	    if (value.unit == null) {
	      var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey;
	      value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line";
	    }
	    if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; }
	    if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; }
	    if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); }
	    return value
	  }

	  function leftButtonDown(cm, pos, repeat, event) {
	    if (ie) { setTimeout(bind(ensureFocus, cm), 0); }
	    else { cm.curOp.focus = activeElt(); }

	    var behavior = configureMouse(cm, repeat, event);

	    var sel = cm.doc.sel, contained;
	    if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
	        repeat == "single" && (contained = sel.contains(pos)) > -1 &&
	        (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) &&
	        (cmp(contained.to(), pos) > 0 || pos.xRel < 0))
	      { leftButtonStartDrag(cm, event, pos, behavior); }
	    else
	      { leftButtonSelect(cm, event, pos, behavior); }
	  }

	  // Start a text drag. When it ends, see if any dragging actually
	  // happen, and treat as a click if it didn't.
	  function leftButtonStartDrag(cm, event, pos, behavior) {
	    var display = cm.display, moved = false;
	    var dragEnd = operation(cm, function (e) {
	      if (webkit) { display.scroller.draggable = false; }
	      cm.state.draggingText = false;
	      off(display.wrapper.ownerDocument, "mouseup", dragEnd);
	      off(display.wrapper.ownerDocument, "mousemove", mouseMove);
	      off(display.scroller, "dragstart", dragStart);
	      off(display.scroller, "drop", dragEnd);
	      if (!moved) {
	        e_preventDefault(e);
	        if (!behavior.addNew)
	          { extendSelection(cm.doc, pos, null, null, behavior.extend); }
	        // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
	        if (webkit || ie && ie_version == 9)
	          { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus();}, 20); }
	        else
	          { display.input.focus(); }
	      }
	    });
	    var mouseMove = function(e2) {
	      moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10;
	    };
	    var dragStart = function () { return moved = true; };
	    // Let the drag handler handle this.
	    if (webkit) { display.scroller.draggable = true; }
	    cm.state.draggingText = dragEnd;
	    dragEnd.copy = !behavior.moveOnDrag;
	    // IE's approach to draggable
	    if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
	    on(display.wrapper.ownerDocument, "mouseup", dragEnd);
	    on(display.wrapper.ownerDocument, "mousemove", mouseMove);
	    on(display.scroller, "dragstart", dragStart);
	    on(display.scroller, "drop", dragEnd);

	    delayBlurEvent(cm);
	    setTimeout(function () { return display.input.focus(); }, 20);
	  }

	  function rangeForUnit(cm, pos, unit) {
	    if (unit == "char") { return new Range(pos, pos) }
	    if (unit == "word") { return cm.findWordAt(pos) }
	    if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }
	    var result = unit(cm, pos);
	    return new Range(result.from, result.to)
	  }

	  // Normal selection, as opposed to text dragging.
	  function leftButtonSelect(cm, event, start, behavior) {
	    var display = cm.display, doc = cm.doc;
	    e_preventDefault(event);

	    var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
	    if (behavior.addNew && !behavior.extend) {
	      ourIndex = doc.sel.contains(start);
	      if (ourIndex > -1)
	        { ourRange = ranges[ourIndex]; }
	      else
	        { ourRange = new Range(start, start); }
	    } else {
	      ourRange = doc.sel.primary();
	      ourIndex = doc.sel.primIndex;
	    }

	    if (behavior.unit == "rectangle") {
	      if (!behavior.addNew) { ourRange = new Range(start, start); }
	      start = posFromMouse(cm, event, true, true);
	      ourIndex = -1;
	    } else {
	      var range$$1 = rangeForUnit(cm, start, behavior.unit);
	      if (behavior.extend)
	        { ourRange = extendRange(ourRange, range$$1.anchor, range$$1.head, behavior.extend); }
	      else
	        { ourRange = range$$1; }
	    }

	    if (!behavior.addNew) {
	      ourIndex = 0;
	      setSelection(doc, new Selection([ourRange], 0), sel_mouse);
	      startSel = doc.sel;
	    } else if (ourIndex == -1) {
	      ourIndex = ranges.length;
	      setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex),
	                   {scroll: false, origin: "*mouse"});
	    } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) {
	      setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
	                   {scroll: false, origin: "*mouse"});
	      startSel = doc.sel;
	    } else {
	      replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
	    }

	    var lastPos = start;
	    function extendTo(pos) {
	      if (cmp(lastPos, pos) == 0) { return }
	      lastPos = pos;

	      if (behavior.unit == "rectangle") {
	        var ranges = [], tabSize = cm.options.tabSize;
	        var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
	        var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
	        var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
	        for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
	             line <= end; line++) {
	          var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
	          if (left == right)
	            { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); }
	          else if (text.length > leftPos)
	            { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); }
	        }
	        if (!ranges.length) { ranges.push(new Range(start, start)); }
	        setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
	                     {origin: "*mouse", scroll: false});
	        cm.scrollIntoView(pos);
	      } else {
	        var oldRange = ourRange;
	        var range$$1 = rangeForUnit(cm, pos, behavior.unit);
	        var anchor = oldRange.anchor, head;
	        if (cmp(range$$1.anchor, anchor) > 0) {
	          head = range$$1.head;
	          anchor = minPos(oldRange.from(), range$$1.anchor);
	        } else {
	          head = range$$1.anchor;
	          anchor = maxPos(oldRange.to(), range$$1.head);
	        }
	        var ranges$1 = startSel.ranges.slice(0);
	        ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head));
	        setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse);
	      }
	    }

	    var editorSize = display.wrapper.getBoundingClientRect();
	    // Used to ensure timeout re-tries don't fire when another extend
	    // happened in the meantime (clearTimeout isn't reliable -- at
	    // least on Chrome, the timeouts still happen even when cleared,
	    // if the clear happens after their scheduled firing time).
	    var counter = 0;

	    function extend(e) {
	      var curCount = ++counter;
	      var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle");
	      if (!cur) { return }
	      if (cmp(cur, lastPos) != 0) {
	        cm.curOp.focus = activeElt();
	        extendTo(cur);
	        var visible = visibleLines(display, doc);
	        if (cur.line >= visible.to || cur.line < visible.from)
	          { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); }
	      } else {
	        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
	        if (outside) { setTimeout(operation(cm, function () {
	          if (counter != curCount) { return }
	          display.scroller.scrollTop += outside;
	          extend(e);
	        }), 50); }
	      }
	    }

	    function done(e) {
	      cm.state.selectingText = false;
	      counter = Infinity;
	      e_preventDefault(e);
	      display.input.focus();
	      off(display.wrapper.ownerDocument, "mousemove", move);
	      off(display.wrapper.ownerDocument, "mouseup", up);
	      doc.history.lastSelOrigin = null;
	    }

	    var move = operation(cm, function (e) {
	      if (e.buttons === 0 || !e_button(e)) { done(e); }
	      else { extend(e); }
	    });
	    var up = operation(cm, done);
	    cm.state.selectingText = up;
	    on(display.wrapper.ownerDocument, "mousemove", move);
	    on(display.wrapper.ownerDocument, "mouseup", up);
	  }

	  // Used when mouse-selecting to adjust the anchor to the proper side
	  // of a bidi jump depending on the visual position of the head.
	  function bidiSimplify(cm, range$$1) {
	    var anchor = range$$1.anchor;
	    var head = range$$1.head;
	    var anchorLine = getLine(cm.doc, anchor.line);
	    if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range$$1 }
	    var order = getOrder(anchorLine);
	    if (!order) { return range$$1 }
	    var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index];
	    if (part.from != anchor.ch && part.to != anchor.ch) { return range$$1 }
	    var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1);
	    if (boundary == 0 || boundary == order.length) { return range$$1 }

	    // Compute the relative visual position of the head compared to the
	    // anchor (<0 is to the left, >0 to the right)
	    var leftSide;
	    if (head.line != anchor.line) {
	      leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0;
	    } else {
	      var headIndex = getBidiPartAt(order, head.ch, head.sticky);
	      var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1);
	      if (headIndex == boundary - 1 || headIndex == boundary)
	        { leftSide = dir < 0; }
	      else
	        { leftSide = dir > 0; }
	    }

	    var usePart = order[boundary + (leftSide ? -1 : 0)];
	    var from = leftSide == (usePart.level == 1);
	    var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before";
	    return anchor.ch == ch && anchor.sticky == sticky ? range$$1 : new Range(new Pos(anchor.line, ch, sticky), head)
	  }


	  // Determines whether an event happened in the gutter, and fires the
	  // handlers for the corresponding event.
	  function gutterEvent(cm, e, type, prevent) {
	    var mX, mY;
	    if (e.touches) {
	      mX = e.touches[0].clientX;
	      mY = e.touches[0].clientY;
	    } else {
	      try { mX = e.clientX; mY = e.clientY; }
	      catch(e) { return false }
	    }
	    if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
	    if (prevent) { e_preventDefault(e); }

	    var display = cm.display;
	    var lineBox = display.lineDiv.getBoundingClientRect();

	    if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }
	    mY -= lineBox.top - display.viewOffset;

	    for (var i = 0; i < cm.options.gutters.length; ++i) {
	      var g = display.gutters.childNodes[i];
	      if (g && g.getBoundingClientRect().right >= mX) {
	        var line = lineAtHeight(cm.doc, mY);
	        var gutter = cm.options.gutters[i];
	        signal(cm, type, cm, line, gutter, e);
	        return e_defaultPrevented(e)
	      }
	    }
	  }

	  function clickInGutter(cm, e) {
	    return gutterEvent(cm, e, "gutterClick", true)
	  }

	  // CONTEXT MENU HANDLING

	  // To make the context menu work, we need to briefly unhide the
	  // textarea (making it as unobtrusive as possible) to let the
	  // right-click take effect on it.
	  function onContextMenu(cm, e) {
	    if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }
	    if (signalDOMEvent(cm, e, "contextmenu")) { return }
	    if (!captureRightClick) { cm.display.input.onContextMenu(e); }
	  }

	  function contextMenuInGutter(cm, e) {
	    if (!hasHandler(cm, "gutterContextMenu")) { return false }
	    return gutterEvent(cm, e, "gutterContextMenu", false)
	  }

	  function themeChanged(cm) {
	    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
	      cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
	    clearCaches(cm);
	  }

	  var Init = {toString: function(){return "CodeMirror.Init"}};

	  var defaults = {};
	  var optionHandlers = {};

	  function defineOptions(CodeMirror) {
	    var optionHandlers = CodeMirror.optionHandlers;

	    function option(name, deflt, handle, notOnInit) {
	      CodeMirror.defaults[name] = deflt;
	      if (handle) { optionHandlers[name] =
	        notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; }
	    }

	    CodeMirror.defineOption = option;

	    // Passed to option handlers when there is no old value.
	    CodeMirror.Init = Init;

	    // These two are, on init, called from the constructor because they
	    // have to be initialized before the editor can start at all.
	    option("value", "", function (cm, val) { return cm.setValue(val); }, true);
	    option("mode", null, function (cm, val) {
	      cm.doc.modeOption = val;
	      loadMode(cm);
	    }, true);

	    option("indentUnit", 2, loadMode, true);
	    option("indentWithTabs", false);
	    option("smartIndent", true);
	    option("tabSize", 4, function (cm) {
	      resetModeState(cm);
	      clearCaches(cm);
	      regChange(cm);
	    }, true);

	    option("lineSeparator", null, function (cm, val) {
	      cm.doc.lineSep = val;
	      if (!val) { return }
	      var newBreaks = [], lineNo = cm.doc.first;
	      cm.doc.iter(function (line) {
	        for (var pos = 0;;) {
	          var found = line.text.indexOf(val, pos);
	          if (found == -1) { break }
	          pos = found + val.length;
	          newBreaks.push(Pos(lineNo, found));
	        }
	        lineNo++;
	      });
	      for (var i = newBreaks.length - 1; i >= 0; i--)
	        { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
	    });
	    option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) {
	      cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
	      if (old != Init) { cm.refresh(); }
	    });
	    option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true);
	    option("electricChars", true);
	    option("inputStyle", mobile ? "contenteditable" : "textarea", function () {
	      throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
	    }, true);
	    option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true);
	    option("rtlMoveVisually", !windows);
	    option("wholeLineUpdateBefore", true);

	    option("theme", "default", function (cm) {
	      themeChanged(cm);
	      guttersChanged(cm);
	    }, true);
	    option("keyMap", "default", function (cm, val, old) {
	      var next = getKeyMap(val);
	      var prev = old != Init && getKeyMap(old);
	      if (prev && prev.detach) { prev.detach(cm, next); }
	      if (next.attach) { next.attach(cm, prev || null); }
	    });
	    option("extraKeys", null);
	    option("configureMouse", null);

	    option("lineWrapping", false, wrappingChanged, true);
	    option("gutters", [], function (cm) {
	      setGuttersForLineNumbers(cm.options);
	      guttersChanged(cm);
	    }, true);
	    option("fixedGutter", true, function (cm, val) {
	      cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
	      cm.refresh();
	    }, true);
	    option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true);
	    option("scrollbarStyle", "native", function (cm) {
	      initScrollbars(cm);
	      updateScrollbars(cm);
	      cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
	      cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
	    }, true);
	    option("lineNumbers", false, function (cm) {
	      setGuttersForLineNumbers(cm.options);
	      guttersChanged(cm);
	    }, true);
	    option("firstLineNumber", 1, guttersChanged, true);
	    option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true);
	    option("showCursorWhenSelecting", false, updateSelection, true);

	    option("resetSelectionOnContextMenu", true);
	    option("lineWiseCopyCut", true);
	    option("pasteLinesPerSelection", true);
	    option("selectionsMayTouch", false);

	    option("readOnly", false, function (cm, val) {
	      if (val == "nocursor") {
	        onBlur(cm);
	        cm.display.input.blur();
	      }
	      cm.display.input.readOnlyChanged(val);
	    });
	    option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true);
	    option("dragDrop", true, dragDropChanged);
	    option("allowDropFileTypes", null);

	    option("cursorBlinkRate", 530);
	    option("cursorScrollMargin", 0);
	    option("cursorHeight", 1, updateSelection, true);
	    option("singleCursorHeightPerLine", true, updateSelection, true);
	    option("workTime", 100);
	    option("workDelay", 100);
	    option("flattenSpans", true, resetModeState, true);
	    option("addModeClass", false, resetModeState, true);
	    option("pollInterval", 100);
	    option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; });
	    option("historyEventDelay", 1250);
	    option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true);
	    option("maxHighlightLength", 10000, resetModeState, true);
	    option("moveInputWithCursor", true, function (cm, val) {
	      if (!val) { cm.display.input.resetPosition(); }
	    });

	    option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; });
	    option("autofocus", null);
	    option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true);
	    option("phrases", null);
	  }

	  function guttersChanged(cm) {
	    updateGutters(cm);
	    regChange(cm);
	    alignHorizontally(cm);
	  }

	  function dragDropChanged(cm, value, old) {
	    var wasOn = old && old != Init;
	    if (!value != !wasOn) {
	      var funcs = cm.display.dragFunctions;
	      var toggle = value ? on : off;
	      toggle(cm.display.scroller, "dragstart", funcs.start);
	      toggle(cm.display.scroller, "dragenter", funcs.enter);
	      toggle(cm.display.scroller, "dragover", funcs.over);
	      toggle(cm.display.scroller, "dragleave", funcs.leave);
	      toggle(cm.display.scroller, "drop", funcs.drop);
	    }
	  }

	  function wrappingChanged(cm) {
	    if (cm.options.lineWrapping) {
	      addClass(cm.display.wrapper, "CodeMirror-wrap");
	      cm.display.sizer.style.minWidth = "";
	      cm.display.sizerWidth = null;
	    } else {
	      rmClass(cm.display.wrapper, "CodeMirror-wrap");
	      findMaxLine(cm);
	    }
	    estimateLineHeights(cm);
	    regChange(cm);
	    clearCaches(cm);
	    setTimeout(function () { return updateScrollbars(cm); }, 100);
	  }

	  // A CodeMirror instance represents an editor. This is the object
	  // that user code is usually dealing with.

	  function CodeMirror(place, options) {
	    var this$1 = this;

	    if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) }

	    this.options = options = options ? copyObj(options) : {};
	    // Determine effective options based on given values and defaults.
	    copyObj(defaults, options, false);
	    setGuttersForLineNumbers(options);

	    var doc = options.value;
	    if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); }
	    else if (options.mode) { doc.modeOption = options.mode; }
	    this.doc = doc;

	    var input = new CodeMirror.inputStyles[options.inputStyle](this);
	    var display = this.display = new Display(place, doc, input);
	    display.wrapper.CodeMirror = this;
	    updateGutters(this);
	    themeChanged(this);
	    if (options.lineWrapping)
	      { this.display.wrapper.className += " CodeMirror-wrap"; }
	    initScrollbars(this);

	    this.state = {
	      keyMaps: [],  // stores maps added by addKeyMap
	      overlays: [], // highlighting overlays, as added by addOverlay
	      modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
	      overwrite: false,
	      delayingBlurEvent: false,
	      focused: false,
	      suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
	      pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
	      selectingText: false,
	      draggingText: false,
	      highlight: new Delayed(), // stores highlight worker timeout
	      keySeq: null,  // Unfinished key sequence
	      specialChars: null
	    };

	    if (options.autofocus && !mobile) { display.input.focus(); }

	    // Override magic textarea content restore that IE sometimes does
	    // on our hidden textarea on reload
	    if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); }

	    registerEventHandlers(this);
	    ensureGlobalHandlers();

	    startOperation(this);
	    this.curOp.forceUpdate = true;
	    attachDoc(this, doc);

	    if ((options.autofocus && !mobile) || this.hasFocus())
	      { setTimeout(bind(onFocus, this), 20); }
	    else
	      { onBlur(this); }

	    for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
	      { optionHandlers[opt](this$1, options[opt], Init); } }
	    maybeUpdateLineNumberWidth(this);
	    if (options.finishInit) { options.finishInit(this); }
	    for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1); }
	    endOperation(this);
	    // Suppress optimizelegibility in Webkit, since it breaks text
	    // measuring on line wrapping boundaries.
	    if (webkit && options.lineWrapping &&
	        getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
	      { display.lineDiv.style.textRendering = "auto"; }
	  }

	  // The default configuration options.
	  CodeMirror.defaults = defaults;
	  // Functions to run when options are changed.
	  CodeMirror.optionHandlers = optionHandlers;

	  // Attach the necessary event handlers when initializing the editor
	  function registerEventHandlers(cm) {
	    var d = cm.display;
	    on(d.scroller, "mousedown", operation(cm, onMouseDown));
	    // Older IE's will not fire a second mousedown for a double click
	    if (ie && ie_version < 11)
	      { on(d.scroller, "dblclick", operation(cm, function (e) {
	        if (signalDOMEvent(cm, e)) { return }
	        var pos = posFromMouse(cm, e);
	        if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }
	        e_preventDefault(e);
	        var word = cm.findWordAt(pos);
	        extendSelection(cm.doc, word.anchor, word.head);
	      })); }
	    else
	      { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); }
	    // Some browsers fire contextmenu *after* opening the menu, at
	    // which point we can't mess with it anymore. Context menu is
	    // handled in onMouseDown for these browsers.
	    on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); });

	    // Used to suppress mouse event handling when a touch happens
	    var touchFinished, prevTouch = {end: 0};
	    function finishTouch() {
	      if (d.activeTouch) {
	        touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000);
	        prevTouch = d.activeTouch;
	        prevTouch.end = +new Date;
	      }
	    }
	    function isMouseLikeTouchEvent(e) {
	      if (e.touches.length != 1) { return false }
	      var touch = e.touches[0];
	      return touch.radiusX <= 1 && touch.radiusY <= 1
	    }
	    function farAway(touch, other) {
	      if (other.left == null) { return true }
	      var dx = other.left - touch.left, dy = other.top - touch.top;
	      return dx * dx + dy * dy > 20 * 20
	    }
	    on(d.scroller, "touchstart", function (e) {
	      if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) {
	        d.input.ensurePolled();
	        clearTimeout(touchFinished);
	        var now = +new Date;
	        d.activeTouch = {start: now, moved: false,
	                         prev: now - prevTouch.end <= 300 ? prevTouch : null};
	        if (e.touches.length == 1) {
	          d.activeTouch.left = e.touches[0].pageX;
	          d.activeTouch.top = e.touches[0].pageY;
	        }
	      }
	    });
	    on(d.scroller, "touchmove", function () {
	      if (d.activeTouch) { d.activeTouch.moved = true; }
	    });
	    on(d.scroller, "touchend", function (e) {
	      var touch = d.activeTouch;
	      if (touch && !eventInWidget(d, e) && touch.left != null &&
	          !touch.moved && new Date - touch.start < 300) {
	        var pos = cm.coordsChar(d.activeTouch, "page"), range;
	        if (!touch.prev || farAway(touch, touch.prev)) // Single tap
	          { range = new Range(pos, pos); }
	        else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
	          { range = cm.findWordAt(pos); }
	        else // Triple tap
	          { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); }
	        cm.setSelection(range.anchor, range.head);
	        cm.focus();
	        e_preventDefault(e);
	      }
	      finishTouch();
	    });
	    on(d.scroller, "touchcancel", finishTouch);

	    // Sync scrolling between fake scrollbars and real scrollable
	    // area, ensure viewport is updated when scrolling.
	    on(d.scroller, "scroll", function () {
	      if (d.scroller.clientHeight) {
	        updateScrollTop(cm, d.scroller.scrollTop);
	        setScrollLeft(cm, d.scroller.scrollLeft, true);
	        signal(cm, "scroll", cm);
	      }
	    });

	    // Listen to wheel events in order to try and update the viewport on time.
	    on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); });
	    on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); });

	    // Prevent wrapper from ever scrolling
	    on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });

	    d.dragFunctions = {
	      enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }},
	      over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
	      start: function (e) { return onDragStart(cm, e); },
	      drop: operation(cm, onDrop),
	      leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }}
	    };

	    var inp = d.input.getField();
	    on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); });
	    on(inp, "keydown", operation(cm, onKeyDown));
	    on(inp, "keypress", operation(cm, onKeyPress));
	    on(inp, "focus", function (e) { return onFocus(cm, e); });
	    on(inp, "blur", function (e) { return onBlur(cm, e); });
	  }

	  var initHooks = [];
	  CodeMirror.defineInitHook = function (f) { return initHooks.push(f); };

	  // Indent the given line. The how parameter can be "smart",
	  // "add"/null, "subtract", or "prev". When aggressive is false
	  // (typically set to true for forced single-line indents), empty
	  // lines are not indented, and places where the mode returns Pass
	  // are left alone.
	  function indentLine(cm, n, how, aggressive) {
	    var doc = cm.doc, state;
	    if (how == null) { how = "add"; }
	    if (how == "smart") {
	      // Fall back to "prev" when the mode doesn't have an indentation
	      // method.
	      if (!doc.mode.indent) { how = "prev"; }
	      else { state = getContextBefore(cm, n).state; }
	    }

	    var tabSize = cm.options.tabSize;
	    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
	    if (line.stateAfter) { line.stateAfter = null; }
	    var curSpaceString = line.text.match(/^\s*/)[0], indentation;
	    if (!aggressive && !/\S/.test(line.text)) {
	      indentation = 0;
	      how = "not";
	    } else if (how == "smart") {
	      indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
	      if (indentation == Pass || indentation > 150) {
	        if (!aggressive) { return }
	        how = "prev";
	      }
	    }
	    if (how == "prev") {
	      if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); }
	      else { indentation = 0; }
	    } else if (how == "add") {
	      indentation = curSpace + cm.options.indentUnit;
	    } else if (how == "subtract") {
	      indentation = curSpace - cm.options.indentUnit;
	    } else if (typeof how == "number") {
	      indentation = curSpace + how;
	    }
	    indentation = Math.max(0, indentation);

	    var indentString = "", pos = 0;
	    if (cm.options.indentWithTabs)
	      { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} }
	    if (pos < indentation) { indentString += spaceStr(indentation - pos); }

	    if (indentString != curSpaceString) {
	      replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
	      line.stateAfter = null;
	      return true
	    } else {
	      // Ensure that, if the cursor was in the whitespace at the start
	      // of the line, it is moved to the end of that space.
	      for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {
	        var range = doc.sel.ranges[i$1];
	        if (range.head.line == n && range.head.ch < curSpaceString.length) {
	          var pos$1 = Pos(n, curSpaceString.length);
	          replaceOneSelection(doc, i$1, new Range(pos$1, pos$1));
	          break
	        }
	      }
	    }
	  }

	  // This will be set to a {lineWise: bool, text: [string]} object, so
	  // that, when pasting, we know what kind of selections the copied
	  // text was made out of.
	  var lastCopied = null;

	  function setLastCopied(newLastCopied) {
	    lastCopied = newLastCopied;
	  }

	  function applyTextInput(cm, inserted, deleted, sel, origin) {
	    var doc = cm.doc;
	    cm.display.shift = false;
	    if (!sel) { sel = doc.sel; }

	    var paste = cm.state.pasteIncoming || origin == "paste";
	    var textLines = splitLinesAuto(inserted), multiPaste = null;
	    // When pasting N lines into N selections, insert one line per selection
	    if (paste && sel.ranges.length > 1) {
	      if (lastCopied && lastCopied.text.join("\n") == inserted) {
	        if (sel.ranges.length % lastCopied.text.length == 0) {
	          multiPaste = [];
	          for (var i = 0; i < lastCopied.text.length; i++)
	            { multiPaste.push(doc.splitLines(lastCopied.text[i])); }
	        }
	      } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) {
	        multiPaste = map(textLines, function (l) { return [l]; });
	      }
	    }

	    var updateInput = cm.curOp.updateInput;
	    // Normal behavior is to insert the new text into every selection
	    for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
	      var range$$1 = sel.ranges[i$1];
	      var from = range$$1.from(), to = range$$1.to();
	      if (range$$1.empty()) {
	        if (deleted && deleted > 0) // Handle deletion
	          { from = Pos(from.line, from.ch - deleted); }
	        else if (cm.state.overwrite && !paste) // Handle overwrite
	          { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); }
	        else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
	          { from = to = Pos(from.line, 0); }
	      }
	      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
	                         origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
	      makeChange(cm.doc, changeEvent);
	      signalLater(cm, "inputRead", cm, changeEvent);
	    }
	    if (inserted && !paste)
	      { triggerElectric(cm, inserted); }

	    ensureCursorVisible(cm);
	    if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; }
	    cm.curOp.typing = true;
	    cm.state.pasteIncoming = cm.state.cutIncoming = false;
	  }

	  function handlePaste(e, cm) {
	    var pasted = e.clipboardData && e.clipboardData.getData("Text");
	    if (pasted) {
	      e.preventDefault();
	      if (!cm.isReadOnly() && !cm.options.disableInput)
	        { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); }
	      return true
	    }
	  }

	  function triggerElectric(cm, inserted) {
	    // When an 'electric' character is inserted, immediately trigger a reindent
	    if (!cm.options.electricChars || !cm.options.smartIndent) { return }
	    var sel = cm.doc.sel;

	    for (var i = sel.ranges.length - 1; i >= 0; i--) {
	      var range$$1 = sel.ranges[i];
	      if (range$$1.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range$$1.head.line)) { continue }
	      var mode = cm.getModeAt(range$$1.head);
	      var indented = false;
	      if (mode.electricChars) {
	        for (var j = 0; j < mode.electricChars.length; j++)
	          { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
	            indented = indentLine(cm, range$$1.head.line, "smart");
	            break
	          } }
	      } else if (mode.electricInput) {
	        if (mode.electricInput.test(getLine(cm.doc, range$$1.head.line).text.slice(0, range$$1.head.ch)))
	          { indented = indentLine(cm, range$$1.head.line, "smart"); }
	      }
	      if (indented) { signalLater(cm, "electricInput", cm, range$$1.head.line); }
	    }
	  }

	  function copyableRanges(cm) {
	    var text = [], ranges = [];
	    for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
	      var line = cm.doc.sel.ranges[i].head.line;
	      var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
	      ranges.push(lineRange);
	      text.push(cm.getRange(lineRange.anchor, lineRange.head));
	    }
	    return {text: text, ranges: ranges}
	  }

	  function disableBrowserMagic(field, spellcheck) {
	    field.setAttribute("autocorrect", "off");
	    field.setAttribute("autocapitalize", "off");
	    field.setAttribute("spellcheck", !!spellcheck);
	  }

	  function hiddenTextarea() {
	    var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none");
	    var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
	    // The textarea is kept positioned near the cursor to prevent the
	    // fact that it'll be scrolled into view on input from scrolling
	    // our fake cursor out of view. On webkit, when wrap=off, paste is
	    // very slow. So make the area wide instead.
	    if (webkit) { te.style.width = "1000px"; }
	    else { te.setAttribute("wrap", "off"); }
	    // If border: 0; -- iOS fails to open keyboard (issue #1287)
	    if (ios) { te.style.border = "1px solid black"; }
	    disableBrowserMagic(te);
	    return div
	  }

	  // The publicly visible API. Note that methodOp(f) means
	  // 'wrap f in an operation, performed on its `this` parameter'.

	  // This is not the complete set of editor methods. Most of the
	  // methods defined on the Doc type are also injected into
	  // CodeMirror.prototype, for backwards compatibility and
	  // convenience.

	  function addEditorMethods(CodeMirror) {
	    var optionHandlers = CodeMirror.optionHandlers;

	    var helpers = CodeMirror.helpers = {};

	    CodeMirror.prototype = {
	      constructor: CodeMirror,
	      focus: function(){window.focus(); this.display.input.focus();},

	      setOption: function(option, value) {
	        var options = this.options, old = options[option];
	        if (options[option] == value && option != "mode") { return }
	        options[option] = value;
	        if (optionHandlers.hasOwnProperty(option))
	          { operation(this, optionHandlers[option])(this, value, old); }
	        signal(this, "optionChange", this, option);
	      },

	      getOption: function(option) {return this.options[option]},
	      getDoc: function() {return this.doc},

	      addKeyMap: function(map$$1, bottom) {
	        this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map$$1));
	      },
	      removeKeyMap: function(map$$1) {
	        var maps = this.state.keyMaps;
	        for (var i = 0; i < maps.length; ++i)
	          { if (maps[i] == map$$1 || maps[i].name == map$$1) {
	            maps.splice(i, 1);
	            return true
	          } }
	      },

	      addOverlay: methodOp(function(spec, options) {
	        var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
	        if (mode.startState) { throw new Error("Overlays may not be stateful.") }
	        insertSorted(this.state.overlays,
	                     {mode: mode, modeSpec: spec, opaque: options && options.opaque,
	                      priority: (options && options.priority) || 0},
	                     function (overlay) { return overlay.priority; });
	        this.state.modeGen++;
	        regChange(this);
	      }),
	      removeOverlay: methodOp(function(spec) {
	        var this$1 = this;

	        var overlays = this.state.overlays;
	        for (var i = 0; i < overlays.length; ++i) {
	          var cur = overlays[i].modeSpec;
	          if (cur == spec || typeof spec == "string" && cur.name == spec) {
	            overlays.splice(i, 1);
	            this$1.state.modeGen++;
	            regChange(this$1);
	            return
	          }
	        }
	      }),

	      indentLine: methodOp(function(n, dir, aggressive) {
	        if (typeof dir != "string" && typeof dir != "number") {
	          if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; }
	          else { dir = dir ? "add" : "subtract"; }
	        }
	        if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); }
	      }),
	      indentSelection: methodOp(function(how) {
	        var this$1 = this;

	        var ranges = this.doc.sel.ranges, end = -1;
	        for (var i = 0; i < ranges.length; i++) {
	          var range$$1 = ranges[i];
	          if (!range$$1.empty()) {
	            var from = range$$1.from(), to = range$$1.to();
	            var start = Math.max(end, from.line);
	            end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
	            for (var j = start; j < end; ++j)
	              { indentLine(this$1, j, how); }
	            var newRanges = this$1.doc.sel.ranges;
	            if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
	              { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); }
	          } else if (range$$1.head.line > end) {
	            indentLine(this$1, range$$1.head.line, how, true);
	            end = range$$1.head.line;
	            if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1); }
	          }
	        }
	      }),

	      // Fetch the parser token for a given character. Useful for hacks
	      // that want to inspect the mode state (say, for completion).
	      getTokenAt: function(pos, precise) {
	        return takeToken(this, pos, precise)
	      },

	      getLineTokens: function(line, precise) {
	        return takeToken(this, Pos(line), precise, true)
	      },

	      getTokenTypeAt: function(pos) {
	        pos = clipPos(this.doc, pos);
	        var styles = getLineStyles(this, getLine(this.doc, pos.line));
	        var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
	        var type;
	        if (ch == 0) { type = styles[2]; }
	        else { for (;;) {
	          var mid = (before + after) >> 1;
	          if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; }
	          else if (styles[mid * 2 + 1] < ch) { before = mid + 1; }
	          else { type = styles[mid * 2 + 2]; break }
	        } }
	        var cut = type ? type.indexOf("overlay ") : -1;
	        return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)
	      },

	      getModeAt: function(pos) {
	        var mode = this.doc.mode;
	        if (!mode.innerMode) { return mode }
	        return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode
	      },

	      getHelper: function(pos, type) {
	        return this.getHelpers(pos, type)[0]
	      },

	      getHelpers: function(pos, type) {
	        var this$1 = this;

	        var found = [];
	        if (!helpers.hasOwnProperty(type)) { return found }
	        var help = helpers[type], mode = this.getModeAt(pos);
	        if (typeof mode[type] == "string") {
	          if (help[mode[type]]) { found.push(help[mode[type]]); }
	        } else if (mode[type]) {
	          for (var i = 0; i < mode[type].length; i++) {
	            var val = help[mode[type][i]];
	            if (val) { found.push(val); }
	          }
	        } else if (mode.helperType && help[mode.helperType]) {
	          found.push(help[mode.helperType]);
	        } else if (help[mode.name]) {
	          found.push(help[mode.name]);
	        }
	        for (var i$1 = 0; i$1 < help._global.length; i$1++) {
	          var cur = help._global[i$1];
	          if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1)
	            { found.push(cur.val); }
	        }
	        return found
	      },

	      getStateAfter: function(line, precise) {
	        var doc = this.doc;
	        line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
	        return getContextBefore(this, line + 1, precise).state
	      },

	      cursorCoords: function(start, mode) {
	        var pos, range$$1 = this.doc.sel.primary();
	        if (start == null) { pos = range$$1.head; }
	        else if (typeof start == "object") { pos = clipPos(this.doc, start); }
	        else { pos = start ? range$$1.from() : range$$1.to(); }
	        return cursorCoords(this, pos, mode || "page")
	      },

	      charCoords: function(pos, mode) {
	        return charCoords(this, clipPos(this.doc, pos), mode || "page")
	      },

	      coordsChar: function(coords, mode) {
	        coords = fromCoordSystem(this, coords, mode || "page");
	        return coordsChar(this, coords.left, coords.top)
	      },

	      lineAtHeight: function(height, mode) {
	        height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
	        return lineAtHeight(this.doc, height + this.display.viewOffset)
	      },
	      heightAtLine: function(line, mode, includeWidgets) {
	        var end = false, lineObj;
	        if (typeof line == "number") {
	          var last = this.doc.first + this.doc.size - 1;
	          if (line < this.doc.first) { line = this.doc.first; }
	          else if (line > last) { line = last; end = true; }
	          lineObj = getLine(this.doc, line);
	        } else {
	          lineObj = line;
	        }
	        return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top +
	          (end ? this.doc.height - heightAtLine(lineObj) : 0)
	      },

	      defaultTextHeight: function() { return textHeight(this.display) },
	      defaultCharWidth: function() { return charWidth(this.display) },

	      getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},

	      addWidget: function(pos, node, scroll, vert, horiz) {
	        var display = this.display;
	        pos = cursorCoords(this, clipPos(this.doc, pos));
	        var top = pos.bottom, left = pos.left;
	        node.style.position = "absolute";
	        node.setAttribute("cm-ignore-events", "true");
	        this.display.input.setUneditable(node);
	        display.sizer.appendChild(node);
	        if (vert == "over") {
	          top = pos.top;
	        } else if (vert == "above" || vert == "near") {
	          var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
	          hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
	          // Default to positioning above (if specified and possible); otherwise default to positioning below
	          if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
	            { top = pos.top - node.offsetHeight; }
	          else if (pos.bottom + node.offsetHeight <= vspace)
	            { top = pos.bottom; }
	          if (left + node.offsetWidth > hspace)
	            { left = hspace - node.offsetWidth; }
	        }
	        node.style.top = top + "px";
	        node.style.left = node.style.right = "";
	        if (horiz == "right") {
	          left = display.sizer.clientWidth - node.offsetWidth;
	          node.style.right = "0px";
	        } else {
	          if (horiz == "left") { left = 0; }
	          else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; }
	          node.style.left = left + "px";
	        }
	        if (scroll)
	          { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); }
	      },

	      triggerOnKeyDown: methodOp(onKeyDown),
	      triggerOnKeyPress: methodOp(onKeyPress),
	      triggerOnKeyUp: onKeyUp,
	      triggerOnMouseDown: methodOp(onMouseDown),

	      execCommand: function(cmd) {
	        if (commands.hasOwnProperty(cmd))
	          { return commands[cmd].call(null, this) }
	      },

	      triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),

	      findPosH: function(from, amount, unit, visually) {
	        var this$1 = this;

	        var dir = 1;
	        if (amount < 0) { dir = -1; amount = -amount; }
	        var cur = clipPos(this.doc, from);
	        for (var i = 0; i < amount; ++i) {
	          cur = findPosH(this$1.doc, cur, dir, unit, visually);
	          if (cur.hitSide) { break }
	        }
	        return cur
	      },

	      moveH: methodOp(function(dir, unit) {
	        var this$1 = this;

	        this.extendSelectionsBy(function (range$$1) {
	          if (this$1.display.shift || this$1.doc.extend || range$$1.empty())
	            { return findPosH(this$1.doc, range$$1.head, dir, unit, this$1.options.rtlMoveVisually) }
	          else
	            { return dir < 0 ? range$$1.from() : range$$1.to() }
	        }, sel_move);
	      }),

	      deleteH: methodOp(function(dir, unit) {
	        var sel = this.doc.sel, doc = this.doc;
	        if (sel.somethingSelected())
	          { doc.replaceSelection("", null, "+delete"); }
	        else
	          { deleteNearSelection(this, function (range$$1) {
	            var other = findPosH(doc, range$$1.head, dir, unit, false);
	            return dir < 0 ? {from: other, to: range$$1.head} : {from: range$$1.head, to: other}
	          }); }
	      }),

	      findPosV: function(from, amount, unit, goalColumn) {
	        var this$1 = this;

	        var dir = 1, x = goalColumn;
	        if (amount < 0) { dir = -1; amount = -amount; }
	        var cur = clipPos(this.doc, from);
	        for (var i = 0; i < amount; ++i) {
	          var coords = cursorCoords(this$1, cur, "div");
	          if (x == null) { x = coords.left; }
	          else { coords.left = x; }
	          cur = findPosV(this$1, coords, dir, unit);
	          if (cur.hitSide) { break }
	        }
	        return cur
	      },

	      moveV: methodOp(function(dir, unit) {
	        var this$1 = this;

	        var doc = this.doc, goals = [];
	        var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected();
	        doc.extendSelectionsBy(function (range$$1) {
	          if (collapse)
	            { return dir < 0 ? range$$1.from() : range$$1.to() }
	          var headPos = cursorCoords(this$1, range$$1.head, "div");
	          if (range$$1.goalColumn != null) { headPos.left = range$$1.goalColumn; }
	          goals.push(headPos.left);
	          var pos = findPosV(this$1, headPos, dir, unit);
	          if (unit == "page" && range$$1 == doc.sel.primary())
	            { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); }
	          return pos
	        }, sel_move);
	        if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
	          { doc.sel.ranges[i].goalColumn = goals[i]; } }
	      }),

	      // Find the word at the given position (as returned by coordsChar).
	      findWordAt: function(pos) {
	        var doc = this.doc, line = getLine(doc, pos.line).text;
	        var start = pos.ch, end = pos.ch;
	        if (line) {
	          var helper = this.getHelper(pos, "wordChars");
	          if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; }
	          var startChar = line.charAt(start);
	          var check = isWordChar(startChar, helper)
	            ? function (ch) { return isWordChar(ch, helper); }
	            : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); }
	            : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); };
	          while (start > 0 && check(line.charAt(start - 1))) { --start; }
	          while (end < line.length && check(line.charAt(end))) { ++end; }
	        }
	        return new Range(Pos(pos.line, start), Pos(pos.line, end))
	      },

	      toggleOverwrite: function(value) {
	        if (value != null && value == this.state.overwrite) { return }
	        if (this.state.overwrite = !this.state.overwrite)
	          { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); }
	        else
	          { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); }

	        signal(this, "overwriteToggle", this, this.state.overwrite);
	      },
	      hasFocus: function() { return this.display.input.getField() == activeElt() },
	      isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },

	      scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }),
	      getScrollInfo: function() {
	        var scroller = this.display.scroller;
	        return {left: scroller.scrollLeft, top: scroller.scrollTop,
	                height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
	                width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
	                clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
	      },

	      scrollIntoView: methodOp(function(range$$1, margin) {
	        if (range$$1 == null) {
	          range$$1 = {from: this.doc.sel.primary().head, to: null};
	          if (margin == null) { margin = this.options.cursorScrollMargin; }
	        } else if (typeof range$$1 == "number") {
	          range$$1 = {from: Pos(range$$1, 0), to: null};
	        } else if (range$$1.from == null) {
	          range$$1 = {from: range$$1, to: null};
	        }
	        if (!range$$1.to) { range$$1.to = range$$1.from; }
	        range$$1.margin = margin || 0;

	        if (range$$1.from.line != null) {
	          scrollToRange(this, range$$1);
	        } else {
	          scrollToCoordsRange(this, range$$1.from, range$$1.to, range$$1.margin);
	        }
	      }),

	      setSize: methodOp(function(width, height) {
	        var this$1 = this;

	        var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; };
	        if (width != null) { this.display.wrapper.style.width = interpret(width); }
	        if (height != null) { this.display.wrapper.style.height = interpret(height); }
	        if (this.options.lineWrapping) { clearLineMeasurementCache(this); }
	        var lineNo$$1 = this.display.viewFrom;
	        this.doc.iter(lineNo$$1, this.display.viewTo, function (line) {
	          if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
	            { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo$$1, "widget"); break } } }
	          ++lineNo$$1;
	        });
	        this.curOp.forceUpdate = true;
	        signal(this, "refresh", this);
	      }),

	      operation: function(f){return runInOp(this, f)},
	      startOperation: function(){return startOperation(this)},
	      endOperation: function(){return endOperation(this)},

	      refresh: methodOp(function() {
	        var oldHeight = this.display.cachedTextHeight;
	        regChange(this);
	        this.curOp.forceUpdate = true;
	        clearCaches(this);
	        scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop);
	        updateGutterSpace(this);
	        if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
	          { estimateLineHeights(this); }
	        signal(this, "refresh", this);
	      }),

	      swapDoc: methodOp(function(doc) {
	        var old = this.doc;
	        old.cm = null;
	        attachDoc(this, doc);
	        clearCaches(this);
	        this.display.input.reset();
	        scrollToCoords(this, doc.scrollLeft, doc.scrollTop);
	        this.curOp.forceScroll = true;
	        signalLater(this, "swapDoc", this, old);
	        return old
	      }),

	      phrase: function(phraseText) {
	        var phrases = this.options.phrases;
	        return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText
	      },

	      getInputField: function(){return this.display.input.getField()},
	      getWrapperElement: function(){return this.display.wrapper},
	      getScrollerElement: function(){return this.display.scroller},
	      getGutterElement: function(){return this.display.gutters}
	    };
	    eventMixin(CodeMirror);

	    CodeMirror.registerHelper = function(type, name, value) {
	      if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; }
	      helpers[type][name] = value;
	    };
	    CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
	      CodeMirror.registerHelper(type, name, value);
	      helpers[type]._global.push({pred: predicate, val: value});
	    };
	  }

	  // Used for horizontal relative motion. Dir is -1 or 1 (left or
	  // right), unit can be "char", "column" (like char, but doesn't
	  // cross line boundaries), "word" (across next word), or "group" (to
	  // the start of next group of word or non-word-non-whitespace
	  // chars). The visually param controls whether, in right-to-left
	  // text, direction 1 means to move towards the next index in the
	  // string, or towards the character to the right of the current
	  // position. The resulting position will have a hitSide=true
	  // property if it reached the end of the document.
	  function findPosH(doc, pos, dir, unit, visually) {
	    var oldPos = pos;
	    var origDir = dir;
	    var lineObj = getLine(doc, pos.line);
	    function findNextLine() {
	      var l = pos.line + dir;
	      if (l < doc.first || l >= doc.first + doc.size) { return false }
	      pos = new Pos(l, pos.ch, pos.sticky);
	      return lineObj = getLine(doc, l)
	    }
	    function moveOnce(boundToLine) {
	      var next;
	      if (visually) {
	        next = moveVisually(doc.cm, lineObj, pos, dir);
	      } else {
	        next = moveLogically(lineObj, pos, dir);
	      }
	      if (next == null) {
	        if (!boundToLine && findNextLine())
	          { pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir); }
	        else
	          { return false }
	      } else {
	        pos = next;
	      }
	      return true
	    }

	    if (unit == "char") {
	      moveOnce();
	    } else if (unit == "column") {
	      moveOnce(true);
	    } else if (unit == "word" || unit == "group") {
	      var sawType = null, group = unit == "group";
	      var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
	      for (var first = true;; first = false) {
	        if (dir < 0 && !moveOnce(!first)) { break }
	        var cur = lineObj.text.charAt(pos.ch) || "\n";
	        var type = isWordChar(cur, helper) ? "w"
	          : group && cur == "\n" ? "n"
	          : !group || /\s/.test(cur) ? null
	          : "p";
	        if (group && !first && !type) { type = "s"; }
	        if (sawType && sawType != type) {
	          if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";}
	          break
	        }

	        if (type) { sawType = type; }
	        if (dir > 0 && !moveOnce(!first)) { break }
	      }
	    }
	    var result = skipAtomic(doc, pos, oldPos, origDir, true);
	    if (equalCursorPos(oldPos, result)) { result.hitSide = true; }
	    return result
	  }

	  // For relative vertical movement. Dir may be -1 or 1. Unit can be
	  // "page" or "line". The resulting position will have a hitSide=true
	  // property if it reached the end of the document.
	  function findPosV(cm, pos, dir, unit) {
	    var doc = cm.doc, x = pos.left, y;
	    if (unit == "page") {
	      var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
	      var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3);
	      y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount;

	    } else if (unit == "line") {
	      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
	    }
	    var target;
	    for (;;) {
	      target = coordsChar(cm, x, y);
	      if (!target.outside) { break }
	      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }
	      y += dir * 5;
	    }
	    return target
	  }

	  // CONTENTEDITABLE INPUT STYLE

	  var ContentEditableInput = function(cm) {
	    this.cm = cm;
	    this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
	    this.polling = new Delayed();
	    this.composing = null;
	    this.gracePeriod = false;
	    this.readDOMTimeout = null;
	  };

	  ContentEditableInput.prototype.init = function (display) {
	      var this$1 = this;

	    var input = this, cm = input.cm;
	    var div = input.div = display.lineDiv;
	    disableBrowserMagic(div, cm.options.spellcheck);

	    on(div, "paste", function (e) {
	      if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
	      // IE doesn't fire input events, so we schedule a read for the pasted content in this way
	      if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); }
	    });

	    on(div, "compositionstart", function (e) {
	      this$1.composing = {data: e.data, done: false};
	    });
	    on(div, "compositionupdate", function (e) {
	      if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; }
	    });
	    on(div, "compositionend", function (e) {
	      if (this$1.composing) {
	        if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); }
	        this$1.composing.done = true;
	      }
	    });

	    on(div, "touchstart", function () { return input.forceCompositionEnd(); });

	    on(div, "input", function () {
	      if (!this$1.composing) { this$1.readFromDOMSoon(); }
	    });

	    function onCopyCut(e) {
	      if (signalDOMEvent(cm, e)) { return }
	      if (cm.somethingSelected()) {
	        setLastCopied({lineWise: false, text: cm.getSelections()});
	        if (e.type == "cut") { cm.replaceSelection("", null, "cut"); }
	      } else if (!cm.options.lineWiseCopyCut) {
	        return
	      } else {
	        var ranges = copyableRanges(cm);
	        setLastCopied({lineWise: true, text: ranges.text});
	        if (e.type == "cut") {
	          cm.operation(function () {
	            cm.setSelections(ranges.ranges, 0, sel_dontScroll);
	            cm.replaceSelection("", null, "cut");
	          });
	        }
	      }
	      if (e.clipboardData) {
	        e.clipboardData.clearData();
	        var content = lastCopied.text.join("\n");
	        // iOS exposes the clipboard API, but seems to discard content inserted into it
	        e.clipboardData.setData("Text", content);
	        if (e.clipboardData.getData("Text") == content) {
	          e.preventDefault();
	          return
	        }
	      }
	      // Old-fashioned briefly-focus-a-textarea hack
	      var kludge = hiddenTextarea(), te = kludge.firstChild;
	      cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
	      te.value = lastCopied.text.join("\n");
	      var hadFocus = document.activeElement;
	      selectInput(te);
	      setTimeout(function () {
	        cm.display.lineSpace.removeChild(kludge);
	        hadFocus.focus();
	        if (hadFocus == div) { input.showPrimarySelection(); }
	      }, 50);
	    }
	    on(div, "copy", onCopyCut);
	    on(div, "cut", onCopyCut);
	  };

	  ContentEditableInput.prototype.prepareSelection = function () {
	    var result = prepareSelection(this.cm, false);
	    result.focus = this.cm.state.focused;
	    return result
	  };

	  ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
	    if (!info || !this.cm.display.view.length) { return }
	    if (info.focus || takeFocus) { this.showPrimarySelection(); }
	    this.showMultipleSelections(info);
	  };

	  ContentEditableInput.prototype.getSelection = function () {
	    return this.cm.display.wrapper.ownerDocument.getSelection()
	  };

	  ContentEditableInput.prototype.showPrimarySelection = function () {
	    var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary();
	    var from = prim.from(), to = prim.to();

	    if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) {
	      sel.removeAllRanges();
	      return
	    }

	    var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
	    var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset);
	    if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
	        cmp(minPos(curAnchor, curFocus), from) == 0 &&
	        cmp(maxPos(curAnchor, curFocus), to) == 0)
	      { return }

	    var view = cm.display.view;
	    var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) ||
	        {node: view[0].measure.map[2], offset: 0};
	    var end = to.line < cm.display.viewTo && posToDOM(cm, to);
	    if (!end) {
	      var measure = view[view.length - 1].measure;
	      var map$$1 = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
	      end = {node: map$$1[map$$1.length - 1], offset: map$$1[map$$1.length - 2] - map$$1[map$$1.length - 3]};
	    }

	    if (!start || !end) {
	      sel.removeAllRanges();
	      return
	    }

	    var old = sel.rangeCount && sel.getRangeAt(0), rng;
	    try { rng = range(start.node, start.offset, end.offset, end.node); }
	    catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
	    if (rng) {
	      if (!gecko && cm.state.focused) {
	        sel.collapse(start.node, start.offset);
	        if (!rng.collapsed) {
	          sel.removeAllRanges();
	          sel.addRange(rng);
	        }
	      } else {
	        sel.removeAllRanges();
	        sel.addRange(rng);
	      }
	      if (old && sel.anchorNode == null) { sel.addRange(old); }
	      else if (gecko) { this.startGracePeriod(); }
	    }
	    this.rememberSelection();
	  };

	  ContentEditableInput.prototype.startGracePeriod = function () {
	      var this$1 = this;

	    clearTimeout(this.gracePeriod);
	    this.gracePeriod = setTimeout(function () {
	      this$1.gracePeriod = false;
	      if (this$1.selectionChanged())
	        { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); }
	    }, 20);
	  };

	  ContentEditableInput.prototype.showMultipleSelections = function (info) {
	    removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
	    removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
	  };

	  ContentEditableInput.prototype.rememberSelection = function () {
	    var sel = this.getSelection();
	    this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
	    this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
	  };

	  ContentEditableInput.prototype.selectionInEditor = function () {
	    var sel = this.getSelection();
	    if (!sel.rangeCount) { return false }
	    var node = sel.getRangeAt(0).commonAncestorContainer;
	    return contains(this.div, node)
	  };

	  ContentEditableInput.prototype.focus = function () {
	    if (this.cm.options.readOnly != "nocursor") {
	      if (!this.selectionInEditor())
	        { this.showSelection(this.prepareSelection(), true); }
	      this.div.focus();
	    }
	  };
	  ContentEditableInput.prototype.blur = function () { this.div.blur(); };
	  ContentEditableInput.prototype.getField = function () { return this.div };

	  ContentEditableInput.prototype.supportsTouch = function () { return true };

	  ContentEditableInput.prototype.receivedFocus = function () {
	    var input = this;
	    if (this.selectionInEditor())
	      { this.pollSelection(); }
	    else
	      { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }

	    function poll() {
	      if (input.cm.state.focused) {
	        input.pollSelection();
	        input.polling.set(input.cm.options.pollInterval, poll);
	      }
	    }
	    this.polling.set(this.cm.options.pollInterval, poll);
	  };

	  ContentEditableInput.prototype.selectionChanged = function () {
	    var sel = this.getSelection();
	    return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
	      sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
	  };

	  ContentEditableInput.prototype.pollSelection = function () {
	    if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return }
	    var sel = this.getSelection(), cm = this.cm;
	    // On Android Chrome (version 56, at least), backspacing into an
	    // uneditable block element will put the cursor in that element,
	    // and then, because it's not editable, hide the virtual keyboard.
	    // Because Android doesn't allow us to actually detect backspace
	    // presses in a sane way, this code checks for when that happens
	    // and simulates a backspace press in this case.
	    if (android && chrome && this.cm.options.gutters.length && isInGutter(sel.anchorNode)) {
	      this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs});
	      this.blur();
	      this.focus();
	      return
	    }
	    if (this.composing) { return }
	    this.rememberSelection();
	    var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
	    var head = domToPos(cm, sel.focusNode, sel.focusOffset);
	    if (anchor && head) { runInOp(cm, function () {
	      setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
	      if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; }
	    }); }
	  };

	  ContentEditableInput.prototype.pollContent = function () {
	    if (this.readDOMTimeout != null) {
	      clearTimeout(this.readDOMTimeout);
	      this.readDOMTimeout = null;
	    }

	    var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
	    var from = sel.from(), to = sel.to();
	    if (from.ch == 0 && from.line > cm.firstLine())
	      { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); }
	    if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())
	      { to = Pos(to.line + 1, 0); }
	    if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }

	    var fromIndex, fromLine, fromNode;
	    if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
	      fromLine = lineNo(display.view[0].line);
	      fromNode = display.view[0].node;
	    } else {
	      fromLine = lineNo(display.view[fromIndex].line);
	      fromNode = display.view[fromIndex - 1].node.nextSibling;
	    }
	    var toIndex = findViewIndex(cm, to.line);
	    var toLine, toNode;
	    if (toIndex == display.view.length - 1) {
	      toLine = display.viewTo - 1;
	      toNode = display.lineDiv.lastChild;
	    } else {
	      toLine = lineNo(display.view[toIndex + 1].line) - 1;
	      toNode = display.view[toIndex + 1].node.previousSibling;
	    }

	    if (!fromNode) { return false }
	    var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
	    var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
	    while (newText.length > 1 && oldText.length > 1) {
	      if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
	      else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
	      else { break }
	    }

	    var cutFront = 0, cutEnd = 0;
	    var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
	    while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
	      { ++cutFront; }
	    var newBot = lst(newText), oldBot = lst(oldText);
	    var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
	                             oldBot.length - (oldText.length == 1 ? cutFront : 0));
	    while (cutEnd < maxCutEnd &&
	           newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
	      { ++cutEnd; }
	    // Try to move start of change to start of selection if ambiguous
	    if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) {
	      while (cutFront && cutFront > from.ch &&
	             newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) {
	        cutFront--;
	        cutEnd++;
	      }
	    }

	    newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "");
	    newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "");

	    var chFrom = Pos(fromLine, cutFront);
	    var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
	    if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
	      replaceRange(cm.doc, newText, chFrom, chTo, "+input");
	      return true
	    }
	  };

	  ContentEditableInput.prototype.ensurePolled = function () {
	    this.forceCompositionEnd();
	  };
	  ContentEditableInput.prototype.reset = function () {
	    this.forceCompositionEnd();
	  };
	  ContentEditableInput.prototype.forceCompositionEnd = function () {
	    if (!this.composing) { return }
	    clearTimeout(this.readDOMTimeout);
	    this.composing = null;
	    this.updateFromDOM();
	    this.div.blur();
	    this.div.focus();
	  };
	  ContentEditableInput.prototype.readFromDOMSoon = function () {
	      var this$1 = this;

	    if (this.readDOMTimeout != null) { return }
	    this.readDOMTimeout = setTimeout(function () {
	      this$1.readDOMTimeout = null;
	      if (this$1.composing) {
	        if (this$1.composing.done) { this$1.composing = null; }
	        else { return }
	      }
	      this$1.updateFromDOM();
	    }, 80);
	  };

	  ContentEditableInput.prototype.updateFromDOM = function () {
	      var this$1 = this;

	    if (this.cm.isReadOnly() || !this.pollContent())
	      { runInOp(this.cm, function () { return regChange(this$1.cm); }); }
	  };

	  ContentEditableInput.prototype.setUneditable = function (node) {
	    node.contentEditable = "false";
	  };

	  ContentEditableInput.prototype.onKeyPress = function (e) {
	    if (e.charCode == 0 || this.composing) { return }
	    e.preventDefault();
	    if (!this.cm.isReadOnly())
	      { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); }
	  };

	  ContentEditableInput.prototype.readOnlyChanged = function (val) {
	    this.div.contentEditable = String(val != "nocursor");
	  };

	  ContentEditableInput.prototype.onContextMenu = function () {};
	  ContentEditableInput.prototype.resetPosition = function () {};

	  ContentEditableInput.prototype.needsContentAttribute = true;

	  function posToDOM(cm, pos) {
	    var view = findViewForLine(cm, pos.line);
	    if (!view || view.hidden) { return null }
	    var line = getLine(cm.doc, pos.line);
	    var info = mapFromLineView(view, line, pos.line);

	    var order = getOrder(line, cm.doc.direction), side = "left";
	    if (order) {
	      var partPos = getBidiPartAt(order, pos.ch);
	      side = partPos % 2 ? "right" : "left";
	    }
	    var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
	    result.offset = result.collapse == "right" ? result.end : result.start;
	    return result
	  }

	  function isInGutter(node) {
	    for (var scan = node; scan; scan = scan.parentNode)
	      { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } }
	    return false
	  }

	  function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }

	  function domTextBetween(cm, from, to, fromLine, toLine) {
	    var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false;
	    function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
	    function close() {
	      if (closing) {
	        text += lineSep;
	        if (extraLinebreak) { text += lineSep; }
	        closing = extraLinebreak = false;
	      }
	    }
	    function addText(str) {
	      if (str) {
	        close();
	        text += str;
	      }
	    }
	    function walk(node) {
	      if (node.nodeType == 1) {
	        var cmText = node.getAttribute("cm-text");
	        if (cmText) {
	          addText(cmText);
	          return
	        }
	        var markerID = node.getAttribute("cm-marker"), range$$1;
	        if (markerID) {
	          var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
	          if (found.length && (range$$1 = found[0].find(0)))
	            { addText(getBetween(cm.doc, range$$1.from, range$$1.to).join(lineSep)); }
	          return
	        }
	        if (node.getAttribute("contenteditable") == "false") { return }
	        var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName);
	        if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return }

	        if (isBlock) { close(); }
	        for (var i = 0; i < node.childNodes.length; i++)
	          { walk(node.childNodes[i]); }

	        if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; }
	        if (isBlock) { closing = true; }
	      } else if (node.nodeType == 3) {
	        addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " "));
	      }
	    }
	    for (;;) {
	      walk(from);
	      if (from == to) { break }
	      from = from.nextSibling;
	      extraLinebreak = false;
	    }
	    return text
	  }

	  function domToPos(cm, node, offset) {
	    var lineNode;
	    if (node == cm.display.lineDiv) {
	      lineNode = cm.display.lineDiv.childNodes[offset];
	      if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }
	      node = null; offset = 0;
	    } else {
	      for (lineNode = node;; lineNode = lineNode.parentNode) {
	        if (!lineNode || lineNode == cm.display.lineDiv) { return null }
	        if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }
	      }
	    }
	    for (var i = 0; i < cm.display.view.length; i++) {
	      var lineView = cm.display.view[i];
	      if (lineView.node == lineNode)
	        { return locateNodeInLineView(lineView, node, offset) }
	    }
	  }

	  function locateNodeInLineView(lineView, node, offset) {
	    var wrapper = lineView.text.firstChild, bad = false;
	    if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }
	    if (node == wrapper) {
	      bad = true;
	      node = wrapper.childNodes[offset];
	      offset = 0;
	      if (!node) {
	        var line = lineView.rest ? lst(lineView.rest) : lineView.line;
	        return badPos(Pos(lineNo(line), line.text.length), bad)
	      }
	    }

	    var textNode = node.nodeType == 3 ? node : null, topNode = node;
	    if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
	      textNode = node.firstChild;
	      if (offset) { offset = textNode.nodeValue.length; }
	    }
	    while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; }
	    var measure = lineView.measure, maps = measure.maps;

	    function find(textNode, topNode, offset) {
	      for (var i = -1; i < (maps ? maps.length : 0); i++) {
	        var map$$1 = i < 0 ? measure.map : maps[i];
	        for (var j = 0; j < map$$1.length; j += 3) {
	          var curNode = map$$1[j + 2];
	          if (curNode == textNode || curNode == topNode) {
	            var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
	            var ch = map$$1[j] + offset;
	            if (offset < 0 || curNode != textNode) { ch = map$$1[j + (offset ? 1 : 0)]; }
	            return Pos(line, ch)
	          }
	        }
	      }
	    }
	    var found = find(textNode, topNode, offset);
	    if (found) { return badPos(found, bad) }

	    // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
	    for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
	      found = find(after, after.firstChild, 0);
	      if (found)
	        { return badPos(Pos(found.line, found.ch - dist), bad) }
	      else
	        { dist += after.textContent.length; }
	    }
	    for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {
	      found = find(before, before.firstChild, -1);
	      if (found)
	        { return badPos(Pos(found.line, found.ch + dist$1), bad) }
	      else
	        { dist$1 += before.textContent.length; }
	    }
	  }

	  // TEXTAREA INPUT STYLE

	  var TextareaInput = function(cm) {
	    this.cm = cm;
	    // See input.poll and input.reset
	    this.prevInput = "";

	    // Flag that indicates whether we expect input to appear real soon
	    // now (after some event like 'keypress' or 'input') and are
	    // polling intensively.
	    this.pollingFast = false;
	    // Self-resetting timeout for the poller
	    this.polling = new Delayed();
	    // Used to work around IE issue with selection being forgotten when focus moves away from textarea
	    this.hasSelection = false;
	    this.composing = null;
	  };

	  TextareaInput.prototype.init = function (display) {
	      var this$1 = this;

	    var input = this, cm = this.cm;
	    this.createField(display);
	    var te = this.textarea;

	    display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild);

	    // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
	    if (ios) { te.style.width = "0px"; }

	    on(te, "input", function () {
	      if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; }
	      input.poll();
	    });

	    on(te, "paste", function (e) {
	      if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }

	      cm.state.pasteIncoming = true;
	      input.fastPoll();
	    });

	    function prepareCopyCut(e) {
	      if (signalDOMEvent(cm, e)) { return }
	      if (cm.somethingSelected()) {
	        setLastCopied({lineWise: false, text: cm.getSelections()});
	      } else if (!cm.options.lineWiseCopyCut) {
	        return
	      } else {
	        var ranges = copyableRanges(cm);
	        setLastCopied({lineWise: true, text: ranges.text});
	        if (e.type == "cut") {
	          cm.setSelections(ranges.ranges, null, sel_dontScroll);
	        } else {
	          input.prevInput = "";
	          te.value = ranges.text.join("\n");
	          selectInput(te);
	        }
	      }
	      if (e.type == "cut") { cm.state.cutIncoming = true; }
	    }
	    on(te, "cut", prepareCopyCut);
	    on(te, "copy", prepareCopyCut);

	    on(display.scroller, "paste", function (e) {
	      if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }
	      cm.state.pasteIncoming = true;
	      input.focus();
	    });

	    // Prevent normal selection in the editor (we handle our own)
	    on(display.lineSpace, "selectstart", function (e) {
	      if (!eventInWidget(display, e)) { e_preventDefault(e); }
	    });

	    on(te, "compositionstart", function () {
	      var start = cm.getCursor("from");
	      if (input.composing) { input.composing.range.clear(); }
	      input.composing = {
	        start: start,
	        range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
	      };
	    });
	    on(te, "compositionend", function () {
	      if (input.composing) {
	        input.poll();
	        input.composing.range.clear();
	        input.composing = null;
	      }
	    });
	  };

	  TextareaInput.prototype.createField = function (_display) {
	    // Wraps and hides input textarea
	    this.wrapper = hiddenTextarea();
	    // The semihidden textarea that is focused when the editor is
	    // focused, and receives input.
	    this.textarea = this.wrapper.firstChild;
	  };

	  TextareaInput.prototype.prepareSelection = function () {
	    // Redraw the selection and/or cursor
	    var cm = this.cm, display = cm.display, doc = cm.doc;
	    var result = prepareSelection(cm);

	    // Move the hidden textarea near the cursor to prevent scrolling artifacts
	    if (cm.options.moveInputWithCursor) {
	      var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
	      var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
	      result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
	                                          headPos.top + lineOff.top - wrapOff.top));
	      result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
	                                           headPos.left + lineOff.left - wrapOff.left));
	    }

	    return result
	  };

	  TextareaInput.prototype.showSelection = function (drawn) {
	    var cm = this.cm, display = cm.display;
	    removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
	    removeChildrenAndAdd(display.selectionDiv, drawn.selection);
	    if (drawn.teTop != null) {
	      this.wrapper.style.top = drawn.teTop + "px";
	      this.wrapper.style.left = drawn.teLeft + "px";
	    }
	  };

	  // Reset the input to correspond to the selection (or to be empty,
	  // when not typing and nothing is selected)
	  TextareaInput.prototype.reset = function (typing) {
	    if (this.contextMenuPending || this.composing) { return }
	    var cm = this.cm;
	    if (cm.somethingSelected()) {
	      this.prevInput = "";
	      var content = cm.getSelection();
	      this.textarea.value = content;
	      if (cm.state.focused) { selectInput(this.textarea); }
	      if (ie && ie_version >= 9) { this.hasSelection = content; }
	    } else if (!typing) {
	      this.prevInput = this.textarea.value = "";
	      if (ie && ie_version >= 9) { this.hasSelection = null; }
	    }
	  };

	  TextareaInput.prototype.getField = function () { return this.textarea };

	  TextareaInput.prototype.supportsTouch = function () { return false };

	  TextareaInput.prototype.focus = function () {
	    if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
	      try { this.textarea.focus(); }
	      catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
	    }
	  };

	  TextareaInput.prototype.blur = function () { this.textarea.blur(); };

	  TextareaInput.prototype.resetPosition = function () {
	    this.wrapper.style.top = this.wrapper.style.left = 0;
	  };

	  TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); };

	  // Poll for input changes, using the normal rate of polling. This
	  // runs as long as the editor is focused.
	  TextareaInput.prototype.slowPoll = function () {
	      var this$1 = this;

	    if (this.pollingFast) { return }
	    this.polling.set(this.cm.options.pollInterval, function () {
	      this$1.poll();
	      if (this$1.cm.state.focused) { this$1.slowPoll(); }
	    });
	  };

	  // When an event has just come in that is likely to add or change
	  // something in the input textarea, we poll faster, to ensure that
	  // the change appears on the screen quickly.
	  TextareaInput.prototype.fastPoll = function () {
	    var missed = false, input = this;
	    input.pollingFast = true;
	    function p() {
	      var changed = input.poll();
	      if (!changed && !missed) {missed = true; input.polling.set(60, p);}
	      else {input.pollingFast = false; input.slowPoll();}
	    }
	    input.polling.set(20, p);
	  };

	  // Read input from the textarea, and update the document to match.
	  // When something is selected, it is present in the textarea, and
	  // selected (unless it is huge, in which case a placeholder is
	  // used). When nothing is selected, the cursor sits after previously
	  // seen text (can be empty), which is stored in prevInput (we must
	  // not reset the textarea when typing, because that breaks IME).
	  TextareaInput.prototype.poll = function () {
	      var this$1 = this;

	    var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
	    // Since this is called a *lot*, try to bail out as cheaply as
	    // possible when it is clear that nothing happened. hasSelection
	    // will be the case when there is a lot of text in the textarea,
	    // in which case reading its value would be expensive.
	    if (this.contextMenuPending || !cm.state.focused ||
	        (hasSelection(input) && !prevInput && !this.composing) ||
	        cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
	      { return false }

	    var text = input.value;
	    // If nothing changed, bail.
	    if (text == prevInput && !cm.somethingSelected()) { return false }
	    // Work around nonsensical selection resetting in IE9/10, and
	    // inexplicable appearance of private area unicode characters on
	    // some key combos in Mac (#2689).
	    if (ie && ie_version >= 9 && this.hasSelection === text ||
	        mac && /[\uf700-\uf7ff]/.test(text)) {
	      cm.display.input.reset();
	      return false
	    }

	    if (cm.doc.sel == cm.display.selForContextMenu) {
	      var first = text.charCodeAt(0);
	      if (first == 0x200b && !prevInput) { prevInput = "\u200b"; }
	      if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") }
	    }
	    // Find the part of the input that is actually new
	    var same = 0, l = Math.min(prevInput.length, text.length);
	    while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; }

	    runInOp(cm, function () {
	      applyTextInput(cm, text.slice(same), prevInput.length - same,
	                     null, this$1.composing ? "*compose" : null);

	      // Don't leave long text in the textarea, since it makes further polling slow
	      if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; }
	      else { this$1.prevInput = text; }

	      if (this$1.composing) {
	        this$1.composing.range.clear();
	        this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"),
	                                           {className: "CodeMirror-composing"});
	      }
	    });
	    return true
	  };

	  TextareaInput.prototype.ensurePolled = function () {
	    if (this.pollingFast && this.poll()) { this.pollingFast = false; }
	  };

	  TextareaInput.prototype.onKeyPress = function () {
	    if (ie && ie_version >= 9) { this.hasSelection = null; }
	    this.fastPoll();
	  };

	  TextareaInput.prototype.onContextMenu = function (e) {
	    var input = this, cm = input.cm, display = cm.display, te = input.textarea;
	    if (input.contextMenuPending) { input.contextMenuPending(); }
	    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
	    if (!pos || presto) { return } // Opera is difficult.

	    // Reset the current text selection only if the click is done outside of the selection
	    // and 'resetSelectionOnContextMenu' option is true.
	    var reset = cm.options.resetSelectionOnContextMenu;
	    if (reset && cm.doc.sel.contains(pos) == -1)
	      { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); }

	    var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText;
	    var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect();
	    input.wrapper.style.cssText = "position: static";
	    te.style.cssText = "position: absolute; width: 30px; height: 30px;\n      top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n      z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n      outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
	    var oldScrollY;
	    if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712)
	    display.input.focus();
	    if (webkit) { window.scrollTo(null, oldScrollY); }
	    display.input.reset();
	    // Adds "Select all" to context menu in FF
	    if (!cm.somethingSelected()) { te.value = input.prevInput = " "; }
	    input.contextMenuPending = rehide;
	    display.selForContextMenu = cm.doc.sel;
	    clearTimeout(display.detectingSelectAll);

	    // Select-all will be greyed out if there's nothing to select, so
	    // this adds a zero-width space so that we can later check whether
	    // it got selected.
	    function prepareSelectAllHack() {
	      if (te.selectionStart != null) {
	        var selected = cm.somethingSelected();
	        var extval = "\u200b" + (selected ? te.value : "");
	        te.value = "\u21da"; // Used to catch context-menu undo
	        te.value = extval;
	        input.prevInput = selected ? "" : "\u200b";
	        te.selectionStart = 1; te.selectionEnd = extval.length;
	        // Re-set this, in case some other handler touched the
	        // selection in the meantime.
	        display.selForContextMenu = cm.doc.sel;
	      }
	    }
	    function rehide() {
	      if (input.contextMenuPending != rehide) { return }
	      input.contextMenuPending = false;
	      input.wrapper.style.cssText = oldWrapperCSS;
	      te.style.cssText = oldCSS;
	      if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); }

	      // Try to detect the user choosing select-all
	      if (te.selectionStart != null) {
	        if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); }
	        var i = 0, poll = function () {
	          if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
	              te.selectionEnd > 0 && input.prevInput == "\u200b") {
	            operation(cm, selectAll)(cm);
	          } else if (i++ < 10) {
	            display.detectingSelectAll = setTimeout(poll, 500);
	          } else {
	            display.selForContextMenu = null;
	            display.input.reset();
	          }
	        };
	        display.detectingSelectAll = setTimeout(poll, 200);
	      }
	    }

	    if (ie && ie_version >= 9) { prepareSelectAllHack(); }
	    if (captureRightClick) {
	      e_stop(e);
	      var mouseup = function () {
	        off(window, "mouseup", mouseup);
	        setTimeout(rehide, 20);
	      };
	      on(window, "mouseup", mouseup);
	    } else {
	      setTimeout(rehide, 50);
	    }
	  };

	  TextareaInput.prototype.readOnlyChanged = function (val) {
	    if (!val) { this.reset(); }
	    this.textarea.disabled = val == "nocursor";
	  };

	  TextareaInput.prototype.setUneditable = function () {};

	  TextareaInput.prototype.needsContentAttribute = false;

	  function fromTextArea(textarea, options) {
	    options = options ? copyObj(options) : {};
	    options.value = textarea.value;
	    if (!options.tabindex && textarea.tabIndex)
	      { options.tabindex = textarea.tabIndex; }
	    if (!options.placeholder && textarea.placeholder)
	      { options.placeholder = textarea.placeholder; }
	    // Set autofocus to true if this textarea is focused, or if it has
	    // autofocus and no other element is focused.
	    if (options.autofocus == null) {
	      var hasFocus = activeElt();
	      options.autofocus = hasFocus == textarea ||
	        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
	    }

	    function save() {textarea.value = cm.getValue();}

	    var realSubmit;
	    if (textarea.form) {
	      on(textarea.form, "submit", save);
	      // Deplorable hack to make the submit method do the right thing.
	      if (!options.leaveSubmitMethodAlone) {
	        var form = textarea.form;
	        realSubmit = form.submit;
	        try {
	          var wrappedSubmit = form.submit = function () {
	            save();
	            form.submit = realSubmit;
	            form.submit();
	            form.submit = wrappedSubmit;
	          };
	        } catch(e) {}
	      }
	    }

	    options.finishInit = function (cm) {
	      cm.save = save;
	      cm.getTextArea = function () { return textarea; };
	      cm.toTextArea = function () {
	        cm.toTextArea = isNaN; // Prevent this from being ran twice
	        save();
	        textarea.parentNode.removeChild(cm.getWrapperElement());
	        textarea.style.display = "";
	        if (textarea.form) {
	          off(textarea.form, "submit", save);
	          if (typeof textarea.form.submit == "function")
	            { textarea.form.submit = realSubmit; }
	        }
	      };
	    };

	    textarea.style.display = "none";
	    var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },
	      options);
	    return cm
	  }

	  function addLegacyProps(CodeMirror) {
	    CodeMirror.off = off;
	    CodeMirror.on = on;
	    CodeMirror.wheelEventPixels = wheelEventPixels;
	    CodeMirror.Doc = Doc;
	    CodeMirror.splitLines = splitLinesAuto;
	    CodeMirror.countColumn = countColumn;
	    CodeMirror.findColumn = findColumn;
	    CodeMirror.isWordChar = isWordCharBasic;
	    CodeMirror.Pass = Pass;
	    CodeMirror.signal = signal;
	    CodeMirror.Line = Line;
	    CodeMirror.changeEnd = changeEnd;
	    CodeMirror.scrollbarModel = scrollbarModel;
	    CodeMirror.Pos = Pos;
	    CodeMirror.cmpPos = cmp;
	    CodeMirror.modes = modes;
	    CodeMirror.mimeModes = mimeModes;
	    CodeMirror.resolveMode = resolveMode;
	    CodeMirror.getMode = getMode;
	    CodeMirror.modeExtensions = modeExtensions;
	    CodeMirror.extendMode = extendMode;
	    CodeMirror.copyState = copyState;
	    CodeMirror.startState = startState;
	    CodeMirror.innerMode = innerMode;
	    CodeMirror.commands = commands;
	    CodeMirror.keyMap = keyMap;
	    CodeMirror.keyName = keyName;
	    CodeMirror.isModifierKey = isModifierKey;
	    CodeMirror.lookupKey = lookupKey;
	    CodeMirror.normalizeKeyMap = normalizeKeyMap;
	    CodeMirror.StringStream = StringStream;
	    CodeMirror.SharedTextMarker = SharedTextMarker;
	    CodeMirror.TextMarker = TextMarker;
	    CodeMirror.LineWidget = LineWidget;
	    CodeMirror.e_preventDefault = e_preventDefault;
	    CodeMirror.e_stopPropagation = e_stopPropagation;
	    CodeMirror.e_stop = e_stop;
	    CodeMirror.addClass = addClass;
	    CodeMirror.contains = contains;
	    CodeMirror.rmClass = rmClass;
	    CodeMirror.keyNames = keyNames;
	  }

	  // EDITOR CONSTRUCTOR

	  defineOptions(CodeMirror);

	  addEditorMethods(CodeMirror);

	  // Set up methods on CodeMirror's prototype to redirect to the editor's document.
	  var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
	  for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
	    { CodeMirror.prototype[prop] = (function(method) {
	      return function() {return method.apply(this.doc, arguments)}
	    })(Doc.prototype[prop]); } }

	  eventMixin(Doc);
	  CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};

	  // Extra arguments are stored as the mode's dependencies, which is
	  // used by (legacy) mechanisms like loadmode.js to automatically
	  // load a mode. (Preferred mechanism is the require/define calls.)
	  CodeMirror.defineMode = function(name/*, mode, …*/) {
	    if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; }
	    defineMode.apply(this, arguments);
	  };

	  CodeMirror.defineMIME = defineMIME;

	  // Minimal default mode.
	  CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
	  CodeMirror.defineMIME("text/plain", "null");

	  // EXTENSIONS

	  CodeMirror.defineExtension = function (name, func) {
	    CodeMirror.prototype[name] = func;
	  };
	  CodeMirror.defineDocExtension = function (name, func) {
	    Doc.prototype[name] = func;
	  };

	  CodeMirror.fromTextArea = fromTextArea;

	  addLegacyProps(CodeMirror);

	  CodeMirror.version = "5.42.2";

	  return CodeMirror;

	})));


/***/ },
/* 352 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";

	  var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/,
	      emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,
	      unorderedListRE = /[*+-]\s/;

	  CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
	    if (cm.getOption("disableInput")) return CodeMirror.Pass;
	    var ranges = cm.listSelections(), replacements = [];
	    for (var i = 0; i < ranges.length; i++) {
	      var pos = ranges[i].head;
	      var eolState = cm.getStateAfter(pos.line);
	      var inList = eolState.list !== false;
	      var inQuote = eolState.quote !== 0;

	      var line = cm.getLine(pos.line), match = listRE.exec(line);
	      var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch));
	      if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) {
	        cm.execCommand("newlineAndIndent");
	        return;
	      }
	      if (emptyListRE.test(line)) {
	        if (!/>\s*$/.test(line)) cm.replaceRange("", {
	          line: pos.line, ch: 0
	        }, {
	          line: pos.line, ch: pos.ch + 1
	        });
	        replacements[i] = "\n";
	      } else {
	        var indent = match[1], after = match[5];
	        var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
	        var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " ");
	        replacements[i] = "\n" + indent + bullet + after;

	        if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
	      }
	    }

	    cm.replaceSelections(replacements);
	  };

	  // Auto-updating Markdown list numbers when a new item is added to the
	  // middle of a list
	  function incrementRemainingMarkdownListNumbers(cm, pos) {
	    var startLine = pos.line, lookAhead = 0, skipCount = 0;
	    var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1];

	    do {
	      lookAhead += 1;
	      var nextLineNumber = startLine + lookAhead;
	      var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine);

	      if (nextItem) {
	        var nextIndent = nextItem[1];
	        var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount);
	        var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber;

	        if (startIndent === nextIndent && !isNaN(nextNumber)) {
	          if (newNumber === nextNumber) itemNumber = nextNumber + 1;
	          if (newNumber > nextNumber) itemNumber = newNumber + 1;
	          cm.replaceRange(
	            nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
	          {
	            line: nextLineNumber, ch: 0
	          }, {
	            line: nextLineNumber, ch: nextLine.length
	          });
	        } else {
	          if (startIndent.length > nextIndent.length) return;
	          // This doesn't run if the next line immediatley indents, as it is
	          // not clear of the users intention (new indented item or same level)
	          if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return;
	          skipCount += 1;
	        }
	      }
	    } while (nextItem);
	  }
	});


/***/ },
/* 353 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE

	var CodeMirror = __webpack_require__(351);

	CodeMirror.commands.tabAndIndentMarkdownList = function (cm) {
		var ranges = cm.listSelections();
		var pos = ranges[0].head;
		var eolState = cm.getStateAfter(pos.line);
		var inList = eolState.list !== false;

		if (inList) {
			cm.execCommand("indentMore");
			return;
		}

		if (cm.options.indentWithTabs) {
			cm.execCommand("insertTab");
		}
		else {
			var spaces = Array(cm.options.tabSize + 1).join(" ");
			cm.replaceSelection(spaces);
		}
	};

	CodeMirror.commands.shiftTabAndUnindentMarkdownList = function (cm) {
		var ranges = cm.listSelections();
		var pos = ranges[0].head;
		var eolState = cm.getStateAfter(pos.line);
		var inList = eolState.list !== false;

		if (inList) {
			cm.execCommand("indentLess");
			return;
		}

		if (cm.options.indentWithTabs) {
			cm.execCommand("insertTab");
		}
		else {
			var spaces = Array(cm.options.tabSize + 1).join(" ");
			cm.replaceSelection(spaces);
		}
	};


/***/ },
/* 354 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";

	  CodeMirror.defineOption("fullScreen", false, function(cm, val, old) {
	    if (old == CodeMirror.Init) old = false;
	    if (!old == !val) return;
	    if (val) setFullscreen(cm);
	    else setNormal(cm);
	  });

	  function setFullscreen(cm) {
	    var wrap = cm.getWrapperElement();
	    cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,
	                                  width: wrap.style.width, height: wrap.style.height};
	    wrap.style.width = "";
	    wrap.style.height = "auto";
	    wrap.className += " CodeMirror-fullscreen";
	    document.documentElement.style.overflow = "hidden";
	    cm.refresh();
	  }

	  function setNormal(cm) {
	    var wrap = cm.getWrapperElement();
	    wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, "");
	    document.documentElement.style.overflow = "";
	    var info = cm.state.fullScreenRestore;
	    wrap.style.width = info.width; wrap.style.height = info.height;
	    window.scrollTo(info.scrollLeft, info.scrollTop);
	    cm.refresh();
	  }
	});


/***/ },
/* 355 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351), __webpack_require__(356), __webpack_require__(357));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";

	CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {

	  var htmlMode = CodeMirror.getMode(cmCfg, "text/html");
	  var htmlModeMissing = htmlMode.name == "null"

	  function getMode(name) {
	    if (CodeMirror.findModeByName) {
	      var found = CodeMirror.findModeByName(name);
	      if (found) name = found.mime || found.mimes[0];
	    }
	    var mode = CodeMirror.getMode(cmCfg, name);
	    return mode.name == "null" ? null : mode;
	  }

	  // Should characters that affect highlighting be highlighted separate?
	  // Does not include characters that will be output (such as `1.` and `-` for lists)
	  if (modeCfg.highlightFormatting === undefined)
	    modeCfg.highlightFormatting = false;

	  // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
	  // Excess `>` will emit `error` token.
	  if (modeCfg.maxBlockquoteDepth === undefined)
	    modeCfg.maxBlockquoteDepth = 0;

	  // Turn on task lists? ("- [ ] " and "- [x] ")
	  if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;

	  // Turn on strikethrough syntax
	  if (modeCfg.strikethrough === undefined)
	    modeCfg.strikethrough = false;

	  if (modeCfg.emoji === undefined)
	    modeCfg.emoji = false;

	  if (modeCfg.fencedCodeBlockHighlighting === undefined)
	    modeCfg.fencedCodeBlockHighlighting = true;

	  if (modeCfg.xml === undefined)
	    modeCfg.xml = true;

	  // Allow token types to be overridden by user-provided token types.
	  if (modeCfg.tokenTypeOverrides === undefined)
	    modeCfg.tokenTypeOverrides = {};

	  var tokenTypes = {
	    header: "header",
	    code: "comment",
	    quote: "quote",
	    list1: "variable-2",
	    list2: "variable-3",
	    list3: "keyword",
	    hr: "hr",
	    image: "image",
	    imageAltText: "image-alt-text",
	    imageMarker: "image-marker",
	    formatting: "formatting",
	    linkInline: "link",
	    linkEmail: "link",
	    linkText: "link",
	    linkHref: "string",
	    em: "em",
	    strong: "strong",
	    strikethrough: "strikethrough",
	    emoji: "builtin"
	  };

	  for (var tokenType in tokenTypes) {
	    if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
	      tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
	    }
	  }

	  var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
	  ,   listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/
	  ,   taskListRE = /^\[(x| )\](?=\s)/i // Must follow listRE
	  ,   atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
	  ,   setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
	  ,   textRE = /^[^#!\[\]*_\\<>` "'(~:]+/
	  ,   fencedCodeRE = /^(~~~+|```+)[ \t]*([\w+#-]*)[^\n`]*$/
	  ,   linkDefRE = /^\s*\[[^\]]+?\]:.*$/ // naive link-definition
	  ,   punctuation = /[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/
	  ,   expandedTab = "    " // CommonMark specifies tab as 4 spaces

	  function switchInline(stream, state, f) {
	    state.f = state.inline = f;
	    return f(stream, state);
	  }

	  function switchBlock(stream, state, f) {
	    state.f = state.block = f;
	    return f(stream, state);
	  }

	  function lineIsEmpty(line) {
	    return !line || !/\S/.test(line.string)
	  }

	  // Blocks

	  function blankLine(state) {
	    // Reset linkTitle state
	    state.linkTitle = false;
	    state.linkHref = false;
	    state.linkText = false;
	    // Reset EM state
	    state.em = false;
	    // Reset STRONG state
	    state.strong = false;
	    // Reset strikethrough state
	    state.strikethrough = false;
	    // Reset state.quote
	    state.quote = 0;
	    // Reset state.indentedCode
	    state.indentedCode = false;
	    if (state.f == htmlBlock) {
	      var exit = htmlModeMissing
	      if (!exit) {
	        var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
	        exit = inner.mode.name == "xml" && inner.state.tagStart === null &&
	          (!inner.state.context && inner.state.tokenize.isInText)
	      }
	      if (exit) {
	        state.f = inlineNormal;
	        state.block = blockNormal;
	        state.htmlState = null;
	      }
	    }
	    // Reset state.trailingSpace
	    state.trailingSpace = 0;
	    state.trailingSpaceNewLine = false;
	    // Mark this line as blank
	    state.prevLine = state.thisLine
	    state.thisLine = {stream: null}
	    return null;
	  }

	  function blockNormal(stream, state) {
	    var firstTokenOnLine = stream.column() === state.indentation;
	    var prevLineLineIsEmpty = lineIsEmpty(state.prevLine.stream);
	    var prevLineIsIndentedCode = state.indentedCode;
	    var prevLineIsHr = state.prevLine.hr;
	    var prevLineIsList = state.list !== false;
	    var maxNonCodeIndentation = (state.listStack[state.listStack.length - 1] || 0) + 3;

	    state.indentedCode = false;

	    var lineIndentation = state.indentation;
	    // compute once per line (on first token)
	    if (state.indentationDiff === null) {
	      state.indentationDiff = state.indentation;
	      if (prevLineIsList) {
	        // Reset inline styles which shouldn't propagate aross list items
	        state.em = false;
	        state.strong = false;
	        state.code = false;
	        state.strikethrough = false;

	        state.list = null;
	        // While this list item's marker's indentation is less than the deepest
	        //  list item's content's indentation,pop the deepest list item
	        //  indentation off the stack, and update block indentation state
	        while (lineIndentation < state.listStack[state.listStack.length - 1]) {
	          state.listStack.pop();
	          if (state.listStack.length) {
	            state.indentation = state.listStack[state.listStack.length - 1];
	          // less than the first list's indent -> the line is no longer a list
	          } else {
	            state.list = false;
	          }
	        }
	        if (state.list !== false) {
	          state.indentationDiff = lineIndentation - state.listStack[state.listStack.length - 1]
	        }
	      }
	    }

	    // not comprehensive (currently only for setext detection purposes)
	    var allowsInlineContinuation = (
	        !prevLineLineIsEmpty && !prevLineIsHr && !state.prevLine.header &&
	        (!prevLineIsList || !prevLineIsIndentedCode) &&
	        !state.prevLine.fencedCodeEnd
	    );

	    var isHr = (state.list === false || prevLineIsHr || prevLineLineIsEmpty) &&
	      state.indentation <= maxNonCodeIndentation && stream.match(hrRE);

	    var match = null;
	    if (state.indentationDiff >= 4 && (prevLineIsIndentedCode || state.prevLine.fencedCodeEnd ||
	         state.prevLine.header || prevLineLineIsEmpty)) {
	      stream.skipToEnd();
	      state.indentedCode = true;
	      return tokenTypes.code;
	    } else if (stream.eatSpace()) {
	      return null;
	    } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(atxHeaderRE)) && match[1].length <= 6) {
	      state.quote = 0;
	      state.header = match[1].length;
	      state.thisLine.header = true;
	      if (modeCfg.highlightFormatting) state.formatting = "header";
	      state.f = state.inline;
	      return getType(state);
	    } else if (state.indentation <= maxNonCodeIndentation && stream.eat('>')) {
	      state.quote = firstTokenOnLine ? 1 : state.quote + 1;
	      if (modeCfg.highlightFormatting) state.formatting = "quote";
	      stream.eatSpace();
	      return getType(state);
	    } else if (!isHr && !state.setext && firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(listRE))) {
	      var listType = match[1] ? "ol" : "ul";

	      state.indentation = lineIndentation + stream.current().length;
	      state.list = true;
	      state.quote = 0;

	      // Add this list item's content's indentation to the stack
	      state.listStack.push(state.indentation);

	      if (modeCfg.taskLists && stream.match(taskListRE, false)) {
	        state.taskList = true;
	      }
	      state.f = state.inline;
	      if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
	      return getType(state);
	    } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(fencedCodeRE, true))) {
	      state.quote = 0;
	      state.fencedEndRE = new RegExp(match[1] + "+ *$");
	      // try switching mode
	      state.localMode = modeCfg.fencedCodeBlockHighlighting && getMode(match[2]);
	      if (state.localMode) state.localState = CodeMirror.startState(state.localMode);
	      state.f = state.block = local;
	      if (modeCfg.highlightFormatting) state.formatting = "code-block";
	      state.code = -1
	      return getType(state);
	    // SETEXT has lowest block-scope precedence after HR, so check it after
	    //  the others (code, blockquote, list...)
	    } else if (
	      // if setext set, indicates line after ---/===
	      state.setext || (
	        // line before ---/===
	        (!allowsInlineContinuation || !prevLineIsList) && !state.quote && state.list === false &&
	        !state.code && !isHr && !linkDefRE.test(stream.string) &&
	        (match = stream.lookAhead(1)) && (match = match.match(setextHeaderRE))
	      )
	    ) {
	      if ( !state.setext ) {
	        state.header = match[0].charAt(0) == '=' ? 1 : 2;
	        state.setext = state.header;
	      } else {
	        state.header = state.setext;
	        // has no effect on type so we can reset it now
	        state.setext = 0;
	        stream.skipToEnd();
	        if (modeCfg.highlightFormatting) state.formatting = "header";
	      }
	      state.thisLine.header = true;
	      state.f = state.inline;
	      return getType(state);
	    } else if (isHr) {
	      stream.skipToEnd();
	      state.hr = true;
	      state.thisLine.hr = true;
	      return tokenTypes.hr;
	    } else if (stream.peek() === '[') {
	      return switchInline(stream, state, footnoteLink);
	    }

	    return switchInline(stream, state, state.inline);
	  }

	  function htmlBlock(stream, state) {
	    var style = htmlMode.token(stream, state.htmlState);
	    if (!htmlModeMissing) {
	      var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
	      if ((inner.mode.name == "xml" && inner.state.tagStart === null &&
	           (!inner.state.context && inner.state.tokenize.isInText)) ||
	          (state.md_inside && stream.current().indexOf(">") > -1)) {
	        state.f = inlineNormal;
	        state.block = blockNormal;
	        state.htmlState = null;
	      }
	    }
	    return style;
	  }

	  function local(stream, state) {
	    var currListInd = state.listStack[state.listStack.length - 1] || 0;
	    var hasExitedList = state.indentation < currListInd;
	    var maxFencedEndInd = currListInd + 3;
	    if (state.fencedEndRE && state.indentation <= maxFencedEndInd && (hasExitedList || stream.match(state.fencedEndRE))) {
	      if (modeCfg.highlightFormatting) state.formatting = "code-block";
	      var returnType;
	      if (!hasExitedList) returnType = getType(state)
	      state.localMode = state.localState = null;
	      state.block = blockNormal;
	      state.f = inlineNormal;
	      state.fencedEndRE = null;
	      state.code = 0
	      state.thisLine.fencedCodeEnd = true;
	      if (hasExitedList) return switchBlock(stream, state, state.block);
	      return returnType;
	    } else if (state.localMode) {
	      return state.localMode.token(stream, state.localState);
	    } else {
	      stream.skipToEnd();
	      return tokenTypes.code;
	    }
	  }

	  // Inline
	  function getType(state) {
	    var styles = [];

	    if (state.formatting) {
	      styles.push(tokenTypes.formatting);

	      if (typeof state.formatting === "string") state.formatting = [state.formatting];

	      for (var i = 0; i < state.formatting.length; i++) {
	        styles.push(tokenTypes.formatting + "-" + state.formatting[i]);

	        if (state.formatting[i] === "header") {
	          styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
	        }

	        // Add `formatting-quote` and `formatting-quote-#` for blockquotes
	        // Add `error` instead if the maximum blockquote nesting depth is passed
	        if (state.formatting[i] === "quote") {
	          if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
	            styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
	          } else {
	            styles.push("error");
	          }
	        }
	      }
	    }

	    if (state.taskOpen) {
	      styles.push("meta");
	      return styles.length ? styles.join(' ') : null;
	    }
	    if (state.taskClosed) {
	      styles.push("property");
	      return styles.length ? styles.join(' ') : null;
	    }

	    if (state.linkHref) {
	      styles.push(tokenTypes.linkHref, "url");
	    } else { // Only apply inline styles to non-url text
	      if (state.strong) { styles.push(tokenTypes.strong); }
	      if (state.em) { styles.push(tokenTypes.em); }
	      if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
	      if (state.emoji) { styles.push(tokenTypes.emoji); }
	      if (state.linkText) { styles.push(tokenTypes.linkText); }
	      if (state.code) { styles.push(tokenTypes.code); }
	      if (state.image) { styles.push(tokenTypes.image); }
	      if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); }
	      if (state.imageMarker) { styles.push(tokenTypes.imageMarker); }
	    }

	    if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }

	    if (state.quote) {
	      styles.push(tokenTypes.quote);

	      // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
	      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
	        styles.push(tokenTypes.quote + "-" + state.quote);
	      } else {
	        styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
	      }
	    }

	    if (state.list !== false) {
	      var listMod = (state.listStack.length - 1) % 3;
	      if (!listMod) {
	        styles.push(tokenTypes.list1);
	      } else if (listMod === 1) {
	        styles.push(tokenTypes.list2);
	      } else {
	        styles.push(tokenTypes.list3);
	      }
	    }

	    if (state.trailingSpaceNewLine) {
	      styles.push("trailing-space-new-line");
	    } else if (state.trailingSpace) {
	      styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
	    }

	    return styles.length ? styles.join(' ') : null;
	  }

	  function handleText(stream, state) {
	    if (stream.match(textRE, true)) {
	      return getType(state);
	    }
	    return undefined;
	  }

	  function inlineNormal(stream, state) {
	    var style = state.text(stream, state);
	    if (typeof style !== 'undefined')
	      return style;

	    if (state.list) { // List marker (*, +, -, 1., etc)
	      state.list = null;
	      return getType(state);
	    }

	    if (state.taskList) {
	      var taskOpen = stream.match(taskListRE, true)[1] === " ";
	      if (taskOpen) state.taskOpen = true;
	      else state.taskClosed = true;
	      if (modeCfg.highlightFormatting) state.formatting = "task";
	      state.taskList = false;
	      return getType(state);
	    }

	    state.taskOpen = false;
	    state.taskClosed = false;

	    if (state.header && stream.match(/^#+$/, true)) {
	      if (modeCfg.highlightFormatting) state.formatting = "header";
	      return getType(state);
	    }

	    var ch = stream.next();

	    // Matches link titles present on next line
	    if (state.linkTitle) {
	      state.linkTitle = false;
	      var matchCh = ch;
	      if (ch === '(') {
	        matchCh = ')';
	      }
	      matchCh = (matchCh+'').replace(/([.?*+^\[\]\\(){}|-])/g, "\\$1");
	      var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
	      if (stream.match(new RegExp(regex), true)) {
	        return tokenTypes.linkHref;
	      }
	    }

	    // If this block is changed, it may need to be updated in GFM mode
	    if (ch === '`') {
	      var previousFormatting = state.formatting;
	      if (modeCfg.highlightFormatting) state.formatting = "code";
	      stream.eatWhile('`');
	      var count = stream.current().length
	      if (state.code == 0 && (!state.quote || count == 1)) {
	        state.code = count
	        return getType(state)
	      } else if (count == state.code) { // Must be exact
	        var t = getType(state)
	        state.code = 0
	        return t
	      } else {
	        state.formatting = previousFormatting
	        return getType(state)
	      }
	    } else if (state.code) {
	      return getType(state);
	    }

	    if (ch === '\\') {
	      stream.next();
	      if (modeCfg.highlightFormatting) {
	        var type = getType(state);
	        var formattingEscape = tokenTypes.formatting + "-escape";
	        return type ? type + " " + formattingEscape : formattingEscape;
	      }
	    }

	    if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
	      state.imageMarker = true;
	      state.image = true;
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      return getType(state);
	    }

	    if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) {
	      state.imageMarker = false;
	      state.imageAltText = true
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      return getType(state);
	    }

	    if (ch === ']' && state.imageAltText) {
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      var type = getType(state);
	      state.imageAltText = false;
	      state.image = false;
	      state.inline = state.f = linkHref;
	      return type;
	    }

	    if (ch === '[' && !state.image) {
	      if (state.linkText && stream.match(/^.*?\]/)) return getType(state)
	      state.linkText = true;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      return getType(state);
	    }

	    if (ch === ']' && state.linkText) {
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      state.linkText = false;
	      state.inline = state.f = stream.match(/\(.*?\)| ?\[.*?\]/, false) ? linkHref : inlineNormal
	      return type;
	    }

	    if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
	      state.f = state.inline = linkInline;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkInline;
	    }

	    if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
	      state.f = state.inline = linkInline;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkEmail;
	    }

	    if (modeCfg.xml && ch === '<' && stream.match(/^(!--|\?|!\[CDATA\[|[a-z][a-z0-9-]*(?:\s+[a-z_:.\-]+(?:\s*=\s*[^>]+)?)*\s*(?:>|$))/i, false)) {
	      var end = stream.string.indexOf(">", stream.pos);
	      if (end != -1) {
	        var atts = stream.string.substring(stream.start, end);
	        if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
	      }
	      stream.backUp(1);
	      state.htmlState = CodeMirror.startState(htmlMode);
	      return switchBlock(stream, state, htmlBlock);
	    }

	    if (modeCfg.xml && ch === '<' && stream.match(/^\/\w*?>/)) {
	      state.md_inside = false;
	      return "tag";
	    } else if (ch === "*" || ch === "_") {
	      var len = 1, before = stream.pos == 1 ? " " : stream.string.charAt(stream.pos - 2)
	      while (len < 3 && stream.eat(ch)) len++
	      var after = stream.peek() || " "
	      // See http://spec.commonmark.org/0.27/#emphasis-and-strong-emphasis
	      var leftFlanking = !/\s/.test(after) && (!punctuation.test(after) || /\s/.test(before) || punctuation.test(before))
	      var rightFlanking = !/\s/.test(before) && (!punctuation.test(before) || /\s/.test(after) || punctuation.test(after))
	      var setEm = null, setStrong = null
	      if (len % 2) { // Em
	        if (!state.em && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
	          setEm = true
	        else if (state.em == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
	          setEm = false
	      }
	      if (len > 1) { // Strong
	        if (!state.strong && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
	          setStrong = true
	        else if (state.strong == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
	          setStrong = false
	      }
	      if (setStrong != null || setEm != null) {
	        if (modeCfg.highlightFormatting) state.formatting = setEm == null ? "strong" : setStrong == null ? "em" : "strong em"
	        if (setEm === true) state.em = ch
	        if (setStrong === true) state.strong = ch
	        var t = getType(state)
	        if (setEm === false) state.em = false
	        if (setStrong === false) state.strong = false
	        return t
	      }
	    } else if (ch === ' ') {
	      if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
	        if (stream.peek() === ' ') { // Surrounded by spaces, ignore
	          return getType(state);
	        } else { // Not surrounded by spaces, back up pointer
	          stream.backUp(1);
	        }
	      }
	    }

	    if (modeCfg.strikethrough) {
	      if (ch === '~' && stream.eatWhile(ch)) {
	        if (state.strikethrough) {// Remove strikethrough
	          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
	          var t = getType(state);
	          state.strikethrough = false;
	          return t;
	        } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
	          state.strikethrough = true;
	          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
	          return getType(state);
	        }
	      } else if (ch === ' ') {
	        if (stream.match(/^~~/, true)) { // Probably surrounded by space
	          if (stream.peek() === ' ') { // Surrounded by spaces, ignore
	            return getType(state);
	          } else { // Not surrounded by spaces, back up pointer
	            stream.backUp(2);
	          }
	        }
	      }
	    }

	    if (modeCfg.emoji && ch === ":" && stream.match(/^(?:[a-z_\d+][a-z_\d+-]*|\-[a-z_\d+][a-z_\d+-]*):/)) {
	      state.emoji = true;
	      if (modeCfg.highlightFormatting) state.formatting = "emoji";
	      var retType = getType(state);
	      state.emoji = false;
	      return retType;
	    }

	    if (ch === ' ') {
	      if (stream.match(/^ +$/, false)) {
	        state.trailingSpace++;
	      } else if (state.trailingSpace) {
	        state.trailingSpaceNewLine = true;
	      }
	    }

	    return getType(state);
	  }

	  function linkInline(stream, state) {
	    var ch = stream.next();

	    if (ch === ">") {
	      state.f = state.inline = inlineNormal;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkInline;
	    }

	    stream.match(/^[^>]+/, true);

	    return tokenTypes.linkInline;
	  }

	  function linkHref(stream, state) {
	    // Check if space, and return NULL if so (to avoid marking the space)
	    if(stream.eatSpace()){
	      return null;
	    }
	    var ch = stream.next();
	    if (ch === '(' || ch === '[') {
	      state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
	      if (modeCfg.highlightFormatting) state.formatting = "link-string";
	      state.linkHref = true;
	      return getType(state);
	    }
	    return 'error';
	  }

	  var linkRE = {
	    ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,
	    "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\]]|\\.)*\])*?(?=\])/
	  }

	  function getLinkHrefInside(endChar) {
	    return function(stream, state) {
	      var ch = stream.next();

	      if (ch === endChar) {
	        state.f = state.inline = inlineNormal;
	        if (modeCfg.highlightFormatting) state.formatting = "link-string";
	        var returnState = getType(state);
	        state.linkHref = false;
	        return returnState;
	      }

	      stream.match(linkRE[endChar])
	      state.linkHref = true;
	      return getType(state);
	    };
	  }

	  function footnoteLink(stream, state) {
	    if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
	      state.f = footnoteLinkInside;
	      stream.next(); // Consume [
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      state.linkText = true;
	      return getType(state);
	    }
	    return switchInline(stream, state, inlineNormal);
	  }

	  function footnoteLinkInside(stream, state) {
	    if (stream.match(/^\]:/, true)) {
	      state.f = state.inline = footnoteUrl;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var returnType = getType(state);
	      state.linkText = false;
	      return returnType;
	    }

	    stream.match(/^([^\]\\]|\\.)+/, true);

	    return tokenTypes.linkText;
	  }

	  function footnoteUrl(stream, state) {
	    // Check if space, and return NULL if so (to avoid marking the space)
	    if(stream.eatSpace()){
	      return null;
	    }
	    // Match URL
	    stream.match(/^[^\s]+/, true);
	    // Check for link title
	    if (stream.peek() === undefined) { // End of line, set flag to check next line
	      state.linkTitle = true;
	    } else { // More content on line, check if link title
	      stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
	    }
	    state.f = state.inline = inlineNormal;
	    return tokenTypes.linkHref + " url";
	  }

	  var mode = {
	    startState: function() {
	      return {
	        f: blockNormal,

	        prevLine: {stream: null},
	        thisLine: {stream: null},

	        block: blockNormal,
	        htmlState: null,
	        indentation: 0,

	        inline: inlineNormal,
	        text: handleText,

	        formatting: false,
	        linkText: false,
	        linkHref: false,
	        linkTitle: false,
	        code: 0,
	        em: false,
	        strong: false,
	        header: 0,
	        setext: 0,
	        hr: false,
	        taskList: false,
	        list: false,
	        listStack: [],
	        quote: 0,
	        trailingSpace: 0,
	        trailingSpaceNewLine: false,
	        strikethrough: false,
	        emoji: false,
	        fencedEndRE: null
	      };
	    },

	    copyState: function(s) {
	      return {
	        f: s.f,

	        prevLine: s.prevLine,
	        thisLine: s.thisLine,

	        block: s.block,
	        htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
	        indentation: s.indentation,

	        localMode: s.localMode,
	        localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,

	        inline: s.inline,
	        text: s.text,
	        formatting: false,
	        linkText: s.linkText,
	        linkTitle: s.linkTitle,
	        linkHref: s.linkHref,
	        code: s.code,
	        em: s.em,
	        strong: s.strong,
	        strikethrough: s.strikethrough,
	        emoji: s.emoji,
	        header: s.header,
	        setext: s.setext,
	        hr: s.hr,
	        taskList: s.taskList,
	        list: s.list,
	        listStack: s.listStack.slice(0),
	        quote: s.quote,
	        indentedCode: s.indentedCode,
	        trailingSpace: s.trailingSpace,
	        trailingSpaceNewLine: s.trailingSpaceNewLine,
	        md_inside: s.md_inside,
	        fencedEndRE: s.fencedEndRE
	      };
	    },

	    token: function(stream, state) {

	      // Reset state.formatting
	      state.formatting = false;

	      if (stream != state.thisLine.stream) {
	        state.header = 0;
	        state.hr = false;

	        if (stream.match(/^\s*$/, true)) {
	          blankLine(state);
	          return null;
	        }

	        state.prevLine = state.thisLine
	        state.thisLine = {stream: stream}

	        // Reset state.taskList
	        state.taskList = false;

	        // Reset state.trailingSpace
	        state.trailingSpace = 0;
	        state.trailingSpaceNewLine = false;

	        if (!state.localState) {
	          state.f = state.block;
	          if (state.f != htmlBlock) {
	            var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, expandedTab).length;
	            state.indentation = indentation;
	            state.indentationDiff = null;
	            if (indentation > 0) return null;
	          }
	        }
	      }
	      return state.f(stream, state);
	    },

	    innerMode: function(state) {
	      if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
	      if (state.localState) return {state: state.localState, mode: state.localMode};
	      return {state: state, mode: mode};
	    },

	    indent: function(state, textAfter, line) {
	      if (state.block == htmlBlock && htmlMode.indent) return htmlMode.indent(state.htmlState, textAfter, line)
	      if (state.localState && state.localMode.indent) return state.localMode.indent(state.localState, textAfter, line)
	      return CodeMirror.Pass
	    },

	    blankLine: blankLine,

	    getType: getType,

	    blockCommentStart: "<!--",
	    blockCommentEnd: "-->",
	    closeBrackets: "()[]{}''\"\"``",
	    fold: "markdown"
	  };
	  return mode;
	}, "xml");

	CodeMirror.defineMIME("text/markdown", "markdown");

	CodeMirror.defineMIME("text/x-markdown", "markdown");

	});


/***/ },
/* 356 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";

	var htmlConfig = {
	  autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
	                    'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
	                    'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
	                    'track': true, 'wbr': true, 'menuitem': true},
	  implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
	                     'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
	                     'th': true, 'tr': true},
	  contextGrabbers: {
	    'dd': {'dd': true, 'dt': true},
	    'dt': {'dd': true, 'dt': true},
	    'li': {'li': true},
	    'option': {'option': true, 'optgroup': true},
	    'optgroup': {'optgroup': true},
	    'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
	          'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
	          'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
	          'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
	          'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
	    'rp': {'rp': true, 'rt': true},
	    'rt': {'rp': true, 'rt': true},
	    'tbody': {'tbody': true, 'tfoot': true},
	    'td': {'td': true, 'th': true},
	    'tfoot': {'tbody': true},
	    'th': {'td': true, 'th': true},
	    'thead': {'tbody': true, 'tfoot': true},
	    'tr': {'tr': true}
	  },
	  doNotIndent: {"pre": true},
	  allowUnquoted: true,
	  allowMissing: true,
	  caseFold: true
	}

	var xmlConfig = {
	  autoSelfClosers: {},
	  implicitlyClosed: {},
	  contextGrabbers: {},
	  doNotIndent: {},
	  allowUnquoted: false,
	  allowMissing: false,
	  allowMissingTagName: false,
	  caseFold: false
	}

	CodeMirror.defineMode("xml", function(editorConf, config_) {
	  var indentUnit = editorConf.indentUnit
	  var config = {}
	  var defaults = config_.htmlMode ? htmlConfig : xmlConfig
	  for (var prop in defaults) config[prop] = defaults[prop]
	  for (var prop in config_) config[prop] = config_[prop]

	  // Return variables for tokenizers
	  var type, setStyle;

	  function inText(stream, state) {
	    function chain(parser) {
	      state.tokenize = parser;
	      return parser(stream, state);
	    }

	    var ch = stream.next();
	    if (ch == "<") {
	      if (stream.eat("!")) {
	        if (stream.eat("[")) {
	          if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
	          else return null;
	        } else if (stream.match("--")) {
	          return chain(inBlock("comment", "-->"));
	        } else if (stream.match("DOCTYPE", true, true)) {
	          stream.eatWhile(/[\w\._\-]/);
	          return chain(doctype(1));
	        } else {
	          return null;
	        }
	      } else if (stream.eat("?")) {
	        stream.eatWhile(/[\w\._\-]/);
	        state.tokenize = inBlock("meta", "?>");
	        return "meta";
	      } else {
	        type = stream.eat("/") ? "closeTag" : "openTag";
	        state.tokenize = inTag;
	        return "tag bracket";
	      }
	    } else if (ch == "&") {
	      var ok;
	      if (stream.eat("#")) {
	        if (stream.eat("x")) {
	          ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
	        } else {
	          ok = stream.eatWhile(/[\d]/) && stream.eat(";");
	        }
	      } else {
	        ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
	      }
	      return ok ? "atom" : "error";
	    } else {
	      stream.eatWhile(/[^&<]/);
	      return null;
	    }
	  }
	  inText.isInText = true;

	  function inTag(stream, state) {
	    var ch = stream.next();
	    if (ch == ">" || (ch == "/" && stream.eat(">"))) {
	      state.tokenize = inText;
	      type = ch == ">" ? "endTag" : "selfcloseTag";
	      return "tag bracket";
	    } else if (ch == "=") {
	      type = "equals";
	      return null;
	    } else if (ch == "<") {
	      state.tokenize = inText;
	      state.state = baseState;
	      state.tagName = state.tagStart = null;
	      var next = state.tokenize(stream, state);
	      return next ? next + " tag error" : "tag error";
	    } else if (/[\'\"]/.test(ch)) {
	      state.tokenize = inAttribute(ch);
	      state.stringStartCol = stream.column();
	      return state.tokenize(stream, state);
	    } else {
	      stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
	      return "word";
	    }
	  }

	  function inAttribute(quote) {
	    var closure = function(stream, state) {
	      while (!stream.eol()) {
	        if (stream.next() == quote) {
	          state.tokenize = inTag;
	          break;
	        }
	      }
	      return "string";
	    };
	    closure.isInAttribute = true;
	    return closure;
	  }

	  function inBlock(style, terminator) {
	    return function(stream, state) {
	      while (!stream.eol()) {
	        if (stream.match(terminator)) {
	          state.tokenize = inText;
	          break;
	        }
	        stream.next();
	      }
	      return style;
	    }
	  }

	  function doctype(depth) {
	    return function(stream, state) {
	      var ch;
	      while ((ch = stream.next()) != null) {
	        if (ch == "<") {
	          state.tokenize = doctype(depth + 1);
	          return state.tokenize(stream, state);
	        } else if (ch == ">") {
	          if (depth == 1) {
	            state.tokenize = inText;
	            break;
	          } else {
	            state.tokenize = doctype(depth - 1);
	            return state.tokenize(stream, state);
	          }
	        }
	      }
	      return "meta";
	    };
	  }

	  function Context(state, tagName, startOfLine) {
	    this.prev = state.context;
	    this.tagName = tagName;
	    this.indent = state.indented;
	    this.startOfLine = startOfLine;
	    if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
	      this.noIndent = true;
	  }
	  function popContext(state) {
	    if (state.context) state.context = state.context.prev;
	  }
	  function maybePopContext(state, nextTagName) {
	    var parentTagName;
	    while (true) {
	      if (!state.context) {
	        return;
	      }
	      parentTagName = state.context.tagName;
	      if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
	          !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
	        return;
	      }
	      popContext(state);
	    }
	  }

	  function baseState(type, stream, state) {
	    if (type == "openTag") {
	      state.tagStart = stream.column();
	      return tagNameState;
	    } else if (type == "closeTag") {
	      return closeTagNameState;
	    } else {
	      return baseState;
	    }
	  }
	  function tagNameState(type, stream, state) {
	    if (type == "word") {
	      state.tagName = stream.current();
	      setStyle = "tag";
	      return attrState;
	    } else if (config.allowMissingTagName && type == "endTag") {
	      setStyle = "tag bracket";
	      return attrState(type, stream, state);
	    } else {
	      setStyle = "error";
	      return tagNameState;
	    }
	  }
	  function closeTagNameState(type, stream, state) {
	    if (type == "word") {
	      var tagName = stream.current();
	      if (state.context && state.context.tagName != tagName &&
	          config.implicitlyClosed.hasOwnProperty(state.context.tagName))
	        popContext(state);
	      if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
	        setStyle = "tag";
	        return closeState;
	      } else {
	        setStyle = "tag error";
	        return closeStateErr;
	      }
	    } else if (config.allowMissingTagName && type == "endTag") {
	      setStyle = "tag bracket";
	      return closeState(type, stream, state);
	    } else {
	      setStyle = "error";
	      return closeStateErr;
	    }
	  }

	  function closeState(type, _stream, state) {
	    if (type != "endTag") {
	      setStyle = "error";
	      return closeState;
	    }
	    popContext(state);
	    return baseState;
	  }
	  function closeStateErr(type, stream, state) {
	    setStyle = "error";
	    return closeState(type, stream, state);
	  }

	  function attrState(type, _stream, state) {
	    if (type == "word") {
	      setStyle = "attribute";
	      return attrEqState;
	    } else if (type == "endTag" || type == "selfcloseTag") {
	      var tagName = state.tagName, tagStart = state.tagStart;
	      state.tagName = state.tagStart = null;
	      if (type == "selfcloseTag" ||
	          config.autoSelfClosers.hasOwnProperty(tagName)) {
	        maybePopContext(state, tagName);
	      } else {
	        maybePopContext(state, tagName);
	        state.context = new Context(state, tagName, tagStart == state.indented);
	      }
	      return baseState;
	    }
	    setStyle = "error";
	    return attrState;
	  }
	  function attrEqState(type, stream, state) {
	    if (type == "equals") return attrValueState;
	    if (!config.allowMissing) setStyle = "error";
	    return attrState(type, stream, state);
	  }
	  function attrValueState(type, stream, state) {
	    if (type == "string") return attrContinuedState;
	    if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
	    setStyle = "error";
	    return attrState(type, stream, state);
	  }
	  function attrContinuedState(type, stream, state) {
	    if (type == "string") return attrContinuedState;
	    return attrState(type, stream, state);
	  }

	  return {
	    startState: function(baseIndent) {
	      var state = {tokenize: inText,
	                   state: baseState,
	                   indented: baseIndent || 0,
	                   tagName: null, tagStart: null,
	                   context: null}
	      if (baseIndent != null) state.baseIndent = baseIndent
	      return state
	    },

	    token: function(stream, state) {
	      if (!state.tagName && stream.sol())
	        state.indented = stream.indentation();

	      if (stream.eatSpace()) return null;
	      type = null;
	      var style = state.tokenize(stream, state);
	      if ((style || type) && style != "comment") {
	        setStyle = null;
	        state.state = state.state(type || style, stream, state);
	        if (setStyle)
	          style = setStyle == "error" ? style + " error" : setStyle;
	      }
	      return style;
	    },

	    indent: function(state, textAfter, fullLine) {
	      var context = state.context;
	      // Indent multi-line strings (e.g. css).
	      if (state.tokenize.isInAttribute) {
	        if (state.tagStart == state.indented)
	          return state.stringStartCol + 1;
	        else
	          return state.indented + indentUnit;
	      }
	      if (context && context.noIndent) return CodeMirror.Pass;
	      if (state.tokenize != inTag && state.tokenize != inText)
	        return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
	      // Indent the starts of attribute names.
	      if (state.tagName) {
	        if (config.multilineTagIndentPastTag !== false)
	          return state.tagStart + state.tagName.length + 2;
	        else
	          return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
	      }
	      if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
	      var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
	      if (tagAfter && tagAfter[1]) { // Closing tag spotted
	        while (context) {
	          if (context.tagName == tagAfter[2]) {
	            context = context.prev;
	            break;
	          } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
	            context = context.prev;
	          } else {
	            break;
	          }
	        }
	      } else if (tagAfter) { // Opening tag spotted
	        while (context) {
	          var grabbers = config.contextGrabbers[context.tagName];
	          if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
	            context = context.prev;
	          else
	            break;
	        }
	      }
	      while (context && context.prev && !context.startOfLine)
	        context = context.prev;
	      if (context) return context.indent + indentUnit;
	      else return state.baseIndent || 0;
	    },

	    electricInput: /<\/[\s\w:]+>$/,
	    blockCommentStart: "<!--",
	    blockCommentEnd: "-->",

	    configuration: config.htmlMode ? "html" : "xml",
	    helperType: config.htmlMode ? "html" : "xml",

	    skipAttribute: function(state) {
	      if (state.state == attrValueState)
	        state.state = attrState
	    }
	  };
	});

	CodeMirror.defineMIME("text/xml", "xml");
	CodeMirror.defineMIME("application/xml", "xml");
	if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
	  CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});

	});


/***/ },
/* 357 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";

	  CodeMirror.modeInfo = [
	    {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
	    {name: "PGP", mimes: ["application/pgp", "application/pgp-encrypted", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["asc", "pgp", "sig"]},
	    {name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn", "asn1"]},
	    {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
	    {name: "Brainfuck", mime: "text/x-brainfuck", mode: "brainfuck", ext: ["b", "bf"]},
	    {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h", "ino"]},
	    {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
	    {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},
	    {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]},
	    {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj", "cljc", "cljx"]},
	    {name: "ClojureScript", mime: "text/x-clojurescript", mode: "clojure", ext: ["cljs"]},
	    {name: "Closure Stylesheets (GSS)", mime: "text/x-gss", mode: "css", ext: ["gss"]},
	    {name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists.txt$/},
	    {name: "CoffeeScript", mimes: ["application/vnd.coffeescript", "text/coffeescript", "text/x-coffeescript"], mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
	    {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
	    {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
	    {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
	    {name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]},
	    {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
	    {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
	    {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
	    {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},
	    {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},
	    {name: "Django", mime: "text/x-django", mode: "django"},
	    {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/},
	    {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},
	    {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},
	    {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},
	    {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},
	    {name: "edn", mime: "application/edn", mode: "clojure", ext: ["edn"]},
	    {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},
	    {name: "Elm", mime: "text/x-elm", mode: "elm", ext: ["elm"]},
	    {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},
	    {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},
	    {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},
	    {name: "Esper", mime: "text/x-esper", mode: "sql"},
	    {name: "Factor", mime: "text/x-factor", mode: "factor", ext: ["factor"]},
	    {name: "FCL", mime: "text/x-fcl", mode: "fcl"},
	    {name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]},
	    {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90", "f95"]},
	    {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},
	    {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},
	    {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},
	    {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i},
	    {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},
	    {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy", "gradle"], file: /^Jenkinsfile$/},
	    {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
	    {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
	    {name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]},
	    {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
	    {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
	    {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
	    {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm", "handlebars", "hbs"], alias: ["xhtml"]},
	    {name: "HTTP", mime: "message/http", mode: "http"},
	    {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},
	    {name: "Pug", mime: "text/x-pug", mode: "pug", ext: ["jade", "pug"], alias: ["jade"]},
	    {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},
	    {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},
	    {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],
	     mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
	    {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
	    {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
	    {name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]},
	    {name: "Jinja2", mime: "null", mode: "jinja2", ext: ["j2", "jinja", "jinja2"]},
	    {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
	    {name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]},
	    {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
	    {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
	    {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
	    {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},
	    {name: "mIRC", mime: "text/mirc", mode: "mirc"},
	    {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},
	    {name: "Mathematica", mime: "text/x-mathematica", mode: "mathematica", ext: ["m", "nb"]},
	    {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},
	    {name: "MUMPS", mime: "text/x-mumps", mode: "mumps", ext: ["mps"]},
	    {name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
	    {name: "mbox", mime: "application/mbox", mode: "mbox", ext: ["mbox"]},
	    {name: "MySQL", mime: "text/x-mysql", mode: "sql"},
	    {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
	    {name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
	    {name: "NTriples", mimes: ["application/n-triples", "application/n-quads", "text/n-triples"],
	     mode: "ntriples", ext: ["nt", "nq"]},
	    {name: "Objective-C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"], alias: ["objective-c", "objc"]},
	    {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
	    {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
	    {name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]},
	    {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
	    {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
	    {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
	    {name: "PHP", mimes: ["text/x-php", "application/x-httpd-php", "application/x-httpd-php-open"], mode: "php", ext: ["php", "php3", "php4", "php5", "php7", "phtml"]},
	    {name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
	    {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
	    {name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
	    {name: "PowerShell", mime: "application/x-powershell", mode: "powershell", ext: ["ps1", "psd1", "psm1"]},
	    {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
	    {name: "ProtoBuf", mime: "text/x-protobuf", mode: "protobuf", ext: ["proto"]},
	    {name: "Python", mime: "text/x-python", mode: "python", ext: ["BUILD", "bzl", "py", "pyw"], file: /^(BUCK|BUILD)$/},
	    {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
	    {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
	    {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r", "R"], alias: ["rscript"]},
	    {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},
	    {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},
	    {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
	    {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
	    {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
	    {name: "SAS", mime: "text/x-sas", mode: "sas", ext: ["sas"]},
	    {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
	    {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
	    {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
	    {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
	    {name: "Shell", mimes: ["text/x-sh", "application/x-sh"], mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/},
	    {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
	    {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
	    {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
	    {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},
	    {name: "Solr", mime: "text/x-solr", mode: "solr"},
	    {name: "SML", mime: "text/x-sml", mode: "mllike", ext: ["sml", "sig", "fun", "smackspec"]},
	    {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},
	    {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
	    {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
	    {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
	    {name: "SQLite", mime: "text/x-sqlite", mode: "sql"},
	    {name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]},
	    {name: "Stylus", mime: "text/x-styl", mode: "stylus", ext: ["styl"]},
	    {name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]},
	    {name: "sTeX", mime: "text/x-stex", mode: "stex"},
	    {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx", "tex"], alias: ["tex"]},
	    {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v", "sv", "svh"]},
	    {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},
	    {name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]},
	    {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},
	    {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},
	    {name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]},
	    {name: "Tornado", mime: "text/x-tornado", mode: "tornado"},
	    {name: "troff", mime: "text/troff", mode: "troff", ext: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]},
	    {name: "TTCN", mime: "text/x-ttcn", mode: "ttcn", ext: ["ttcn", "ttcn3", "ttcnpp"]},
	    {name: "TTCN_CFG", mime: "text/x-ttcn-cfg", mode: "ttcn-cfg", ext: ["cfg"]},
	    {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
	    {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
	    {name: "TypeScript-JSX", mime: "text/typescript-jsx", mode: "jsx", ext: ["tsx"], alias: ["tsx"]},
	    {name: "Twig", mime: "text/x-twig", mode: "twig"},
	    {name: "Web IDL", mime: "text/x-webidl", mode: "webidl", ext: ["webidl"]},
	    {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
	    {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
	    {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
	    {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
	    {name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]},
	    {name: "Vue.js Component", mimes: ["script/x-vue", "text/x-vue"], mode: "vue", ext: ["vue"]},
	    {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd", "svg"], alias: ["rss", "wsdl", "xsd"]},
	    {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
	    {name: "Yacas", mime: "text/x-yacas", mode: "yacas", ext: ["ys"]},
	    {name: "YAML", mimes: ["text/x-yaml", "text/yaml"], mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
	    {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]},
	    {name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]},
	    {name: "xu", mime: "text/x-xu", mode: "mscgen", ext: ["xu"]},
	    {name: "msgenny", mime: "text/x-msgenny", mode: "mscgen", ext: ["msgenny"]}
	  ];
	  // Ensure all modes have a mime property for backwards compatibility
	  for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	    var info = CodeMirror.modeInfo[i];
	    if (info.mimes) info.mime = info.mimes[0];
	  }

	  CodeMirror.findModeByMIME = function(mime) {
	    mime = mime.toLowerCase();
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.mime == mime) return info;
	      if (info.mimes) for (var j = 0; j < info.mimes.length; j++)
	        if (info.mimes[j] == mime) return info;
	    }
	    if (/\+xml$/.test(mime)) return CodeMirror.findModeByMIME("application/xml")
	    if (/\+json$/.test(mime)) return CodeMirror.findModeByMIME("application/json")
	  };

	  CodeMirror.findModeByExtension = function(ext) {
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.ext) for (var j = 0; j < info.ext.length; j++)
	        if (info.ext[j] == ext) return info;
	    }
	  };

	  CodeMirror.findModeByFileName = function(filename) {
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.file && info.file.test(filename)) return info;
	    }
	    var dot = filename.lastIndexOf(".");
	    var ext = dot > -1 && filename.substring(dot + 1, filename.length);
	    if (ext) return CodeMirror.findModeByExtension(ext);
	  };

	  CodeMirror.findModeByName = function(name) {
	    name = name.toLowerCase();
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.name.toLowerCase() == name) return info;
	      if (info.alias) for (var j = 0; j < info.alias.length; j++)
	        if (info.alias[j].toLowerCase() == name) return info;
	    }
	  };
	});


/***/ },
/* 358 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	// Utility function that allows modes to be combined. The mode given
	// as the base argument takes care of most of the normal mode
	// functionality, but a second (typically simple) mode is used, which
	// can override the style of text. Both modes get to parse all of the
	// text, but when both assign a non-null style to a piece of code, the
	// overlay wins, unless the combine argument was true and not overridden,
	// or state.overlay.combineTokens was true, in which case the styles are
	// combined.

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";

	CodeMirror.overlayMode = function(base, overlay, combine) {
	  return {
	    startState: function() {
	      return {
	        base: CodeMirror.startState(base),
	        overlay: CodeMirror.startState(overlay),
	        basePos: 0, baseCur: null,
	        overlayPos: 0, overlayCur: null,
	        streamSeen: null
	      };
	    },
	    copyState: function(state) {
	      return {
	        base: CodeMirror.copyState(base, state.base),
	        overlay: CodeMirror.copyState(overlay, state.overlay),
	        basePos: state.basePos, baseCur: null,
	        overlayPos: state.overlayPos, overlayCur: null
	      };
	    },

	    token: function(stream, state) {
	      if (stream != state.streamSeen ||
	          Math.min(state.basePos, state.overlayPos) < stream.start) {
	        state.streamSeen = stream;
	        state.basePos = state.overlayPos = stream.start;
	      }

	      if (stream.start == state.basePos) {
	        state.baseCur = base.token(stream, state.base);
	        state.basePos = stream.pos;
	      }
	      if (stream.start == state.overlayPos) {
	        stream.pos = stream.start;
	        state.overlayCur = overlay.token(stream, state.overlay);
	        state.overlayPos = stream.pos;
	      }
	      stream.pos = Math.min(state.basePos, state.overlayPos);

	      // state.overlay.combineTokens always takes precedence over combine,
	      // unless set to null
	      if (state.overlayCur == null) return state.baseCur;
	      else if (state.baseCur != null &&
	               state.overlay.combineTokens ||
	               combine && state.overlay.combineTokens == null)
	        return state.baseCur + " " + state.overlayCur;
	      else return state.overlayCur;
	    },

	    indent: base.indent && function(state, textAfter) {
	      return base.indent(state.base, textAfter);
	    },
	    electricChars: base.electricChars,

	    innerMode: function(state) { return {state: state.base, mode: base}; },

	    blankLine: function(state) {
	      var baseToken, overlayToken;
	      if (base.blankLine) baseToken = base.blankLine(state.base);
	      if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay);

	      return overlayToken == null ?
	        baseToken :
	        (combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken);
	    }
	  };
	};

	});


/***/ },
/* 359 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  CodeMirror.defineOption("placeholder", "", function(cm, val, old) {
	    var prev = old && old != CodeMirror.Init;
	    if (val && !prev) {
	      cm.on("blur", onBlur);
	      cm.on("change", onChange);
	      cm.on("swapDoc", onChange);
	      onChange(cm);
	    } else if (!val && prev) {
	      cm.off("blur", onBlur);
	      cm.off("change", onChange);
	      cm.off("swapDoc", onChange);
	      clearPlaceholder(cm);
	      var wrapper = cm.getWrapperElement();
	      wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
	    }

	    if (val && !cm.hasFocus()) onBlur(cm);
	  });

	  function clearPlaceholder(cm) {
	    if (cm.state.placeholder) {
	      cm.state.placeholder.parentNode.removeChild(cm.state.placeholder);
	      cm.state.placeholder = null;
	    }
	  }
	  function setPlaceholder(cm) {
	    clearPlaceholder(cm);
	    var elt = cm.state.placeholder = document.createElement("pre");
	    elt.style.cssText = "height: 0; overflow: visible";
	    elt.style.direction = cm.getOption("direction");
	    elt.className = "CodeMirror-placeholder";
	    var placeHolder = cm.getOption("placeholder")
	    if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
	    elt.appendChild(placeHolder)
	    cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
	  }

	  function onBlur(cm) {
	    if (isEmpty(cm)) setPlaceholder(cm);
	  }
	  function onChange(cm) {
	    var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
	    wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");

	    if (empty) setPlaceholder(cm);
	    else clearPlaceholder(cm);
	  }

	  function isEmpty(cm) {
	    return (cm.lineCount() === 1) && (cm.getLine(0) === "");
	  }
	});


/***/ },
/* 360 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	// Because sometimes you need to mark the selected *text*.
	//
	// Adds an option 'styleSelectedText' which, when enabled, gives
	// selected text the CSS class given as option value, or
	// "CodeMirror-selectedtext" when the value is not a string.

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";

	  CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
	    var prev = old && old != CodeMirror.Init;
	    if (val && !prev) {
	      cm.state.markedSelection = [];
	      cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
	      reset(cm);
	      cm.on("cursorActivity", onCursorActivity);
	      cm.on("change", onChange);
	    } else if (!val && prev) {
	      cm.off("cursorActivity", onCursorActivity);
	      cm.off("change", onChange);
	      clear(cm);
	      cm.state.markedSelection = cm.state.markedSelectionStyle = null;
	    }
	  });

	  function onCursorActivity(cm) {
	    if (cm.state.markedSelection)
	      cm.operation(function() { update(cm); });
	  }

	  function onChange(cm) {
	    if (cm.state.markedSelection && cm.state.markedSelection.length)
	      cm.operation(function() { clear(cm); });
	  }

	  var CHUNK_SIZE = 8;
	  var Pos = CodeMirror.Pos;
	  var cmp = CodeMirror.cmpPos;

	  function coverRange(cm, from, to, addAt) {
	    if (cmp(from, to) == 0) return;
	    var array = cm.state.markedSelection;
	    var cls = cm.state.markedSelectionStyle;
	    for (var line = from.line;;) {
	      var start = line == from.line ? from : Pos(line, 0);
	      var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
	      var end = atEnd ? to : Pos(endLine, 0);
	      var mark = cm.markText(start, end, {className: cls});
	      if (addAt == null) array.push(mark);
	      else array.splice(addAt++, 0, mark);
	      if (atEnd) break;
	      line = endLine;
	    }
	  }

	  function clear(cm) {
	    var array = cm.state.markedSelection;
	    for (var i = 0; i < array.length; ++i) array[i].clear();
	    array.length = 0;
	  }

	  function reset(cm) {
	    clear(cm);
	    var ranges = cm.listSelections();
	    for (var i = 0; i < ranges.length; i++)
	      coverRange(cm, ranges[i].from(), ranges[i].to());
	  }

	  function update(cm) {
	    if (!cm.somethingSelected()) return clear(cm);
	    if (cm.listSelections().length > 1) return reset(cm);

	    var from = cm.getCursor("start"), to = cm.getCursor("end");

	    var array = cm.state.markedSelection;
	    if (!array.length) return coverRange(cm, from, to);

	    var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
	    if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE ||
	        cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
	      return reset(cm);

	    while (cmp(from, coverStart.from) > 0) {
	      array.shift().clear();
	      coverStart = array[0].find();
	    }
	    if (cmp(from, coverStart.from) < 0) {
	      if (coverStart.to.line - from.line < CHUNK_SIZE) {
	        array.shift().clear();
	        coverRange(cm, from, coverStart.to, 0);
	      } else {
	        coverRange(cm, from, coverStart.from, 0);
	      }
	    }

	    while (cmp(to, coverEnd.to) < 0) {
	      array.pop().clear();
	      coverEnd = array[array.length - 1].find();
	    }
	    if (cmp(to, coverEnd.to) > 0) {
	      if (to.line - coverEnd.from.line < CHUNK_SIZE) {
	        array.pop().clear();
	        coverRange(cm, coverEnd.from, to);
	      } else {
	        coverRange(cm, coverEnd.to, to);
	      }
	    }
	  }
	});


/***/ },
/* 361 */
/***/ function(module, exports, __webpack_require__) {

	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/LICENSE

	(function(mod) {
	  if (true) // CommonJS
	    mod(__webpack_require__(351), __webpack_require__(355), __webpack_require__(358));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";

	var urlRE = /^((?:(?:aaas?|about|acap|adiumxtra|af[ps]|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|cap|chrome(?:-extension)?|cid|coap|com-eventbrite-attendee|content|crid|cvs|data|dav|dict|dlna-(?:playcontainer|playsingle)|dns|doi|dtn|dvb|ed2k|facetime|feed|file|finger|fish|ftp|geo|gg|git|gizmoproject|go|gopher|gtalk|h323|hcp|https?|iax|icap|icon|im|imap|info|ipn|ipp|irc[6s]?|iris(?:\.beep|\.lwz|\.xpc|\.xpcs)?|itms|jar|javascript|jms|keyparc|lastfm|ldaps?|magnet|mailto|maps|market|message|mid|mms|ms-help|msnim|msrps?|mtqp|mumble|mupdate|mvn|news|nfs|nih?|nntp|notes|oid|opaquelocktoken|palm|paparazzi|platform|pop|pres|proxy|psyc|query|res(?:ource)?|rmi|rsync|rtmp|rtsp|secondlife|service|session|sftp|sgn|shttp|sieve|sips?|skype|sm[bs]|snmp|soap\.beeps?|soldat|spotify|ssh|steam|svn|tag|teamspeak|tel(?:net)?|tftp|things|thismessage|tip|tn3270|tv|udp|unreal|urn|ut2004|vemmi|ventrilo|view-source|webcal|wss?|wtai|wyciwyg|xcon(?:-userid)?|xfire|xmlrpc\.beeps?|xmpp|xri|ymsgr|z39\.50[rs]?):(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i

	CodeMirror.defineMode("gfm", function(config, modeConfig) {
	  var codeDepth = 0;
	  function blankLine(state) {
	    state.code = false;
	    return null;
	  }
	  var gfmOverlay = {
	    startState: function() {
	      return {
	        code: false,
	        codeBlock: false,
	        ateSpace: false
	      };
	    },
	    copyState: function(s) {
	      return {
	        code: s.code,
	        codeBlock: s.codeBlock,
	        ateSpace: s.ateSpace
	      };
	    },
	    token: function(stream, state) {
	      state.combineTokens = null;

	      // Hack to prevent formatting override inside code blocks (block and inline)
	      if (state.codeBlock) {
	        if (stream.match(/^```+/)) {
	          state.codeBlock = false;
	          return null;
	        }
	        stream.skipToEnd();
	        return null;
	      }
	      if (stream.sol()) {
	        state.code = false;
	      }
	      if (stream.sol() && stream.match(/^```+/)) {
	        stream.skipToEnd();
	        state.codeBlock = true;
	        return null;
	      }
	      // If this block is changed, it may need to be updated in Markdown mode
	      if (stream.peek() === '`') {
	        stream.next();
	        var before = stream.pos;
	        stream.eatWhile('`');
	        var difference = 1 + stream.pos - before;
	        if (!state.code) {
	          codeDepth = difference;
	          state.code = true;
	        } else {
	          if (difference === codeDepth) { // Must be exact
	            state.code = false;
	          }
	        }
	        return null;
	      } else if (state.code) {
	        stream.next();
	        return null;
	      }
	      // Check if space. If so, links can be formatted later on
	      if (stream.eatSpace()) {
	        state.ateSpace = true;
	        return null;
	      }
	      if (stream.sol() || state.ateSpace) {
	        state.ateSpace = false;
	        if (modeConfig.gitHubSpice !== false) {
	          if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?=.{0,6}\d)(?:[a-f0-9]{7,40}\b)/)) {
	            // User/Project@SHA
	            // User@SHA
	            // SHA
	            state.combineTokens = true;
	            return "link";
	          } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
	            // User/Project#Num
	            // User#Num
	            // #Num
	            state.combineTokens = true;
	            return "link";
	          }
	        }
	      }
	      if (stream.match(urlRE) &&
	          stream.string.slice(stream.start - 2, stream.start) != "](" &&
	          (stream.start == 0 || /\W/.test(stream.string.charAt(stream.start - 1)))) {
	        // URLs
	        // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
	        // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
	        // And then limited url schemes to the CommonMark list, so foo:bar isn't matched as a URL
	        state.combineTokens = true;
	        return "link";
	      }
	      stream.next();
	      return null;
	    },
	    blankLine: blankLine
	  };

	  var markdownConfig = {
	    taskLists: true,
	    strikethrough: true,
	    emoji: true
	  };
	  for (var attr in modeConfig) {
	    markdownConfig[attr] = modeConfig[attr];
	  }
	  markdownConfig.name = "markdown";
	  return CodeMirror.overlayMode(CodeMirror.getMode(config, markdownConfig), gfmOverlay);

	}, "markdown");

	  CodeMirror.defineMIME("text/x-gfm", "gfm");
	});


/***/ },
/* 362 */
/***/ function(module, exports, __webpack_require__) {

	// Use strict mode (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)
	"use strict";


	// Requires
	var Typo = __webpack_require__(363);


	// Create function
	function CodeMirrorSpellChecker(options) {
		// Initialize
		options = options || {};


		// Verify
		if(typeof options.codeMirrorInstance !== "function" || typeof options.codeMirrorInstance.defineMode !== "function") {
			console.log("CodeMirror Spell Checker: You must provide an instance of CodeMirror via the option `codeMirrorInstance`");
			return;
		}


		// Because some browsers don't support this functionality yet
		if(!String.prototype.includes) {
			String.prototype.includes = function() {
				"use strict";
				return String.prototype.indexOf.apply(this, arguments) !== -1;
			};
		}


		// Define the new mode
		options.codeMirrorInstance.defineMode("spell-checker", function(config) {
			// Load AFF/DIC data
			if(!CodeMirrorSpellChecker.aff_loading) {
				CodeMirrorSpellChecker.aff_loading = true;
				var xhr_aff = new XMLHttpRequest();
				xhr_aff.open("GET", "https://cdn.jsdelivr.net/codemirror.spell-checker/latest/en_US.aff", true);
				xhr_aff.onload = function() {
					if(xhr_aff.readyState === 4 && xhr_aff.status === 200) {
						CodeMirrorSpellChecker.aff_data = xhr_aff.responseText;
						CodeMirrorSpellChecker.num_loaded++;

						if(CodeMirrorSpellChecker.num_loaded == 2) {
							CodeMirrorSpellChecker.typo = new Typo("en_US", CodeMirrorSpellChecker.aff_data, CodeMirrorSpellChecker.dic_data, {
								platform: "any"
							});
						}
					}
				};
				xhr_aff.send(null);
			}

			if(!CodeMirrorSpellChecker.dic_loading) {
				CodeMirrorSpellChecker.dic_loading = true;
				var xhr_dic = new XMLHttpRequest();
				xhr_dic.open("GET", "https://cdn.jsdelivr.net/codemirror.spell-checker/latest/en_US.dic", true);
				xhr_dic.onload = function() {
					if(xhr_dic.readyState === 4 && xhr_dic.status === 200) {
						CodeMirrorSpellChecker.dic_data = xhr_dic.responseText;
						CodeMirrorSpellChecker.num_loaded++;

						if(CodeMirrorSpellChecker.num_loaded == 2) {
							CodeMirrorSpellChecker.typo = new Typo("en_US", CodeMirrorSpellChecker.aff_data, CodeMirrorSpellChecker.dic_data, {
								platform: "any"
							});
						}
					}
				};
				xhr_dic.send(null);
			}


			// Define what separates a word
			var rx_word = "!\"#$%&()*+,-./:;<=>?@[\\]^_`{|}~ ";


			// Create the overlay and such
			var overlay = {
				token: function(stream) {
					var ch = stream.peek();
					var word = "";

					if(rx_word.includes(ch)) {
						stream.next();
						return null;
					}

					while((ch = stream.peek()) != null && !rx_word.includes(ch)) {
						word += ch;
						stream.next();
					}

					if(CodeMirrorSpellChecker.typo && !CodeMirrorSpellChecker.typo.check(word))
						return "spell-error"; // CSS class: cm-spell-error

					return null;
				}
			};

			var mode = options.codeMirrorInstance.getMode(
				config, config.backdrop || "text/plain"
			);

			return options.codeMirrorInstance.overlayMode(mode, overlay, true);
		});
	}


	// Initialize data globally to reduce memory consumption
	CodeMirrorSpellChecker.num_loaded = 0;
	CodeMirrorSpellChecker.aff_loading = false;
	CodeMirrorSpellChecker.dic_loading = false;
	CodeMirrorSpellChecker.aff_data = "";
	CodeMirrorSpellChecker.dic_data = "";
	CodeMirrorSpellChecker.typo;


	// Export
	module.exports = CodeMirrorSpellChecker;

/***/ },
/* 363 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(__dirname, Buffer) {/* globals chrome: false */
	/* globals __dirname: false */
	/* globals require: false */
	/* globals Buffer: false */
	/* globals module: false */

	/**
	 * Typo is a JavaScript implementation of a spellchecker using hunspell-style 
	 * dictionaries.
	 */

	var Typo;

	(function () {
	"use strict";

	/**
	 * Typo constructor.
	 *
	 * @param {String} [dictionary] The locale code of the dictionary being used. e.g.,
	 *                              "en_US". This is only used to auto-load dictionaries.
	 * @param {String} [affData]    The data from the dictionary's .aff file. If omitted
	 *                              and Typo.js is being used in a Chrome extension, the .aff
	 *                              file will be loaded automatically from
	 *                              lib/typo/dictionaries/[dictionary]/[dictionary].aff
	 *                              In other environments, it will be loaded from
	 *                              [settings.dictionaryPath]/dictionaries/[dictionary]/[dictionary].aff
	 * @param {String} [wordsData]  The data from the dictionary's .dic file. If omitted
	 *                              and Typo.js is being used in a Chrome extension, the .dic
	 *                              file will be loaded automatically from
	 *                              lib/typo/dictionaries/[dictionary]/[dictionary].dic
	 *                              In other environments, it will be loaded from
	 *                              [settings.dictionaryPath]/dictionaries/[dictionary]/[dictionary].dic
	 * @param {Object} [settings]   Constructor settings. Available properties are:
	 *                              {String} [dictionaryPath]: path to load dictionary from in non-chrome
	 *                              environment.
	 *                              {Object} [flags]: flag information.
	 *                              {Boolean} [asyncLoad]: If true, affData and wordsData will be loaded
	 *                              asynchronously.
	 *                              {Function} [loadedCallback]: Called when both affData and wordsData
	 *                              have been loaded. Only used if asyncLoad is set to true. The parameter
	 *                              is the instantiated Typo object.
	 *
	 * @returns {Typo} A Typo object.
	 */

	Typo = function (dictionary, affData, wordsData, settings) {
		settings = settings || {};

		this.dictionary = null;
		
		this.rules = {};
		this.dictionaryTable = {};
		
		this.compoundRules = [];
		this.compoundRuleCodes = {};
		
		this.replacementTable = [];
		
		this.flags = settings.flags || {}; 
		
		this.memoized = {};

		this.loaded = false;
		
		var self = this;
		
		var path;
		
		// Loop-control variables.
		var i, j, _len, _jlen;
		
		if (dictionary) {
			self.dictionary = dictionary;
			
			// If the data is preloaded, just setup the Typo object.
			if (affData && wordsData) {
				setup();
			}
			// Loading data for Chrome extentions.
			else if (typeof window !== 'undefined' && 'chrome' in window && 'extension' in window.chrome && 'getURL' in window.chrome.extension) {
				if (settings.dictionaryPath) {
					path = settings.dictionaryPath;
				}
				else {
					path = "typo/dictionaries";
				}
				
				if (!affData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".aff"), setAffData);
				if (!wordsData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".dic"), setWordsData);
			}
			else {
				if (settings.dictionaryPath) {
					path = settings.dictionaryPath;
				}
				else if (true) {
					path = __dirname + '/dictionaries';
				}
				else {
					path = './dictionaries';
				}
				
				if (!affData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".aff", setAffData);
				if (!wordsData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".dic", setWordsData);
			}
		}
		
		function readDataFile(url, setFunc) {
			var response = self._readFile(url, null, settings.asyncLoad);
			
			if (settings.asyncLoad) {
				response.then(function(data) {
					setFunc(data);
				});
			}
			else {
				setFunc(response);
			}
		}

		function setAffData(data) {
			affData = data;

			if (wordsData) {
				setup();
			}
		}

		function setWordsData(data) {
			wordsData = data;

			if (affData) {
				setup();
			}
		}

		function setup() {
			self.rules = self._parseAFF(affData);
			
			// Save the rule codes that are used in compound rules.
			self.compoundRuleCodes = {};
			
			for (i = 0, _len = self.compoundRules.length; i < _len; i++) {
				var rule = self.compoundRules[i];
				
				for (j = 0, _jlen = rule.length; j < _jlen; j++) {
					self.compoundRuleCodes[rule[j]] = [];
				}
			}
			
			// If we add this ONLYINCOMPOUND flag to self.compoundRuleCodes, then _parseDIC
			// will do the work of saving the list of words that are compound-only.
			if ("ONLYINCOMPOUND" in self.flags) {
				self.compoundRuleCodes[self.flags.ONLYINCOMPOUND] = [];
			}
			
			self.dictionaryTable = self._parseDIC(wordsData);
			
			// Get rid of any codes from the compound rule codes that are never used 
			// (or that were special regex characters).  Not especially necessary... 
			for (i in self.compoundRuleCodes) {
				if (self.compoundRuleCodes[i].length === 0) {
					delete self.compoundRuleCodes[i];
				}
			}
			
			// Build the full regular expressions for each compound rule.
			// I have a feeling (but no confirmation yet) that this method of 
			// testing for compound words is probably slow.
			for (i = 0, _len = self.compoundRules.length; i < _len; i++) {
				var ruleText = self.compoundRules[i];
				
				var expressionText = "";
				
				for (j = 0, _jlen = ruleText.length; j < _jlen; j++) {
					var character = ruleText[j];
					
					if (character in self.compoundRuleCodes) {
						expressionText += "(" + self.compoundRuleCodes[character].join("|") + ")";
					}
					else {
						expressionText += character;
					}
				}
				
				self.compoundRules[i] = new RegExp(expressionText, "i");
			}
			
			self.loaded = true;
			
			if (settings.asyncLoad && settings.loadedCallback) {
				settings.loadedCallback(self);
			}
		}
		
		return this;
	};

	Typo.prototype = {
		/**
		 * Loads a Typo instance from a hash of all of the Typo properties.
		 *
		 * @param object obj A hash of Typo properties, probably gotten from a JSON.parse(JSON.stringify(typo_instance)).
		 */
		
		load : function (obj) {
			for (var i in obj) {
				if (obj.hasOwnProperty(i)) {
					this[i] = obj[i];
				}
			}
			
			return this;
		},
		
		/**
		 * Read the contents of a file.
		 * 
		 * @param {String} path The path (relative) to the file.
		 * @param {String} [charset="ISO8859-1"] The expected charset of the file
		 * @param {Boolean} async If true, the file will be read asynchronously. For node.js this does nothing, all
		 *        files are read synchronously.
		 * @returns {String} The file data if async is false, otherwise a promise object. If running node.js, the data is
		 *          always returned.
		 */
		
		_readFile : function (path, charset, async) {
			charset = charset || "utf8";
			
			if (typeof XMLHttpRequest !== 'undefined') {
				var promise;
				var req = new XMLHttpRequest();
				req.open("GET", path, async);
				
				if (async) {
					promise = new Promise(function(resolve, reject) {
						req.onload = function() {
							if (req.status === 200) {
								resolve(req.responseText);
							}
							else {
								reject(req.statusText);
							}
						};
						
						req.onerror = function() {
							reject(req.statusText);
						}
					});
				}
			
				if (req.overrideMimeType)
					req.overrideMimeType("text/plain; charset=" + charset);
			
				req.send(null);
				
				return async ? promise : req.responseText;
			}
			else if (true) {
				// Node.js
				var fs = __webpack_require__(368);
				
				try {
					if (fs.existsSync(path)) {
						var stats = fs.statSync(path);
						
						var fileDescriptor = fs.openSync(path, 'r');
						
						var buffer = new Buffer(stats.size);
						
						fs.readSync(fileDescriptor, buffer, 0, buffer.length, null);
						
						return buffer.toString(charset, 0, buffer.length);
					}
					else {
						console.log("Path " + path + " does not exist.");
					}
				} catch (e) {
					console.log(e);
					return '';
				}
			}
		},
		
		/**
		 * Parse the rules out from a .aff file.
		 *
		 * @param {String} data The contents of the affix file.
		 * @returns object The rules from the file.
		 */
		
		_parseAFF : function (data) {
			var rules = {};
			
			var line, subline, numEntries, lineParts;
			var i, j, _len, _jlen;
			
			// Remove comment lines
			data = this._removeAffixComments(data);
			
			var lines = data.split("\n");
			
			for (i = 0, _len = lines.length; i < _len; i++) {
				line = lines[i];
				
				var definitionParts = line.split(/\s+/);
				
				var ruleType = definitionParts[0];
				
				if (ruleType == "PFX" || ruleType == "SFX") {
					var ruleCode = definitionParts[1];
					var combineable = definitionParts[2];
					numEntries = parseInt(definitionParts[3], 10);
					
					var entries = [];
					
					for (j = i + 1, _jlen = i + 1 + numEntries; j < _jlen; j++) {
						subline = lines[j];
						
						lineParts = subline.split(/\s+/);
						var charactersToRemove = lineParts[2];
						
						var additionParts = lineParts[3].split("/");
						
						var charactersToAdd = additionParts[0];
						if (charactersToAdd === "0") charactersToAdd = "";
						
						var continuationClasses = this.parseRuleCodes(additionParts[1]);
						
						var regexToMatch = lineParts[4];
						
						var entry = {};
						entry.add = charactersToAdd;
						
						if (continuationClasses.length > 0) entry.continuationClasses = continuationClasses;
						
						if (regexToMatch !== ".") {
							if (ruleType === "SFX") {
								entry.match = new RegExp(regexToMatch + "$");
							}
							else {
								entry.match = new RegExp("^" + regexToMatch);
							}
						}
						
						if (charactersToRemove != "0") {
							if (ruleType === "SFX") {
								entry.remove = new RegExp(charactersToRemove  + "$");
							}
							else {
								entry.remove = charactersToRemove;
							}
						}
						
						entries.push(entry);
					}
					
					rules[ruleCode] = { "type" : ruleType, "combineable" : (combineable == "Y"), "entries" : entries };
					
					i += numEntries;
				}
				else if (ruleType === "COMPOUNDRULE") {
					numEntries = parseInt(definitionParts[1], 10);
					
					for (j = i + 1, _jlen = i + 1 + numEntries; j < _jlen; j++) {
						line = lines[j];
						
						lineParts = line.split(/\s+/);
						this.compoundRules.push(lineParts[1]);
					}
					
					i += numEntries;
				}
				else if (ruleType === "REP") {
					lineParts = line.split(/\s+/);
					
					if (lineParts.length === 3) {
						this.replacementTable.push([ lineParts[1], lineParts[2] ]);
					}
				}
				else {
					// ONLYINCOMPOUND
					// COMPOUNDMIN
					// FLAG
					// KEEPCASE
					// NEEDAFFIX
					
					this.flags[ruleType] = definitionParts[1];
				}
			}
			
			return rules;
		},
		
		/**
		 * Removes comment lines and then cleans up blank lines and trailing whitespace.
		 *
		 * @param {String} data The data from an affix file.
		 * @return {String} The cleaned-up data.
		 */
		
		_removeAffixComments : function (data) {
			// Remove comments
			// This used to remove any string starting with '#' up to the end of the line,
			// but some COMPOUNDRULE definitions include '#' as part of the rule.
			// I haven't seen any affix files that use comments on the same line as real data,
			// so I don't think this will break anything.
			data = data.replace(/^\s*#.*$/mg, "");
			
			// Trim each line
			data = data.replace(/^\s\s*/m, '').replace(/\s\s*$/m, '');
			
			// Remove blank lines.
			data = data.replace(/\n{2,}/g, "\n");
			
			// Trim the entire string
			data = data.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
			
			return data;
		},
		
		/**
		 * Parses the words out from the .dic file.
		 *
		 * @param {String} data The data from the dictionary file.
		 * @returns object The lookup table containing all of the words and
		 *                 word forms from the dictionary.
		 */
		
		_parseDIC : function (data) {
			data = this._removeDicComments(data);
			
			var lines = data.split("\n");
			var dictionaryTable = {};
			
			function addWord(word, rules) {
				// Some dictionaries will list the same word multiple times with different rule sets.
				if (!dictionaryTable.hasOwnProperty(word)) {
					dictionaryTable[word] = null;
				}
				
				if (rules.length > 0) {
					if (dictionaryTable[word] === null) {
						dictionaryTable[word] = [];
					}

					dictionaryTable[word].push(rules);
				}
			}
			
			// The first line is the number of words in the dictionary.
			for (var i = 1, _len = lines.length; i < _len; i++) {
				var line = lines[i];
				
				var parts = line.split("/", 2);
				
				var word = parts[0];

				// Now for each affix rule, generate that form of the word.
				if (parts.length > 1) {
					var ruleCodesArray = this.parseRuleCodes(parts[1]);
					
					// Save the ruleCodes for compound word situations.
					if (!("NEEDAFFIX" in this.flags) || ruleCodesArray.indexOf(this.flags.NEEDAFFIX) == -1) {
						addWord(word, ruleCodesArray);
					}
					
					for (var j = 0, _jlen = ruleCodesArray.length; j < _jlen; j++) {
						var code = ruleCodesArray[j];
						
						var rule = this.rules[code];
						
						if (rule) {
							var newWords = this._applyRule(word, rule);
							
							for (var ii = 0, _iilen = newWords.length; ii < _iilen; ii++) {
								var newWord = newWords[ii];
								
								addWord(newWord, []);
								
								if (rule.combineable) {
									for (var k = j + 1; k < _jlen; k++) {
										var combineCode = ruleCodesArray[k];
										
										var combineRule = this.rules[combineCode];
										
										if (combineRule) {
											if (combineRule.combineable && (rule.type != combineRule.type)) {
												var otherNewWords = this._applyRule(newWord, combineRule);
												
												for (var iii = 0, _iiilen = otherNewWords.length; iii < _iiilen; iii++) {
													var otherNewWord = otherNewWords[iii];
													addWord(otherNewWord, []);
												}
											}
										}
									}
								}
							}
						}
						
						if (code in this.compoundRuleCodes) {
							this.compoundRuleCodes[code].push(word);
						}
					}
				}
				else {
					addWord(word.trim(), []);
				}
			}
			
			return dictionaryTable;
		},
		
		
		/**
		 * Removes comment lines and then cleans up blank lines and trailing whitespace.
		 *
		 * @param {String} data The data from a .dic file.
		 * @return {String} The cleaned-up data.
		 */
		
		_removeDicComments : function (data) {
			// I can't find any official documentation on it, but at least the de_DE
			// dictionary uses tab-indented lines as comments.
			
			// Remove comments
			data = data.replace(/^\t.*$/mg, "");
			
			return data;
		},
		
		parseRuleCodes : function (textCodes) {
			if (!textCodes) {
				return [];
			}
			else if (!("FLAG" in this.flags)) {
				return textCodes.split("");
			}
			else if (this.flags.FLAG === "long") {
				var flags = [];
				
				for (var i = 0, _len = textCodes.length; i < _len; i += 2) {
					flags.push(textCodes.substr(i, 2));
				}
				
				return flags;
			}
			else if (this.flags.FLAG === "num") {
				return textCodes.split(",");
			}
		},
		
		/**
		 * Applies an affix rule to a word.
		 *
		 * @param {String} word The base word.
		 * @param {Object} rule The affix rule.
		 * @returns {String[]} The new words generated by the rule.
		 */
		
		_applyRule : function (word, rule) {
			var entries = rule.entries;
			var newWords = [];
			
			for (var i = 0, _len = entries.length; i < _len; i++) {
				var entry = entries[i];
				
				if (!entry.match || word.match(entry.match)) {
					var newWord = word;
					
					if (entry.remove) {
						newWord = newWord.replace(entry.remove, "");
					}
					
					if (rule.type === "SFX") {
						newWord = newWord + entry.add;
					}
					else {
						newWord = entry.add + newWord;
					}
					
					newWords.push(newWord);
					
					if ("continuationClasses" in entry) {
						for (var j = 0, _jlen = entry.continuationClasses.length; j < _jlen; j++) {
							var continuationRule = this.rules[entry.continuationClasses[j]];
							
							if (continuationRule) {
								newWords = newWords.concat(this._applyRule(newWord, continuationRule));
							}
							/*
							else {
								// This shouldn't happen, but it does, at least in the de_DE dictionary.
								// I think the author mistakenly supplied lower-case rule codes instead 
								// of upper-case.
							}
							*/
						}
					}
				}
			}
			
			return newWords;
		},
		
		/**
		 * Checks whether a word or a capitalization variant exists in the current dictionary.
		 * The word is trimmed and several variations of capitalizations are checked.
		 * If you want to check a word without any changes made to it, call checkExact()
		 *
		 * @see http://blog.stevenlevithan.com/archives/faster-trim-javascript re:trimming function
		 *
		 * @param {String} aWord The word to check.
		 * @returns {Boolean}
		 */
		
		check : function (aWord) {
			if (!this.loaded) {
				throw "Dictionary not loaded.";
			}
			
			// Remove leading and trailing whitespace
			var trimmedWord = aWord.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
			
			if (this.checkExact(trimmedWord)) {
				return true;
			}
			
			// The exact word is not in the dictionary.
			if (trimmedWord.toUpperCase() === trimmedWord) {
				// The word was supplied in all uppercase.
				// Check for a capitalized form of the word.
				var capitalizedWord = trimmedWord[0] + trimmedWord.substring(1).toLowerCase();
				
				if (this.hasFlag(capitalizedWord, "KEEPCASE")) {
					// Capitalization variants are not allowed for this word.
					return false;
				}
				
				if (this.checkExact(capitalizedWord)) {
					return true;
				}
			}
			
			var lowercaseWord = trimmedWord.toLowerCase();
			
			if (lowercaseWord !== trimmedWord) {
				if (this.hasFlag(lowercaseWord, "KEEPCASE")) {
					// Capitalization variants are not allowed for this word.
					return false;
				}
				
				// Check for a lowercase form
				if (this.checkExact(lowercaseWord)) {
					return true;
				}
			}
			
			return false;
		},
		
		/**
		 * Checks whether a word exists in the current dictionary.
		 *
		 * @param {String} word The word to check.
		 * @returns {Boolean}
		 */
		
		checkExact : function (word) {
			if (!this.loaded) {
				throw "Dictionary not loaded.";
			}

			var ruleCodes = this.dictionaryTable[word];
			
			var i, _len;
			
			if (typeof ruleCodes === 'undefined') {
				// Check if this might be a compound word.
				if ("COMPOUNDMIN" in this.flags && word.length >= this.flags.COMPOUNDMIN) {
					for (i = 0, _len = this.compoundRules.length; i < _len; i++) {
						if (word.match(this.compoundRules[i])) {
							return true;
						}
					}
				}
			}
			else if (ruleCodes === null) {
				// a null (but not undefined) value for an entry in the dictionary table
				// means that the word is in the dictionary but has no flags.
				return true;
			}
			else if (typeof ruleCodes === 'object') { // this.dictionary['hasOwnProperty'] will be a function.
				for (i = 0, _len = ruleCodes.length; i < _len; i++) {
					if (!this.hasFlag(word, "ONLYINCOMPOUND", ruleCodes[i])) {
						return true;
					}
				}
			}

			return false;
		},
		
		/**
		 * Looks up whether a given word is flagged with a given flag.
		 *
		 * @param {String} word The word in question.
		 * @param {String} flag The flag in question.
		 * @return {Boolean}
		 */
		 
		hasFlag : function (word, flag, wordFlags) {
			if (!this.loaded) {
				throw "Dictionary not loaded.";
			}

			if (flag in this.flags) {
				if (typeof wordFlags === 'undefined') {
					wordFlags = Array.prototype.concat.apply([], this.dictionaryTable[word]);
				}
				
				if (wordFlags && wordFlags.indexOf(this.flags[flag]) !== -1) {
					return true;
				}
			}
			
			return false;
		},
		
		/**
		 * Returns a list of suggestions for a misspelled word.
		 *
		 * @see http://www.norvig.com/spell-correct.html for the basis of this suggestor.
		 * This suggestor is primitive, but it works.
		 *
		 * @param {String} word The misspelling.
		 * @param {Number} [limit=5] The maximum number of suggestions to return.
		 * @returns {String[]} The array of suggestions.
		 */
		
		alphabet : "",
		
		suggest : function (word, limit) {
			if (!this.loaded) {
				throw "Dictionary not loaded.";
			}

			limit = limit || 5;

			if (this.memoized.hasOwnProperty(word)) {
				var memoizedLimit = this.memoized[word]['limit'];

				// Only return the cached list if it's big enough or if there weren't enough suggestions
				// to fill a smaller limit.
				if (limit <= memoizedLimit || this.memoized[word]['suggestions'].length < memoizedLimit) {
					return this.memoized[word]['suggestions'].slice(0, limit);
				}
			}
			
			if (this.check(word)) return [];
			
			// Check the replacement table.
			for (var i = 0, _len = this.replacementTable.length; i < _len; i++) {
				var replacementEntry = this.replacementTable[i];
				
				if (word.indexOf(replacementEntry[0]) !== -1) {
					var correctedWord = word.replace(replacementEntry[0], replacementEntry[1]);
					
					if (this.check(correctedWord)) {
						return [ correctedWord ];
					}
				}
			}
			
			var self = this;
			self.alphabet = "abcdefghijklmnopqrstuvwxyz";
			
			/*
			if (!self.alphabet) {
				// Use the alphabet as implicitly defined by the words in the dictionary.
				var alphaHash = {};
				
				for (var i in self.dictionaryTable) {
					for (var j = 0, _len = i.length; j < _len; j++) {
						alphaHash[i[j]] = true;
					}
				}
				
				for (var i in alphaHash) {
					self.alphabet += i;
				}
				
				var alphaArray = self.alphabet.split("");
				alphaArray.sort();
				self.alphabet = alphaArray.join("");
			}
			*/
			
			function edits1(words) {
				var rv = [];
				
				var ii, i, j, _iilen, _len, _jlen;
				
				for (ii = 0, _iilen = words.length; ii < _iilen; ii++) {
					var word = words[ii];
					
					for (i = 0, _len = word.length + 1; i < _len; i++) {
						var s = [ word.substring(0, i), word.substring(i) ];
					
						if (s[1]) {
							rv.push(s[0] + s[1].substring(1));
						}
						
						// Eliminate transpositions of identical letters
						if (s[1].length > 1 && s[1][1] !== s[1][0]) {
							rv.push(s[0] + s[1][1] + s[1][0] + s[1].substring(2));
						}

						if (s[1]) {
							for (j = 0, _jlen = self.alphabet.length; j < _jlen; j++) {
								// Eliminate replacement of a letter by itself
								if (self.alphabet[j] != s[1].substring(0,1)){
									rv.push(s[0] + self.alphabet[j] + s[1].substring(1));
								}
							}
						}

						if (s[1]) {
							for (j = 0, _jlen = self.alphabet.length; j < _jlen; j++) {
								rv.push(s[0] + self.alphabet[j] + s[1]);
							}
						}
					}
				}
				
				return rv;
			}
			
			function known(words) {
				var rv = [];
				
				for (var i = 0, _len = words.length; i < _len; i++) {
					if (self.check(words[i])) {
						rv.push(words[i]);
					}
				}
				
				return rv;
			}
			
			function correct(word) {
				// Get the edit-distance-1 and edit-distance-2 forms of this word.
				var ed1 = edits1([word]);
				var ed2 = edits1(ed1);
				
				var corrections = known(ed1.concat(ed2));
				
				var i, _len;
				
				// Sort the edits based on how many different ways they were created.
				var weighted_corrections = {};
				
				for (i = 0, _len = corrections.length; i < _len; i++) {
					if (!(corrections[i] in weighted_corrections)) {
						weighted_corrections[corrections[i]] = 1;
					}
					else {
						weighted_corrections[corrections[i]] += 1;
					}
				}
				
				var sorted_corrections = [];
				
				for (i in weighted_corrections) {
					if (weighted_corrections.hasOwnProperty(i)) {
						sorted_corrections.push([ i, weighted_corrections[i] ]);
					}
				}
				
				function sorter(a, b) {
					if (a[1] < b[1]) {
						return -1;
					}
					
					return 1;
				}
				
				sorted_corrections.sort(sorter).reverse();
				
				var rv = [];

				var capitalization_scheme = "lowercase";
				
				if (word.toUpperCase() === word) {
					capitalization_scheme = "uppercase";
				}
				else if (word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase() === word) {
					capitalization_scheme = "capitalized";
				}
				
				for (i = 0, _len = Math.min(limit, sorted_corrections.length); i < _len; i++) {
					if ("uppercase" === capitalization_scheme) {
						sorted_corrections[i][0] = sorted_corrections[i][0].toUpperCase();
					}
					else if ("capitalized" === capitalization_scheme) {
						sorted_corrections[i][0] = sorted_corrections[i][0].substr(0, 1).toUpperCase() + sorted_corrections[i][0].substr(1);
					}
					
					if (!self.hasFlag(sorted_corrections[i][0], "NOSUGGEST")) {
						rv.push(sorted_corrections[i][0]);
					}
				}
				
				return rv;
			}
			
			this.memoized[word] = {
				'suggestions': correct(word),
				'limit': limit
			};

			return this.memoized[word]['suggestions'];
		}
	};
	})();

	// Support for use as a node.js module.
	if (true) {
		module.exports = Typo;
	}
	/* WEBPACK VAR INJECTION */}.call(exports, "/", __webpack_require__(364).Buffer))

/***/ },
/* 364 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(Buffer, 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 */

	'use strict'

	var base64 = __webpack_require__(365)
	var ieee754 = __webpack_require__(366)
	var isArray = __webpack_require__(367)

	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(exports, __webpack_require__(364).Buffer, (function() { return this; }())))

/***/ },
/* 365 */
/***/ function(module, exports) {

	'use strict'

	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

	  for (var 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('')
	}


/***/ },
/* 366 */
/***/ function(module, exports) {

	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
	}


/***/ },
/* 367 */
/***/ function(module, exports) {

	var toString = {}.toString;

	module.exports = Array.isArray || function (arr) {
	  return toString.call(arr) == '[object Array]';
	};


/***/ },
/* 368 */
/***/ function(module, exports) {

	/* (ignored) */

/***/ },
/* 369 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {/**
	 * marked - a markdown parser
	 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
	 * https://github.com/chjj/marked
	 */

	;(function() {

	/**
	 * Block-Level Grammar
	 */

	var block = {
	  newline: /^\n+/,
	  code: /^( {4}[^\n]+\n*)+/,
	  fences: noop,
	  hr: /^( *[-*_]){3,} *(?:\n+|$)/,
	  heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
	  nptable: noop,
	  lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
	  blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
	  list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
	  html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
	  def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
	  table: noop,
	  paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
	  text: /^[^\n]+/
	};

	block.bullet = /(?:[*+-]|\d+\.)/;
	block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
	block.item = replace(block.item, 'gm')
	  (/bull/g, block.bullet)
	  ();

	block.list = replace(block.list)
	  (/bull/g, block.bullet)
	  ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
	  ('def', '\\n+(?=' + block.def.source + ')')
	  ();

	block.blockquote = replace(block.blockquote)
	  ('def', block.def)
	  ();

	block._tag = '(?!(?:'
	  + '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';

	block.html = replace(block.html)
	  ('comment', /<!--[\s\S]*?-->/)
	  ('closed', /<(tag)[\s\S]+?<\/\1>/)
	  ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
	  (/tag/g, block._tag)
	  ();

	block.paragraph = replace(block.paragraph)
	  ('hr', block.hr)
	  ('heading', block.heading)
	  ('lheading', block.lheading)
	  ('blockquote', block.blockquote)
	  ('tag', '<' + block._tag)
	  ('def', block.def)
	  ();

	/**
	 * Normal Block Grammar
	 */

	block.normal = merge({}, block);

	/**
	 * GFM Block Grammar
	 */

	block.gfm = merge({}, block.normal, {
	  fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
	  paragraph: /^/,
	  heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
	});

	block.gfm.paragraph = replace(block.paragraph)
	  ('(?!', '(?!'
	    + block.gfm.fences.source.replace('\\1', '\\2') + '|'
	    + block.list.source.replace('\\1', '\\3') + '|')
	  ();

	/**
	 * GFM + Tables Block Grammar
	 */

	block.tables = merge({}, block.gfm, {
	  nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
	  table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
	});

	/**
	 * Block Lexer
	 */

	function Lexer(options) {
	  this.tokens = [];
	  this.tokens.links = {};
	  this.options = options || marked.defaults;
	  this.rules = block.normal;

	  if (this.options.gfm) {
	    if (this.options.tables) {
	      this.rules = block.tables;
	    } else {
	      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, bq) {
	  var src = src.replace(/^ +$/gm, '')
	    , next
	    , loose
	    , cap
	    , bull
	    , b
	    , item
	    , space
	    , i
	    , l;

	  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)) {
	      src = src.substring(cap[0].length);
	      cap = cap[0].replace(/^ {4}/gm, '');
	      this.tokens.push({
	        type: 'code',
	        text: !this.options.pedantic
	          ? cap.replace(/\n+$/, '')
	          : cap
	      });
	      continue;
	    }

	    // fences (gfm)
	    if (cap = this.rules.fences.exec(src)) {
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: 'code',
	        lang: 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 (top && (cap = this.rules.nptable.exec(src))) {
	      src = src.substring(cap[0].length);

	      item = {
	        type: 'table',
	        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
	        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
	        cells: cap[3].replace(/\n$/, '').split('\n')
	      };

	      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] = item.cells[i].split(/ *\| */);
	      }

	      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] === '=' ? 1 : 2,
	        text: cap[1]
	      });
	      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, true);

	      this.tokens.push({
	        type: 'blockquote_end'
	      });

	      continue;
	    }

	    // list
	    if (cap = this.rules.list.exec(src)) {
	      src = src.substring(cap[0].length);
	      bull = cap[2];

	      this.tokens.push({
	        type: 'list_start',
	        ordered: bull.length > 1
	      });

	      // Get each top-level item.
	      cap = cap[0].match(this.rules.item);

	      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 (this.options.smartLists && i !== l - 1) {
	          b = block.bullet.exec(cap[i + 1])[0];
	          if (bull !== b && !(bull.length > 1 && b.length > 1)) {
	            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;
	        }

	        this.tokens.push({
	          type: loose
	            ? 'loose_item_start'
	            : 'list_item_start'
	        });

	        // Recurse.
	        this.token(item, false, bq);

	        this.tokens.push({
	          type: 'list_item_end'
	        });
	      }

	      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: cap[0]
	      });
	      continue;
	    }

	    // def
	    if ((!bq && top) && (cap = this.rules.def.exec(src))) {
	      src = src.substring(cap[0].length);
	      this.tokens.links[cap[1].toLowerCase()] = {
	        href: cap[2],
	        title: cap[3]
	      };
	      continue;
	    }

	    // table (gfm)
	    if (top && (cap = this.rules.table.exec(src))) {
	      src = src.substring(cap[0].length);

	      item = {
	        type: 'table',
	        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
	        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
	        cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
	      };

	      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] = item.cells[i]
	          .replace(/^ *\| *| *\| *$/g, '')
	          .split(/ *\| */);
	      }

	      this.tokens.push(item);

	      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: /^<([^ >]+(@|:\/)[^ >]+)>/,
	  url: noop,
	  tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
	  link: /^!?\[(inside)\]\(href\)/,
	  reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
	  nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
	  strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
	  em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
	  code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
	  br: /^ {2,}\n(?!\s*$)/,
	  del: noop,
	  text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
	};

	inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
	inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;

	inline.link = replace(inline.link)
	  ('inside', inline._inside)
	  ('href', inline._href)
	  ();

	inline.reflink = replace(inline.reflink)
	  ('inside', inline._inside)
	  ();

	/**
	 * 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)\*(?!\*)/
	});

	/**
	 * GFM Inline Grammar
	 */

	inline.gfm = merge({}, inline.normal, {
	  escape: replace(inline.escape)('])', '~|])')(),
	  url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
	  del: /^~~(?=\S)([\s\S]*?\S)~~/,
	  text: replace(inline.text)
	    (']|', '~]|')
	    ('|', '|https?://|')
	    ()
	});

	/**
	 * GFM + Line Breaks Inline Grammar
	 */

	inline.breaks = merge({}, inline.gfm, {
	  br: replace(inline.br)('{2,}', '*')(),
	  text: replace(inline.gfm.text)('{2,}', '*')()
	});

	/**
	 * 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.gfm) {
	    if (this.options.breaks) {
	      this.rules = inline.breaks;
	    } else {
	      this.rules = inline.gfm;
	    }
	  } else if (this.options.pedantic) {
	    this.rules = inline.pedantic;
	  }
	}

	/**
	 * 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
	    , cap;

	  while (src) {
	    // escape
	    if (cap = this.rules.escape.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += cap[1];
	      continue;
	    }

	    // autolink
	    if (cap = this.rules.autolink.exec(src)) {
	      src = src.substring(cap[0].length);
	      if (cap[2] === '@') {
	        text = cap[1].charAt(6) === ':'
	          ? this.mangle(cap[1].substring(7))
	          : this.mangle(cap[1]);
	        href = this.mangle('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))) {
	      src = src.substring(cap[0].length);
	      text = escape(cap[1]);
	      href = text;
	      out += this.renderer.link(href, null, text);
	      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;
	      }
	      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)) {
	      src = src.substring(cap[0].length);
	      this.inLink = true;
	      out += this.outputLink(cap, {
	        href: cap[2],
	        title: cap[3]
	      });
	      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[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[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], 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;
	    }

	    // text
	    if (cap = this.rules.text.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += this.renderer.text(escape(this.smartypants(cap[0])));
	      continue;
	    }

	    if (src) {
	      throw new
	        Error('Infinite loop on byte: ' + src.charCodeAt(0));
	    }
	  }

	  return out;
	};

	/**
	 * Compile Link
	 */

	InlineLexer.prototype.outputLink = function(cap, link) {
	  var href = escape(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 || {};
	}

	Renderer.prototype.code = function(code, lang, escaped) {
	  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))
	      + '\n</code></pre>';
	  }

	  return '<pre><code class="'
	    + this.options.langPrefix
	    + escape(lang, true)
	    + '">'
	    + (escaped ? code : escape(code, true))
	    + '\n</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) {
	  return '<h'
	    + level
	    + ' id="'
	    + this.options.headerPrefix
	    + raw.toLowerCase().replace(/[^\w]+/g, '-')
	    + '">'
	    + text
	    + '</h'
	    + level
	    + '>\n';
	};

	Renderer.prototype.hr = function() {
	  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
	};

	Renderer.prototype.list = function(body, ordered) {
	  var type = ordered ? 'ol' : 'ul';
	  return '<' + type + '>\n' + body + '</' + type + '>\n';
	};

	Renderer.prototype.listitem = function(text) {
	  return '<li>' + text + '</li>\n';
	};

	Renderer.prototype.paragraph = function(text) {
	  return '<p>' + text + '</p>\n';
	};

	Renderer.prototype.table = function(header, body) {
	  return '<table>\n'
	    + '<thead>\n'
	    + header
	    + '</thead>\n'
	    + '<tbody>\n'
	    + body
	    + '</tbody>\n'
	    + '</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 + ' style="text-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) {
	  if (this.options.sanitize) {
	    try {
	      var prot = decodeURIComponent(unescape(href))
	        .replace(/[^\w:]/g, '')
	        .toLowerCase();
	    } catch (e) {
	      return '';
	    }
	    if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
	      return '';
	    }
	  }
	  var out = '<a href="' + href + '"';
	  if (title) {
	    out += ' title="' + title + '"';
	  }
	  out += '>' + text + '</a>';
	  return out;
	};

	Renderer.prototype.image = function(href, title, 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;
	};

	/**
	 * 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;
	}

	/**
	 * Static Parse Method
	 */

	Parser.parse = function(src, options, renderer) {
	  var parser = new Parser(options, renderer);
	  return parser.parse(src);
	};

	/**
	 * Parse Loop
	 */

	Parser.prototype.parse = function(src) {
	  this.inline = new InlineLexer(src.links, this.options, this.renderer);
	  this.tokens = src.reverse();

	  var out = '';
	  while (this.next()) {
	    out += this.tok();
	  }

	  return out;
	};

	/**
	 * Next Token
	 */

	Parser.prototype.next = function() {
	  return this.token = this.tokens.pop();
	};

	/**
	 * 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,
	        this.token.text);
	    }
	    case 'code': {
	      return this.renderer.code(this.token.text,
	        this.token.lang,
	        this.token.escaped);
	    }
	    case 'table': {
	      var header = ''
	        , body = ''
	        , i
	        , row
	        , cell
	        , flags
	        , j;

	      // header
	      cell = '';
	      for (i = 0; i < this.token.header.length; i++) {
	        flags = { header: true, align: this.token.align[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': {
	      var body = '';

	      while (this.next().type !== 'blockquote_end') {
	        body += this.tok();
	      }

	      return this.renderer.blockquote(body);
	    }
	    case 'list_start': {
	      var body = ''
	        , ordered = this.token.ordered;

	      while (this.next().type !== 'list_end') {
	        body += this.tok();
	      }

	      return this.renderer.list(body, ordered);
	    }
	    case 'list_item_start': {
	      var body = '';

	      while (this.next().type !== 'list_item_end') {
	        body += this.token.type === 'text'
	          ? this.parseText()
	          : this.tok();
	      }

	      return this.renderer.listitem(body);
	    }
	    case 'loose_item_start': {
	      var body = '';

	      while (this.next().type !== 'list_item_end') {
	        body += this.tok();
	      }

	      return this.renderer.listitem(body);
	    }
	    case 'html': {
	      var html = !this.token.pre && !this.options.pedantic
	        ? this.inline.output(this.token.text)
	        : this.token.text;
	      return this.renderer.html(html);
	    }
	    case 'paragraph': {
	      return this.renderer.paragraph(this.inline.output(this.token.text));
	    }
	    case 'text': {
	      return this.renderer.paragraph(this.parseText());
	    }
	  }
	};

	/**
	 * Helpers
	 */

	function escape(html, encode) {
	  return html
	    .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
	    .replace(/</g, '&lt;')
	    .replace(/>/g, '&gt;')
	    .replace(/"/g, '&quot;')
	    .replace(/'/g, '&#39;');
	}

	function unescape(html) {
		// explicitly match decimal, hex, and named HTML entities 
	  return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, 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 replace(regex, opt) {
	  regex = regex.source;
	  opt = opt || '';
	  return function self(name, val) {
	    if (!name) return new RegExp(regex, opt);
	    val = val.source || val;
	    val = val.replace(/(^|[^\[])\^/g, '$1');
	    regex = regex.replace(name, val);
	    return self;
	  };
	}

	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;
	}


	/**
	 * Marked
	 */

	function marked(src, opt, callback) {
	  if (callback || typeof opt === 'function') {
	    if (!callback) {
	      callback = opt;
	      opt = null;
	    }

	    opt = merge({}, marked.defaults, 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);
	    return Parser.parse(Lexer.lex(src, opt), opt);
	  } catch (e) {
	    e.message += '\nPlease report this to https://github.com/chjj/marked.';
	    if ((opt || marked.defaults).silent) {
	      return '<p>An error occured:</p><pre>'
	        + escape(e.message + '', true)
	        + '</pre>';
	    }
	    throw e;
	  }
	}

	/**
	 * Options
	 */

	marked.options =
	marked.setOptions = function(opt) {
	  merge(marked.defaults, opt);
	  return marked;
	};

	marked.defaults = {
	  gfm: true,
	  tables: true,
	  breaks: false,
	  pedantic: false,
	  sanitize: false,
	  sanitizer: null,
	  mangle: true,
	  smartLists: false,
	  silent: false,
	  highlight: null,
	  langPrefix: 'lang-',
	  smartypants: false,
	  headerPrefix: '',
	  renderer: new Renderer,
	  xhtml: false
	};

	/**
	 * Expose
	 */

	marked.Parser = Parser;
	marked.parser = Parser.parse;

	marked.Renderer = Renderer;

	marked.Lexer = Lexer;
	marked.lexer = Lexer.lex;

	marked.InlineLexer = InlineLexer;
	marked.inlineLexer = InlineLexer.output;

	marked.parse = marked;

	if (true) {
	  module.exports = marked;
	} else if (typeof define === 'function' && define.amd) {
	  define(function() { return marked; });
	} else {
	  this.marked = marked;
	}

	}).call(function() {
	  return this || (typeof window !== 'undefined' ? window : global);
	}());

	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 370 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
		Autosize 3.0.17
		license: MIT
		http://www.jacklmoore.com/autosize
	*/
	(function (global, factory) {
		if (true) {
			!(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports, module], __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 if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
			factory(exports, module);
		} else {
			var mod = {
				exports: {}
			};
			factory(mod.exports, mod);
			global.autosize = mod.exports;
		}
	})(this, function (exports, module) {
		'use strict';

		var set = typeof Set === 'function' ? new Set() : (function () {
			var list = [];

			return {
				has: function has(key) {
					return Boolean(list.indexOf(key) > -1);
				},
				add: function add(key) {
					list.push(key);
				},
				'delete': function _delete(key) {
					list.splice(list.indexOf(key), 1);
				} };
		})();

		var createEvent = function createEvent(name) {
			return new Event(name);
		};
		try {
			new Event('test');
		} catch (e) {
			// IE does not support `new Event()`
			createEvent = function (name) {
				var evt = document.createEvent('Event');
				evt.initEvent(name, true, false);
				return evt;
			};
		}

		function assign(ta) {
			if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || set.has(ta)) return;

			var heightOffset = null;
			var clientWidth = ta.clientWidth;
			var cachedHeight = null;

			function init() {
				var style = window.getComputedStyle(ta, null);

				if (style.resize === 'vertical') {
					ta.style.resize = 'none';
				} else if (style.resize === 'both') {
					ta.style.resize = 'horizontal';
				}

				if (style.boxSizing === 'content-box') {
					heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
				} else {
					heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
				}
				// Fix when a textarea is not on document body and heightOffset is Not a Number
				if (isNaN(heightOffset)) {
					heightOffset = 0;
				}

				update();
			}

			function changeOverflow(value) {
				{
					// Chrome/Safari-specific fix:
					// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
					// made available by removing the scrollbar. The following forces the necessary text reflow.
					var width = ta.style.width;
					ta.style.width = '0px';
					// Force reflow:
					/* jshint ignore:start */
					ta.offsetWidth;
					/* jshint ignore:end */
					ta.style.width = width;
				}

				ta.style.overflowY = value;

				resize();
			}

			function getParentOverflows(el) {
				var arr = [];

				while (el && el.parentNode && el.parentNode instanceof Element) {
					if (el.parentNode.scrollTop) {
						arr.push({
							node: el.parentNode,
							scrollTop: el.parentNode.scrollTop });
					}
					el = el.parentNode;
				}

				return arr;
			}

			function resize() {
				var originalHeight = ta.style.height;
				var overflows = getParentOverflows(ta);
				var docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240)

				ta.style.height = 'auto';

				var endHeight = ta.scrollHeight + heightOffset;

				if (ta.scrollHeight === 0) {
					// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
					ta.style.height = originalHeight;
					return;
				}

				ta.style.height = endHeight + 'px';

				// used to check if an update is actually necessary on window.resize
				clientWidth = ta.clientWidth;

				// prevents scroll-position jumping
				overflows.forEach(function (el) {
					el.node.scrollTop = el.scrollTop;
				});

				if (docTop) {
					document.documentElement.scrollTop = docTop;
				}
			}

			function update() {
				resize();

				var computed = window.getComputedStyle(ta, null);
				var computedHeight = Math.round(parseFloat(computed.height));
				var styleHeight = Math.round(parseFloat(ta.style.height));

				// The computed height not matching the height set via resize indicates that
				// the max-height has been exceeded, in which case the overflow should be set to visible.
				if (computedHeight !== styleHeight) {
					if (computed.overflowY !== 'visible') {
						changeOverflow('visible');
					}
				} else {
					// Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
					if (computed.overflowY !== 'hidden') {
						changeOverflow('hidden');
					}
				}

				if (cachedHeight !== computedHeight) {
					cachedHeight = computedHeight;
					var evt = createEvent('autosize:resized');
					ta.dispatchEvent(evt);
				}
			}

			var pageResize = function pageResize() {
				if (ta.clientWidth !== clientWidth) {
					update();
				}
			};

			var destroy = (function (style) {
				window.removeEventListener('resize', pageResize, false);
				ta.removeEventListener('input', update, false);
				ta.removeEventListener('keyup', update, false);
				ta.removeEventListener('autosize:destroy', destroy, false);
				ta.removeEventListener('autosize:update', update, false);
				set['delete'](ta);

				Object.keys(style).forEach(function (key) {
					ta.style[key] = style[key];
				});
			}).bind(ta, {
				height: ta.style.height,
				resize: ta.style.resize,
				overflowY: ta.style.overflowY,
				overflowX: ta.style.overflowX,
				wordWrap: ta.style.wordWrap });

			ta.addEventListener('autosize:destroy', destroy, false);

			// IE9 does not fire onpropertychange or oninput for deletions,
			// so binding to onkeyup to catch most of those events.
			// There is no way that I know of to detect something like 'cut' in IE9.
			if ('onpropertychange' in ta && 'oninput' in ta) {
				ta.addEventListener('keyup', update, false);
			}

			window.addEventListener('resize', pageResize, false);
			ta.addEventListener('input', update, false);
			ta.addEventListener('autosize:update', update, false);
			set.add(ta);
			ta.style.overflowX = 'hidden';
			ta.style.wordWrap = 'break-word';

			init();
		}

		function destroy(ta) {
			if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
			var evt = createEvent('autosize:destroy');
			ta.dispatchEvent(evt);
		}

		function update(ta) {
			if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
			var evt = createEvent('autosize:update');
			ta.dispatchEvent(evt);
		}

		var autosize = null;

		// Do nothing in Node.js environment and IE8 (or lower)
		if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
			autosize = function (el) {
				return el;
			};
			autosize.destroy = function (el) {
				return el;
			};
			autosize.update = function (el) {
				return el;
			};
		} else {
			autosize = function (el, options) {
				if (el) {
					Array.prototype.forEach.call(el.length ? el : [el], function (x) {
						return assign(x, options);
					});
				}
				return el;
			};
			autosize.destroy = function (el) {
				if (el) {
					Array.prototype.forEach.call(el.length ? el : [el], destroy);
				}
				return el;
			};
			autosize.update = function (el) {
				if (el) {
					Array.prototype.forEach.call(el.length ? el : [el], update);
				}
				return el;
			};
		}

		module.exports = autosize;
	});

/***/ },
/* 371 */
/***/ function(module, exports) {

	'use strict';

	(function RansackForm() {
	  var attrtype, enums, selectb, selectd, selecte, selecti, selects;
	  if ($('.ransack-form').length === 0) {
	    return;
	  }
	  selects = $('.ransack-form').data('selects');
	  selecte = $('.ransack-form').data('selecte');
	  selecti = $('.ransack-form').data('selecti');
	  selectb = $('.ransack-form').data('selectb');
	  selectd = $('.ransack-form').data('selectd');
	  attrtype = $('.ransack-form').data('types');
	  enums = $('rasack-form').data('enums');
	  $('form').on('click', '.remove_fields', function (event) {
	    $(this).closest('.field').remove();
	    return event.preventDefault();
	  });
	  $('form').on('click', '.add_fields', function (event) {
	    var regexp, time;
	    time = new Date().getTime();
	    regexp = new RegExp($(this).data('id'), 'g');
	    $(this).before($(this).data('fields').replace(regexp, time));
	    return event.preventDefault();
	  });
	  $('form').on('change', 'select#predic', function (event) {
	    var type = attrtype[$('form select:first-of-type').val()];
	    if (type === "datetime") type = "date";
	    var cond, valueInput;
	    cond = $(this).val();
	    valueInput = $(this).parent().children('.value-field');

	    if ($.inArray(cond, ['present', 'blank', 'true', 'false', 'null', 'not_null']) >= 0) {
	      valueInput.prop("type", "text");
	      valueInput.val("1");
	      return valueInput.hide();
	    } else {
	      return valueInput.show();
	    }
	  });
	  $('form').on('change', 'select:first-of-type', function (event) {
	    var attributeName, enumselect, getSelectOptions, key, lastField, originValueInputId, originValueInputName, predicateSelect, predicateValue, selectInput, selectInputVal, selectedEnumValue, type, value, valueInput, _results, _results1;
	    getSelectOptions = function getSelectOptions(param, array, originValueInputId) {
	      var i, _i, _len, _results;
	      _results = [];
	      $.each(array, function (key, value) {
	        if (value.toString() === param.toString()) {
	          _results.push($("#" + originValueInputId).append("<option selected='selected' value='" + value + "'>" + key + "</option>"));
	        } else {
	          _results.push($("#" + originValueInputId).append("<option value='" + value + "'>" + key + "</option>"));
	        }
	      });
	      return _results;
	    };

	    attributeName = $(this).val();
	    predicateSelect = $(this).next('select#predic');
	    valueInput = $(this).parent().children('.value-field');
	    selectInput = predicateSelect.next('select');
	    predicateValue = predicateSelect.find('option:selected').val();
	    selectedEnumValue = predicateSelect.next('input').val();
	    type = attrtype[attributeName];
	    originValueInputId = valueInput.attr('id');
	    originValueInputName = valueInput.attr('name');
	    enumselect = $("select#" + originValueInputId).val();
	    lastField = predicateSelect.next('input');
	    predicateSelect.empty();

	    if (type == void 0 || type[0] !== "enum") {
	      predicateSelect.show();
	      predicateSelect.next('select').replaceWith("<input class='form-control value-field' type='text' name=" + originValueInputName + " id=" + originValueInputId + ">");
	    }
	    if (type !== 'date' && type !== 'datetime' && (type == void 0 || type[0] !== "enum")) {
	      lastField.attr('type', 'text');
	    }
	    if (typeof selectInput.val() === "undefined") {
	      selectInputVal = valueInput.val();
	    } else {
	      selectInputVal = selectInput.val();
	    }
	    if (type === 'boolean') {
	      valueInput.hide();
	      valueInput.val("true");
	      _results = [];
	      for (key in selectb) {
	        value = selectb[key];
	        if (key !== predicateValue) {
	          _results.push(predicateSelect.append("<option value='" + key + "'>" + value + "</option>"));
	        } else {
	          _results.push(predicateSelect.append("<option selected='selected' value='" + key + "'>" + value + "</option>"));
	        }
	      }
	      return _results;
	    } else if (type !== void 0 && type[0] === 'enum') {
	      for (key in selecte) {
	        value = selecte[key];
	        if (key === predicateValue) {
	          predicateSelect.append("<option selected='selected' value='" + key + "'>" + value + "</option>");
	        } else {
	          predicateSelect.append("<option value='" + key + "'>" + value + "</option>");
	        }
	      }

	      valueInput.replaceWith("<select class='form-control value-field' id='" + originValueInputId + "' name='" + originValueInputName + "'>");
	      selectInput.replaceWith("<select class='form-control value-field' id='" + originValueInputId + "' name='" + originValueInputName + "'>");
	      if (typeof originValueInputId === "undefined" && typeof originValueInputName === "undefined") {
	        return;
	      }
	      return getSelectOptions(selectInputVal, type[1], originValueInputId);
	    } else if (type === 'date' || type === 'datetime' || type === 'integer') {
	      valueInput.show();
	      for (key in selecti) {
	        value = selecti[key];
	        if (key !== predicateValue) {
	          predicateSelect.append("<option value='" + key + "'>" + value + "</option>");
	        } else {
	          predicateSelect.append("<option selected='selected' value='" + key + "'>" + value + "</option>");
	        }
	      }
	      if (type === 'integer') return predicateSelect.next('input').attr('type', 'integer');else return predicateSelect.next('input').attr('type', 'date');
	    } else {
	      valueInput.show();
	      _results1 = [];
	      for (key in selects) {
	        value = selects[key];
	        if (key !== predicateValue) {
	          _results1.push(predicateSelect.append("<option value='" + key + "'>" + value + "</option>"));
	        } else {
	          _results1.push(predicateSelect.append("<option selected='selected' value='" + key + "'>" + value + "</option>"));
	        }
	      }
	      return _results1;
	    }
	  });
	  return $('select').trigger('change');
	}).call(undefined);

/***/ },
/* 372 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict';

	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

	/*
	 * Chartkick.js
	 * Create beautiful charts with one line of JavaScript
	 * https://github.com/ankane/chartkick.js
	 * v2.3.6
	 * MIT License
	 */

	(function (global, factory) {
	  ( false ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() :  true ? !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : global.Chartkick = factory();
	})(undefined, function () {
	  'use strict';

	  function isArray(variable) {
	    return Object.prototype.toString.call(variable) === "[object Array]";
	  }

	  function isFunction(variable) {
	    return variable instanceof Function;
	  }

	  function isPlainObject(variable) {
	    return !isFunction(variable) && variable instanceof Object;
	  }

	  // https://github.com/madrobby/zepto/blob/master/src/zepto.js
	  function extend(target, source) {
	    var key;
	    for (key in source) {
	      if (isPlainObject(source[key]) || isArray(source[key])) {
	        if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
	          target[key] = {};
	        }
	        if (isArray(source[key]) && !isArray(target[key])) {
	          target[key] = [];
	        }
	        extend(target[key], source[key]);
	      } else if (source[key] !== undefined) {
	        target[key] = source[key];
	      }
	    }
	  }

	  function merge(obj1, obj2) {
	    var target = {};
	    extend(target, obj1);
	    extend(target, obj2);
	    return target;
	  }

	  var DATE_PATTERN = /^(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)$/i;

	  // https://github.com/Do/iso8601.js
	  var ISO8601_PATTERN = /(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([.,]\d+)?($|Z|([+-])(\d\d)(:)?(\d\d)?)/i;
	  var DECIMAL_SEPARATOR = String(1.5).charAt(1);

	  function parseISO8601(input) {
	    var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
	    type = Object.prototype.toString.call(input);
	    if (type === "[object Date]") {
	      return input;
	    }
	    if (type !== "[object String]") {
	      return;
	    }
	    matches = input.match(ISO8601_PATTERN);
	    if (matches) {
	      year = parseInt(matches[1], 10);
	      month = parseInt(matches[3], 10) - 1;
	      day = parseInt(matches[5], 10);
	      hour = parseInt(matches[7], 10);
	      minutes = matches[9] ? parseInt(matches[9], 10) : 0;
	      seconds = matches[11] ? parseInt(matches[11], 10) : 0;
	      milliseconds = matches[12] ? parseFloat(DECIMAL_SEPARATOR + matches[12].slice(1)) * 1000 : 0;
	      result = Date.UTC(year, month, day, hour, minutes, seconds, milliseconds);
	      if (matches[13] && matches[14]) {
	        offset = matches[15] * 60;
	        if (matches[17]) {
	          offset += parseInt(matches[17], 10);
	        }
	        offset *= matches[14] === "-" ? -1 : 1;
	        result -= offset * 60 * 1000;
	      }
	      return new Date(result);
	    }
	  }
	  // end iso8601.js

	  function negativeValues(series) {
	    var i, j, data;
	    for (i = 0; i < series.length; i++) {
	      data = series[i].data;
	      for (j = 0; j < data.length; j++) {
	        if (data[j][1] < 0) {
	          return true;
	        }
	      }
	    }
	    return false;
	  }

	  function toStr(n) {
	    return "" + n;
	  }

	  function toFloat(n) {
	    return parseFloat(n);
	  }

	  function toDate(n) {
	    var matches, year, month, day;
	    if ((typeof n === 'undefined' ? 'undefined' : _typeof(n)) !== "object") {
	      if (typeof n === "number") {
	        n = new Date(n * 1000); // ms
	      } else {
	        n = toStr(n);
	        if (matches = n.match(DATE_PATTERN)) {
	          year = parseInt(matches[1], 10);
	          month = parseInt(matches[3], 10) - 1;
	          day = parseInt(matches[5], 10);
	          return new Date(year, month, day);
	        } else {
	          // str
	          // try our best to get the str into iso8601
	          // TODO be smarter about this
	          var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
	          n = parseISO8601(str) || new Date(n);
	        }
	      }
	    }
	    return n;
	  }

	  function toArr(n) {
	    if (!isArray(n)) {
	      var arr = [],
	          i;
	      for (i in n) {
	        if (n.hasOwnProperty(i)) {
	          arr.push([i, n[i]]);
	        }
	      }
	      n = arr;
	    }
	    return n;
	  }

	  function jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle) {
	    return function (chart, opts, chartOptions) {
	      var series = chart.data;
	      var options = merge({}, defaultOptions);
	      options = merge(options, chartOptions || {});

	      if (chart.hideLegend || "legend" in opts) {
	        hideLegend(options, opts.legend, chart.hideLegend);
	      }

	      if (opts.title) {
	        setTitle(options, opts.title);
	      }

	      // min
	      if ("min" in opts) {
	        setMin(options, opts.min);
	      } else if (!negativeValues(series)) {
	        setMin(options, 0);
	      }

	      // max
	      if (opts.max) {
	        setMax(options, opts.max);
	      }

	      if ("stacked" in opts) {
	        setStacked(options, opts.stacked);
	      }

	      if (opts.colors) {
	        options.colors = opts.colors;
	      }

	      if (opts.xtitle) {
	        setXtitle(options, opts.xtitle);
	      }

	      if (opts.ytitle) {
	        setYtitle(options, opts.ytitle);
	      }

	      // merge library last
	      options = merge(options, opts.library || {});

	      return options;
	    };
	  }

	  function sortByTime(a, b) {
	    return a[0].getTime() - b[0].getTime();
	  }

	  function sortByNumberSeries(a, b) {
	    return a[0] - b[0];
	  }

	  function sortByNumber(a, b) {
	    return a - b;
	  }

	  function isMinute(d) {
	    return d.getMilliseconds() === 0 && d.getSeconds() === 0;
	  }

	  function isHour(d) {
	    return isMinute(d) && d.getMinutes() === 0;
	  }

	  function isDay(d) {
	    return isHour(d) && d.getHours() === 0;
	  }

	  function isWeek(d, dayOfWeek) {
	    return isDay(d) && d.getDay() === dayOfWeek;
	  }

	  function isMonth(d) {
	    return isDay(d) && d.getDate() === 1;
	  }

	  function isYear(d) {
	    return isMonth(d) && d.getMonth() === 0;
	  }

	  function isDate(obj) {
	    return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
	  }

	  function formatValue(pre, value, options) {
	    pre = pre || "";
	    if (options.prefix) {
	      if (value < 0) {
	        value = value * -1;
	        pre += "-";
	      }
	      pre += options.prefix;
	    }

	    if (options.thousands || options.decimal) {
	      value = toStr(value);
	      var parts = value.split(".");
	      value = parts[0];
	      if (options.thousands) {
	        value = value.replace(/\B(?=(\d{3})+(?!\d))/g, options.thousands);
	      }
	      if (parts.length > 1) {
	        value += (options.decimal || ".") + parts[1];
	      }
	    }

	    return pre + value + (options.suffix || "");
	  }

	  function allZeros(data) {
	    var i, j, d;
	    for (i = 0; i < data.length; i++) {
	      d = data[i].data;
	      for (j = 0; j < d.length; j++) {
	        if (d[j][1] != 0) {
	          return false;
	        }
	      }
	    }
	    return true;
	  }

	  var baseOptions = {
	    maintainAspectRatio: false,
	    animation: false,
	    tooltips: {
	      displayColors: false,
	      callbacks: {}
	    },
	    legend: {},
	    title: { fontSize: 20, fontColor: "#333" }
	  };

	  var defaultOptions = {
	    scales: {
	      yAxes: [{
	        ticks: {
	          maxTicksLimit: 4
	        },
	        scaleLabel: {
	          fontSize: 16,
	          // fontStyle: "bold",
	          fontColor: "#333"
	        }
	      }],
	      xAxes: [{
	        gridLines: {
	          drawOnChartArea: false
	        },
	        scaleLabel: {
	          fontSize: 16,
	          // fontStyle: "bold",
	          fontColor: "#333"
	        },
	        time: {},
	        ticks: {}
	      }]
	    }
	  };

	  // http://there4.io/2012/05/02/google-chart-color-list/
	  var defaultColors = ["#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6", "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11", "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"];

	  var hideLegend = function hideLegend(options, legend, _hideLegend) {
	    if (legend !== undefined) {
	      options.legend.display = !!legend;
	      if (legend && legend !== true) {
	        options.legend.position = legend;
	      }
	    } else if (_hideLegend) {
	      options.legend.display = false;
	    }
	  };

	  var setTitle = function setTitle(options, title) {
	    options.title.display = true;
	    options.title.text = title;
	  };

	  var setMin = function setMin(options, min) {
	    if (min !== null) {
	      options.scales.yAxes[0].ticks.min = toFloat(min);
	    }
	  };

	  var setMax = function setMax(options, max) {
	    options.scales.yAxes[0].ticks.max = toFloat(max);
	  };

	  var setBarMin = function setBarMin(options, min) {
	    if (min !== null) {
	      options.scales.xAxes[0].ticks.min = toFloat(min);
	    }
	  };

	  var setBarMax = function setBarMax(options, max) {
	    options.scales.xAxes[0].ticks.max = toFloat(max);
	  };

	  var setStacked = function setStacked(options, stacked) {
	    options.scales.xAxes[0].stacked = !!stacked;
	    options.scales.yAxes[0].stacked = !!stacked;
	  };

	  var setXtitle = function setXtitle(options, title) {
	    options.scales.xAxes[0].scaleLabel.display = true;
	    options.scales.xAxes[0].scaleLabel.labelString = title;
	  };

	  var setYtitle = function setYtitle(options, title) {
	    options.scales.yAxes[0].scaleLabel.display = true;
	    options.scales.yAxes[0].scaleLabel.labelString = title;
	  };

	  // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
	  var addOpacity = function addOpacity(hex, opacity) {
	    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
	    return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
	  };

	  var setLabelSize = function setLabelSize(chart, data, options) {
	    var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
	    if (maxLabelSize > 25) {
	      maxLabelSize = 25;
	    }
	    options.scales.xAxes[0].ticks.callback = function (value) {
	      value = toStr(value);
	      if (value.length > maxLabelSize) {
	        return value.substring(0, maxLabelSize - 2) + "...";
	      } else {
	        return value;
	      }
	    };
	  };

	  var setFormatOptions = function setFormatOptions(chart, options, chartType) {
	    var formatOptions = {
	      prefix: chart.options.prefix,
	      suffix: chart.options.suffix,
	      thousands: chart.options.thousands,
	      decimal: chart.options.decimal
	    };

	    if (formatOptions.prefix || formatOptions.suffix || formatOptions.thousands || formatOptions.decimal) {
	      if (chartType !== "pie") {
	        var myAxes = options.scales.yAxes;
	        if (chartType === "bar") {
	          myAxes = options.scales.xAxes;
	        }

	        if (!myAxes[0].ticks.callback) {
	          myAxes[0].ticks.callback = function (value) {
	            return formatValue("", value, formatOptions);
	          };
	        }
	      }

	      if (!options.tooltips.callbacks.label) {
	        if (chartType !== "pie") {
	          var valueLabel = chartType === "bar" ? "xLabel" : "yLabel";
	          options.tooltips.callbacks.label = function (tooltipItem, data) {
	            var label = data.datasets[tooltipItem.datasetIndex].label || '';
	            if (label) {
	              label += ': ';
	            }
	            return formatValue(label, tooltipItem[valueLabel], formatOptions);
	          };
	        } else {
	          // need to use separate label for pie charts
	          options.tooltips.callbacks.label = function (tooltipItem, data) {
	            var dataLabel = data.labels[tooltipItem.index];
	            var value = ': ';

	            if (isArray(dataLabel)) {
	              // show value on first line of multiline label
	              // need to clone because we are changing the value
	              dataLabel = dataLabel.slice();
	              dataLabel[0] += value;
	            } else {
	              dataLabel += value;
	            }

	            return formatValue(dataLabel, data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index], formatOptions);
	          };
	        }
	      }
	    }
	  };

	  var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);

	  var createDataTable = function createDataTable(chart, options, chartType) {
	    var datasets = [];
	    var labels = [];

	    var colors = chart.options.colors || defaultColors;

	    var day = true;
	    var week = true;
	    var dayOfWeek;
	    var month = true;
	    var year = true;
	    var hour = true;
	    var minute = true;
	    var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;

	    var series = chart.data;

	    var sortedLabels = [];

	    var i,
	        j,
	        s,
	        d,
	        key,
	        rows = [];
	    for (i = 0; i < series.length; i++) {
	      s = series[i];

	      for (j = 0; j < s.data.length; j++) {
	        d = s.data[j];
	        key = detectType ? d[0].getTime() : d[0];
	        if (!rows[key]) {
	          rows[key] = new Array(series.length);
	        }
	        rows[key][i] = toFloat(d[1]);
	        if (sortedLabels.indexOf(key) === -1) {
	          sortedLabels.push(key);
	        }
	      }
	    }

	    if (detectType || chart.options.xtype === "number") {
	      sortedLabels.sort(sortByNumber);
	    }

	    var rows2 = [];
	    for (j = 0; j < series.length; j++) {
	      rows2.push([]);
	    }

	    var value;
	    var k;
	    for (k = 0; k < sortedLabels.length; k++) {
	      i = sortedLabels[k];
	      if (detectType) {
	        value = new Date(toFloat(i));
	        // TODO make this efficient
	        day = day && isDay(value);
	        if (!dayOfWeek) {
	          dayOfWeek = value.getDay();
	        }
	        week = week && isWeek(value, dayOfWeek);
	        month = month && isMonth(value);
	        year = year && isYear(value);
	        hour = hour && isHour(value);
	        minute = minute && isMinute(value);
	      } else {
	        value = i;
	      }
	      labels.push(value);
	      for (j = 0; j < series.length; j++) {
	        // Chart.js doesn't like undefined
	        rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
	      }
	    }

	    for (i = 0; i < series.length; i++) {
	      s = series[i];

	      var color = s.color || colors[i];
	      var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;

	      var dataset = {
	        label: s.name,
	        data: rows2[i],
	        fill: chartType === "area",
	        borderColor: color,
	        backgroundColor: backgroundColor,
	        pointBackgroundColor: color,
	        pointHoverBackgroundColor: color,
	        borderWidth: 2
	      };

	      if (s.stack) {
	        dataset.stack = s.stack;
	      }

	      if (chart.options.curve === false) {
	        dataset.lineTension = 0;
	      }

	      if (chart.options.points === false) {
	        dataset.pointRadius = 0;
	        dataset.pointHitRadius = 5;
	      }

	      dataset = merge(dataset, chart.options.dataset || {});
	      dataset = merge(dataset, s.library || {});
	      dataset = merge(dataset, s.dataset || {});

	      datasets.push(dataset);
	    }

	    if (detectType && labels.length > 0) {
	      var minTime = labels[0].getTime();
	      var maxTime = labels[0].getTime();
	      for (i = 1; i < labels.length; i++) {
	        value = labels[i].getTime();
	        if (value < minTime) {
	          minTime = value;
	        }
	        if (value > maxTime) {
	          maxTime = value;
	        }
	      }

	      var timeDiff = (maxTime - minTime) / (86400 * 1000.0);

	      if (!options.scales.xAxes[0].time.unit) {
	        var step;
	        if (year || timeDiff > 365 * 10) {
	          options.scales.xAxes[0].time.unit = "year";
	          step = 365;
	        } else if (month || timeDiff > 30 * 10) {
	          options.scales.xAxes[0].time.unit = "month";
	          step = 30;
	        } else if (day || timeDiff > 10) {
	          options.scales.xAxes[0].time.unit = "day";
	          step = 1;
	        } else if (hour || timeDiff > 0.5) {
	          options.scales.xAxes[0].time.displayFormats = { hour: "MMM D, h a" };
	          options.scales.xAxes[0].time.unit = "hour";
	          step = 1 / 24.0;
	        } else if (minute) {
	          options.scales.xAxes[0].time.displayFormats = { minute: "h:mm a" };
	          options.scales.xAxes[0].time.unit = "minute";
	          step = 1 / 24.0 / 60.0;
	        }

	        if (step && timeDiff > 0) {
	          var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
	          if (week && step === 1) {
	            unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
	          }
	          options.scales.xAxes[0].time.unitStepSize = unitStepSize;
	        }
	      }

	      if (!options.scales.xAxes[0].time.tooltipFormat) {
	        if (day) {
	          options.scales.xAxes[0].time.tooltipFormat = "ll";
	        } else if (hour) {
	          options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
	        } else if (minute) {
	          options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
	        }
	      }
	    }

	    var data = {
	      labels: labels,
	      datasets: datasets
	    };

	    return data;
	  };

	  var defaultExport = function defaultExport(library) {
	    this.name = "chartjs";
	    this.library = library;
	  };

	  defaultExport.prototype.renderLineChart = function renderLineChart(chart, chartType) {
	    if (chart.options.xtype === "number") {
	      return this.renderScatterChart(chart, chartType, true);
	    }

	    var chartOptions = {};
	    // fix for https://github.com/chartjs/Chart.js/issues/2441
	    if (!chart.options.max && allZeros(chart.data)) {
	      chartOptions.max = 1;
	    }

	    var options = jsOptions(chart, merge(chartOptions, chart.options));
	    setFormatOptions(chart, options, chartType);

	    var data = createDataTable(chart, options, chartType || "line");

	    options.scales.xAxes[0].type = chart.discrete ? "category" : "time";

	    this.drawChart(chart, "line", data, options);
	  };

	  defaultExport.prototype.renderPieChart = function renderPieChart(chart) {
	    var options = merge({}, baseOptions);
	    if (chart.options.donut) {
	      options.cutoutPercentage = 50;
	    }

	    if ("legend" in chart.options) {
	      hideLegend(options, chart.options.legend);
	    }

	    if (chart.options.title) {
	      setTitle(options, chart.options.title);
	    }

	    options = merge(options, chart.options.library || {});
	    setFormatOptions(chart, options, "pie");

	    var labels = [];
	    var values = [];
	    for (var i = 0; i < chart.data.length; i++) {
	      var point = chart.data[i];
	      labels.push(point[0]);
	      values.push(point[1]);
	    }

	    var dataset = {
	      data: values,
	      backgroundColor: chart.options.colors || defaultColors
	    };
	    dataset = merge(dataset, chart.options.dataset || {});

	    var data = {
	      labels: labels,
	      datasets: [dataset]
	    };

	    this.drawChart(chart, "pie", data, options);
	  };

	  defaultExport.prototype.renderColumnChart = function renderColumnChart(chart, chartType) {
	    var options;
	    if (chartType === "bar") {
	      options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
	    } else {
	      options = jsOptions(chart, chart.options);
	    }
	    setFormatOptions(chart, options, chartType);
	    var data = createDataTable(chart, options, "column");
	    if (chartType !== "bar") {
	      setLabelSize(chart, data, options);
	    }
	    this.drawChart(chart, chartType === "bar" ? "horizontalBar" : "bar", data, options);
	  };

	  defaultExport.prototype.renderAreaChart = function renderAreaChart(chart) {
	    this.renderLineChart(chart, "area");
	  };

	  defaultExport.prototype.renderBarChart = function renderBarChart(chart) {
	    this.renderColumnChart(chart, "bar");
	  };

	  defaultExport.prototype.renderScatterChart = function renderScatterChart(chart, chartType, lineChart) {
	    chartType = chartType || "line";

	    var options = jsOptions(chart, chart.options);
	    if (!lineChart) {
	      setFormatOptions(chart, options, chartType);
	    }

	    var colors = chart.options.colors || defaultColors;

	    var datasets = [];
	    var series = chart.data;
	    for (var i = 0; i < series.length; i++) {
	      var s = series[i];
	      var d = [];
	      for (var j = 0; j < s.data.length; j++) {
	        var point = {
	          x: toFloat(s.data[j][0]),
	          y: toFloat(s.data[j][1])
	        };
	        if (chartType === "bubble") {
	          point.r = toFloat(s.data[j][2]);
	        }
	        d.push(point);
	      }

	      var color = s.color || colors[i];
	      var backgroundColor = chartType === "area" ? addOpacity(color, 0.5) : color;

	      datasets.push({
	        label: s.name,
	        showLine: lineChart || false,
	        data: d,
	        borderColor: color,
	        backgroundColor: backgroundColor,
	        pointBackgroundColor: color,
	        fill: chartType === "area"
	      });
	    }

	    if (chartType === "area") {
	      chartType = "line";
	    }

	    var data = { datasets: datasets };

	    options.scales.xAxes[0].type = "linear";
	    options.scales.xAxes[0].position = "bottom";

	    this.drawChart(chart, chartType, data, options);
	  };

	  defaultExport.prototype.renderBubbleChart = function renderBubbleChart(chart) {
	    this.renderScatterChart(chart, "bubble");
	  };

	  defaultExport.prototype.destroy = function destroy(chart) {
	    if (chart.chart) {
	      chart.chart.destroy();
	    }
	  };

	  defaultExport.prototype.drawChart = function drawChart(chart, type, data, options) {
	    this.destroy(chart);

	    chart.element.innerHTML = "<canvas></canvas>";
	    var ctx = chart.element.getElementsByTagName("CANVAS")[0];
	    chart.chart = new this.library(ctx, {
	      type: type,
	      data: data,
	      options: options
	    });
	  };

	  var defaultOptions$1 = {
	    chart: {},
	    xAxis: {
	      title: {
	        text: null
	      },
	      labels: {
	        style: {
	          fontSize: "12px"
	        }
	      }
	    },
	    yAxis: {
	      title: {
	        text: null
	      },
	      labels: {
	        style: {
	          fontSize: "12px"
	        }
	      }
	    },
	    title: {
	      text: null
	    },
	    credits: {
	      enabled: false
	    },
	    legend: {
	      borderWidth: 0
	    },
	    tooltip: {
	      style: {
	        fontSize: "12px"
	      }
	    },
	    plotOptions: {
	      areaspline: {},
	      series: {
	        marker: {}
	      }
	    }
	  };

	  var hideLegend$1 = function hideLegend$1(options, legend, hideLegend) {
	    if (legend !== undefined) {
	      options.legend.enabled = !!legend;
	      if (legend && legend !== true) {
	        if (legend === "top" || legend === "bottom") {
	          options.legend.verticalAlign = legend;
	        } else {
	          options.legend.layout = "vertical";
	          options.legend.verticalAlign = "middle";
	          options.legend.align = legend;
	        }
	      }
	    } else if (hideLegend) {
	      options.legend.enabled = false;
	    }
	  };

	  var setTitle$1 = function setTitle$1(options, title) {
	    options.title.text = title;
	  };

	  var setMin$1 = function setMin$1(options, min) {
	    options.yAxis.min = min;
	  };

	  var setMax$1 = function setMax$1(options, max) {
	    options.yAxis.max = max;
	  };

	  var setStacked$1 = function setStacked$1(options, stacked) {
	    options.plotOptions.series.stacking = stacked ? stacked === true ? "normal" : stacked : null;
	  };

	  var setXtitle$1 = function setXtitle$1(options, title) {
	    options.xAxis.title.text = title;
	  };

	  var setYtitle$1 = function setYtitle$1(options, title) {
	    options.yAxis.title.text = title;
	  };

	  var jsOptions$1 = jsOptionsFunc(defaultOptions$1, hideLegend$1, setTitle$1, setMin$1, setMax$1, setStacked$1, setXtitle$1, setYtitle$1);

	  var setFormatOptions$1 = function setFormatOptions$1(chart, options, chartType) {
	    var formatOptions = {
	      prefix: chart.options.prefix,
	      suffix: chart.options.suffix,
	      thousands: chart.options.thousands,
	      decimal: chart.options.decimal
	    };

	    if (formatOptions.prefix || formatOptions.suffix || formatOptions.thousands || formatOptions.decimal) {
	      if (chartType !== "pie" && !options.yAxis.labels.formatter) {
	        options.yAxis.labels.formatter = function () {
	          return formatValue("", this.value, formatOptions);
	        };
	      }

	      if (!options.tooltip.pointFormatter) {
	        options.tooltip.pointFormatter = function () {
	          return '<span style="color:' + this.color + '>\u25CF</span> ' + formatValue(this.series.name + ': <b>', this.y, formatOptions) + '</b><br/>';
	        };
	      }
	    }
	  };

	  var defaultExport$1 = function defaultExport(library) {
	    this.name = "highcharts";
	    this.library = library;
	  };

	  defaultExport$1.prototype.renderLineChart = function renderLineChart(chart, chartType) {
	    chartType = chartType || "spline";
	    var chartOptions = {};
	    if (chartType === "areaspline") {
	      chartOptions = {
	        plotOptions: {
	          areaspline: {
	            stacking: "normal"
	          },
	          area: {
	            stacking: "normal"
	          },
	          series: {
	            marker: {
	              enabled: false
	            }
	          }
	        }
	      };
	    }

	    if (chart.options.curve === false) {
	      if (chartType === "areaspline") {
	        chartType = "area";
	      } else if (chartType === "spline") {
	        chartType = "line";
	      }
	    }

	    var options = jsOptions$1(chart, chart.options, chartOptions),
	        data,
	        i,
	        j;
	    options.xAxis.type = chart.discrete ? "category" : "datetime";
	    if (!options.chart.type) {
	      options.chart.type = chartType;
	    }
	    setFormatOptions$1(chart, options, chartType);

	    var series = chart.data;
	    for (i = 0; i < series.length; i++) {
	      data = series[i].data;
	      if (!chart.discrete) {
	        for (j = 0; j < data.length; j++) {
	          data[j][0] = data[j][0].getTime();
	        }
	      }
	      series[i].marker = { symbol: "circle" };
	      if (chart.options.points === false) {
	        series[i].marker.enabled = false;
	      }
	    }

	    this.drawChart(chart, series, options);
	  };

	  defaultExport$1.prototype.renderScatterChart = function renderScatterChart(chart) {
	    var options = jsOptions$1(chart, chart.options, {});
	    options.chart.type = "scatter";
	    this.drawChart(chart, chart.data, options);
	  };

	  defaultExport$1.prototype.renderPieChart = function renderPieChart(chart) {
	    var chartOptions = merge(defaultOptions$1, {});

	    if (chart.options.colors) {
	      chartOptions.colors = chart.options.colors;
	    }
	    if (chart.options.donut) {
	      chartOptions.plotOptions = { pie: { innerSize: "50%" } };
	    }

	    if ("legend" in chart.options) {
	      hideLegend$1(chartOptions, chart.options.legend);
	    }

	    if (chart.options.title) {
	      setTitle$1(chartOptions, chart.options.title);
	    }

	    var options = merge(chartOptions, chart.options.library || {});
	    setFormatOptions$1(chart, options, "pie");
	    var series = [{
	      type: "pie",
	      name: chart.options.label || "Value",
	      data: chart.data
	    }];

	    this.drawChart(chart, series, options);
	  };

	  defaultExport$1.prototype.renderColumnChart = function renderColumnChart(chart, chartType) {
	    chartType = chartType || "column";
	    var series = chart.data;
	    var options = jsOptions$1(chart, chart.options),
	        i,
	        j,
	        s,
	        d,
	        rows = [],
	        categories = [];
	    options.chart.type = chartType;
	    setFormatOptions$1(chart, options, chartType);

	    for (i = 0; i < series.length; i++) {
	      s = series[i];

	      for (j = 0; j < s.data.length; j++) {
	        d = s.data[j];
	        if (!rows[d[0]]) {
	          rows[d[0]] = new Array(series.length);
	          categories.push(d[0]);
	        }
	        rows[d[0]][i] = d[1];
	      }
	    }

	    if (chart.options.xtype === "number") {
	      categories.sort(sortByNumber);
	    }

	    options.xAxis.categories = categories;

	    var newSeries = [],
	        d2;
	    for (i = 0; i < series.length; i++) {
	      d = [];
	      for (j = 0; j < categories.length; j++) {
	        d.push(rows[categories[j]][i] || 0);
	      }

	      d2 = {
	        name: series[i].name,
	        data: d
	      };
	      if (series[i].stack) {
	        d2.stack = series[i].stack;
	      }

	      newSeries.push(d2);
	    }

	    this.drawChart(chart, newSeries, options);
	  };

	  defaultExport$1.prototype.renderBarChart = function renderBarChart(chart) {
	    this.renderColumnChart(chart, "bar");
	  };

	  defaultExport$1.prototype.renderAreaChart = function renderAreaChart(chart) {
	    this.renderLineChart(chart, "areaspline");
	  };

	  defaultExport$1.prototype.destroy = function destroy(chart) {
	    if (chart.chart) {
	      chart.chart.destroy();
	    }
	  };

	  defaultExport$1.prototype.drawChart = function drawChart(chart, data, options) {
	    this.destroy(chart);

	    options.chart.renderTo = chart.element.id;
	    options.series = data;
	    chart.chart = new this.library.Chart(options);
	  };

	  var loaded = {};
	  var callbacks = [];

	  // Set chart options
	  var defaultOptions$2 = {
	    chartArea: {},
	    fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
	    pointSize: 6,
	    legend: {
	      textStyle: {
	        fontSize: 12,
	        color: "#444"
	      },
	      alignment: "center",
	      position: "right"
	    },
	    curveType: "function",
	    hAxis: {
	      textStyle: {
	        color: "#666",
	        fontSize: 12
	      },
	      titleTextStyle: {},
	      gridlines: {
	        color: "transparent"
	      },
	      baselineColor: "#ccc",
	      viewWindow: {}
	    },
	    vAxis: {
	      textStyle: {
	        color: "#666",
	        fontSize: 12
	      },
	      titleTextStyle: {},
	      baselineColor: "#ccc",
	      viewWindow: {}
	    },
	    tooltip: {
	      textStyle: {
	        color: "#666",
	        fontSize: 12
	      }
	    }
	  };

	  var hideLegend$2 = function hideLegend$2(options, legend, hideLegend) {
	    if (legend !== undefined) {
	      var position;
	      if (!legend) {
	        position = "none";
	      } else if (legend === true) {
	        position = "right";
	      } else {
	        position = legend;
	      }
	      options.legend.position = position;
	    } else if (hideLegend) {
	      options.legend.position = "none";
	    }
	  };

	  var setTitle$2 = function setTitle$2(options, title) {
	    options.title = title;
	    options.titleTextStyle = { color: "#333", fontSize: "20px" };
	  };

	  var setMin$2 = function setMin$2(options, min) {
	    options.vAxis.viewWindow.min = min;
	  };

	  var setMax$2 = function setMax$2(options, max) {
	    options.vAxis.viewWindow.max = max;
	  };

	  var setBarMin$1 = function setBarMin$1(options, min) {
	    options.hAxis.viewWindow.min = min;
	  };

	  var setBarMax$1 = function setBarMax$1(options, max) {
	    options.hAxis.viewWindow.max = max;
	  };

	  var setStacked$2 = function setStacked$2(options, stacked) {
	    options.isStacked = stacked ? stacked : false;
	  };

	  var setXtitle$2 = function setXtitle$2(options, title) {
	    options.hAxis.title = title;
	    options.hAxis.titleTextStyle.italic = false;
	  };

	  var setYtitle$2 = function setYtitle$2(options, title) {
	    options.vAxis.title = title;
	    options.vAxis.titleTextStyle.italic = false;
	  };

	  var jsOptions$2 = jsOptionsFunc(defaultOptions$2, hideLegend$2, setTitle$2, setMin$2, setMax$2, setStacked$2, setXtitle$2, setYtitle$2);

	  var resize = function resize(callback) {
	    if (window.attachEvent) {
	      window.attachEvent("onresize", callback);
	    } else if (window.addEventListener) {
	      window.addEventListener("resize", callback, true);
	    }
	    callback();
	  };

	  var defaultExport$2 = function defaultExport(library) {
	    this.name = "google";
	    this.library = library;
	  };

	  defaultExport$2.prototype.renderLineChart = function renderLineChart(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, function () {
	      var chartOptions = {};

	      if (chart.options.curve === false) {
	        chartOptions.curveType = "none";
	      }

	      if (chart.options.points === false) {
	        chartOptions.pointSize = 0;
	      }

	      var options = jsOptions$2(chart, chart.options, chartOptions);
	      var columnType = chart.discrete ? "string" : "datetime";
	      if (chart.options.xtype === "number") {
	        columnType = "number";
	      }
	      var data = this$1.createDataTable(chart.data, columnType);

	      this$1.drawChart(chart, this$1.library.visualization.LineChart, data, options);
	    });
	  };

	  defaultExport$2.prototype.renderPieChart = function renderPieChart(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, function () {
	      var chartOptions = {
	        chartArea: {
	          top: "10%",
	          height: "80%"
	        },
	        legend: {}
	      };
	      if (chart.options.colors) {
	        chartOptions.colors = chart.options.colors;
	      }
	      if (chart.options.donut) {
	        chartOptions.pieHole = 0.5;
	      }
	      if ("legend" in chart.options) {
	        hideLegend$2(chartOptions, chart.options.legend);
	      }
	      if (chart.options.title) {
	        setTitle$2(chartOptions, chart.options.title);
	      }
	      var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});

	      var data = new this$1.library.visualization.DataTable();
	      data.addColumn("string", "");
	      data.addColumn("number", "Value");
	      data.addRows(chart.data);

	      this$1.drawChart(chart, this$1.library.visualization.PieChart, data, options);
	    });
	  };

	  defaultExport$2.prototype.renderColumnChart = function renderColumnChart(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, function () {
	      var options = jsOptions$2(chart, chart.options);
	      var data = this$1.createDataTable(chart.data, "string", chart.options.xtype);

	      this$1.drawChart(chart, this$1.library.visualization.ColumnChart, data, options);
	    });
	  };

	  defaultExport$2.prototype.renderBarChart = function renderBarChart(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, function () {
	      var chartOptions = {
	        hAxis: {
	          gridlines: {
	            color: "#ccc"
	          }
	        }
	      };
	      var options = jsOptionsFunc(defaultOptions$2, hideLegend$2, setTitle$2, setBarMin$1, setBarMax$1, setStacked$2, setXtitle$2, setYtitle$2)(chart, chart.options, chartOptions);
	      var data = this$1.createDataTable(chart.data, "string", chart.options.xtype);

	      this$1.drawChart(chart, this$1.library.visualization.BarChart, data, options);
	    });
	  };

	  defaultExport$2.prototype.renderAreaChart = function renderAreaChart(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, function () {
	      var chartOptions = {
	        isStacked: true,
	        pointSize: 0,
	        areaOpacity: 0.5
	      };

	      var options = jsOptions$2(chart, chart.options, chartOptions);
	      var columnType = chart.discrete ? "string" : "datetime";
	      if (chart.options.xtype === "number") {
	        columnType = "number";
	      }
	      var data = this$1.createDataTable(chart.data, columnType);

	      this$1.drawChart(chart, this$1.library.visualization.AreaChart, data, options);
	    });
	  };

	  defaultExport$2.prototype.renderGeoChart = function renderGeoChart(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, function () {
	      var chartOptions = {
	        legend: "none",
	        colorAxis: {
	          colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
	        }
	      };
	      var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});

	      var data = new this$1.library.visualization.DataTable();
	      data.addColumn("string", "");
	      data.addColumn("number", chart.options.label || "Value");
	      data.addRows(chart.data);

	      this$1.drawChart(chart, this$1.library.visualization.GeoChart, data, options);
	    });
	  };

	  defaultExport$2.prototype.renderScatterChart = function renderScatterChart(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, function () {
	      var chartOptions = {};
	      var options = jsOptions$2(chart, chart.options, chartOptions);

	      var series = chart.data,
	          rows2 = [],
	          i,
	          j,
	          data,
	          d;
	      for (i = 0; i < series.length; i++) {
	        d = series[i].data;
	        for (j = 0; j < d.length; j++) {
	          var row = new Array(series.length + 1);
	          row[0] = d[j][0];
	          row[i + 1] = d[j][1];
	          rows2.push(row);
	        }
	      }

	      data = new this$1.library.visualization.DataTable();
	      data.addColumn("number", "");
	      for (i = 0; i < series.length; i++) {
	        data.addColumn("number", series[i].name);
	      }
	      data.addRows(rows2);

	      this$1.drawChart(chart, this$1.library.visualization.ScatterChart, data, options);
	    });
	  };

	  defaultExport$2.prototype.renderTimeline = function renderTimeline(chart) {
	    var this$1 = this;

	    this.waitForLoaded(chart, "timeline", function () {
	      var chartOptions = {
	        legend: "none"
	      };

	      if (chart.options.colors) {
	        chartOptions.colors = chart.options.colors;
	      }
	      var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});

	      var data = new this$1.library.visualization.DataTable();
	      data.addColumn({ type: "string", id: "Name" });
	      data.addColumn({ type: "date", id: "Start" });
	      data.addColumn({ type: "date", id: "End" });
	      data.addRows(chart.data);

	      chart.element.style.lineHeight = "normal";

	      this$1.drawChart(chart, this$1.library.visualization.Timeline, data, options);
	    });
	  };

	  defaultExport$2.prototype.destroy = function destroy(chart) {
	    if (chart.chart) {
	      chart.chart.clearChart();
	    }
	  };

	  defaultExport$2.prototype.drawChart = function drawChart(chart, type, data, options) {
	    this.destroy(chart);

	    chart.chart = new type(chart.element);
	    resize(function () {
	      chart.chart.draw(data, options);
	    });
	  };

	  defaultExport$2.prototype.waitForLoaded = function waitForLoaded(chart, pack, callback) {
	    var this$1 = this;

	    if (!callback) {
	      callback = pack;
	      pack = "corechart";
	    }

	    callbacks.push({ pack: pack, callback: callback });

	    if (loaded[pack]) {
	      this.runCallbacks();
	    } else {
	      loaded[pack] = true;

	      // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
	      var loadOptions = {
	        packages: [pack],
	        callback: function callback() {
	          this$1.runCallbacks();
	        }
	      };
	      var config = chart.__config();
	      if (config.language) {
	        loadOptions.language = config.language;
	      }
	      if (pack === "corechart" && config.mapsApiKey) {
	        loadOptions.mapsApiKey = config.mapsApiKey;
	      }

	      if (this.library.setOnLoadCallback) {
	        this.library.load("visualization", "1", loadOptions);
	      } else {
	        this.library.charts.load("current", loadOptions);
	      }
	    }
	  };

	  defaultExport$2.prototype.runCallbacks = function runCallbacks() {
	    var this$1 = this;

	    var cb, call;
	    for (var i = 0; i < callbacks.length; i++) {
	      cb = callbacks[i];
	      call = this$1.library.visualization && (cb.pack === "corechart" && this$1.library.visualization.LineChart || cb.pack === "timeline" && this$1.library.visualization.Timeline);
	      if (call) {
	        cb.callback();
	        callbacks.splice(i, 1);
	        i--;
	      }
	    }
	  };

	  // cant use object as key
	  defaultExport$2.prototype.createDataTable = function createDataTable(series, columnType, xtype) {
	    var i,
	        j,
	        s,
	        d,
	        key,
	        rows = [],
	        sortedLabels = [];
	    for (i = 0; i < series.length; i++) {
	      s = series[i];

	      for (j = 0; j < s.data.length; j++) {
	        d = s.data[j];
	        key = columnType === "datetime" ? d[0].getTime() : d[0];
	        if (!rows[key]) {
	          rows[key] = new Array(series.length);
	          sortedLabels.push(key);
	        }
	        rows[key][i] = toFloat(d[1]);
	      }
	    }

	    var rows2 = [];
	    var day = true;
	    var value;
	    for (j = 0; j < sortedLabels.length; j++) {
	      i = sortedLabels[j];
	      if (columnType === "datetime") {
	        value = new Date(toFloat(i));
	        day = day && isDay(value);
	      } else if (columnType === "number") {
	        value = toFloat(i);
	      } else {
	        value = i;
	      }
	      rows2.push([value].concat(rows[i]));
	    }
	    if (columnType === "datetime") {
	      rows2.sort(sortByTime);
	    } else if (columnType === "number") {
	      rows2.sort(sortByNumberSeries);
	    }

	    if (xtype === "number") {
	      rows2.sort(sortByNumberSeries);

	      for (i = 0; i < rows2.length; i++) {
	        rows2[i][0] = toStr(rows2[i][0]);
	      }
	    }

	    // create datatable
	    var data = new this.library.visualization.DataTable();
	    columnType = columnType === "datetime" && day ? "date" : columnType;
	    data.addColumn(columnType, "");
	    for (i = 0; i < series.length; i++) {
	      data.addColumn("number", series[i].name);
	    }
	    data.addRows(rows2);

	    return data;
	  };

	  var pendingRequests = [],
	      runningRequests = 0,
	      maxRequests = 4;

	  function pushRequest(url, success, error) {
	    pendingRequests.push([url, success, error]);
	    runNext();
	  }

	  function runNext() {
	    if (runningRequests < maxRequests) {
	      var request = pendingRequests.shift();
	      if (request) {
	        runningRequests++;
	        getJSON(request[0], request[1], request[2]);
	        runNext();
	      }
	    }
	  }

	  function requestComplete() {
	    runningRequests--;
	    runNext();
	  }

	  function getJSON(url, success, error) {
	    ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
	      var message = typeof errorThrown === "string" ? errorThrown : errorThrown.message;
	      error(message);
	    });
	  }

	  function ajaxCall(url, success, error) {
	    var $ = window.jQuery || window.Zepto || window.$;

	    if ($) {
	      $.ajax({
	        dataType: "json",
	        url: url,
	        success: success,
	        error: error,
	        complete: requestComplete
	      });
	    } else {
	      var xhr = new XMLHttpRequest();
	      xhr.open("GET", url, true);
	      xhr.setRequestHeader("Content-Type", "application/json");
	      xhr.onload = function () {
	        requestComplete();
	        if (xhr.status === 200) {
	          success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
	        } else {
	          error(xhr, "error", xhr.statusText);
	        }
	      };
	      xhr.send();
	    }
	  }

	  var config = typeof window !== "undefined" && window.Chartkick || {};
	  var adapters = [];

	  // helpers

	  function setText(element, text) {
	    if (document.body.innerText) {
	      element.innerText = text;
	    } else {
	      element.textContent = text;
	    }
	  }

	  function chartError(element, message) {
	    setText(element, "Error Loading Chart: " + message);
	    element.style.color = "#ff0000";
	  }

	  function errorCatcher(chart) {
	    try {
	      chart.__render();
	    } catch (err) {
	      chartError(chart.element, err.message);
	      throw err;
	    }
	  }

	  function fetchDataSource(chart, dataSource) {
	    if (typeof dataSource === "string") {
	      pushRequest(dataSource, function (data) {
	        chart.rawData = data;
	        errorCatcher(chart);
	      }, function (message) {
	        chartError(chart.element, message);
	      });
	    } else {
	      chart.rawData = dataSource;
	      errorCatcher(chart);
	    }
	  }

	  function addDownloadButton(chart) {
	    var element = chart.element;
	    var link = document.createElement("a");
	    link.download = chart.options.download === true ? "chart.png" : chart.options.download; // http://caniuse.com/download
	    link.style.position = "absolute";
	    link.style.top = "20px";
	    link.style.right = "20px";
	    link.style.zIndex = 1000;
	    link.style.lineHeight = "20px";
	    link.target = "_blank"; // for safari
	    var image = document.createElement("img");
	    image.alt = "Download";
	    image.style.border = "none";
	    // icon from font-awesome
	    // http://fa2png.io/
	    image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABCFBMVEUAAADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMywEsqxAAAAV3RSTlMAAQIDBggJCgsMDQ4PERQaHB0eISIjJCouLzE0OTo/QUJHSUpLTU5PUllhYmltcHh5foWLjI+SlaCio6atr7S1t7m6vsHHyM7R2tze5Obo7fHz9ff5+/1hlxK2AAAA30lEQVQYGUXBhVYCQQBA0TdYWAt2d3d3YWAHyur7/z9xgD16Lw0DW+XKx+1GgX+FRzM3HWQWrHl5N/oapW5RPe0PkBu+UYeICvozTWZVK23Ao04B79oJrOsJDOoxkZoQPWgX29pHpCZEk7rEvQYiNSFq1UMqvlCjJkRBS1R8hb00Vb/TajtBL7nTHE1X1vyMQF732dQhyF2o6SAwrzP06iUQzvwsArlnzcOdrgBhJyHa1QOgO9U1GsKuvjUTjavliZYQ8nNPapG6sap/3nrIdJ6bOWzmX/fy0XVpfzZP3S8OJT3g9EEiJwAAAABJRU5ErkJggg==";
	    link.appendChild(image);
	    element.style.position = "relative";

	    chart.__downloadAttached = true;

	    // mouseenter
	    chart.__enterEvent = addEvent(element, "mouseover", function (e) {
	      var related = e.relatedTarget;
	      // check download option again to ensure it wasn't changed
	      if ((!related || related !== this && !childOf(this, related)) && chart.options.download) {
	        link.href = chart.toImage();
	        element.appendChild(link);
	      }
	    });

	    // mouseleave
	    chart.__leaveEvent = addEvent(element, "mouseout", function (e) {
	      var related = e.relatedTarget;
	      if (!related || related !== this && !childOf(this, related)) {
	        if (link.parentNode) {
	          link.parentNode.removeChild(link);
	        }
	      }
	    });
	  }

	  // http://stackoverflow.com/questions/10149963/adding-event-listener-cross-browser
	  function addEvent(elem, event, fn) {
	    if (elem.addEventListener) {
	      elem.addEventListener(event, fn, false);
	      return fn;
	    } else {
	      var fn2 = function fn2() {
	        // set the this pointer same as addEventListener when fn is called
	        return fn.call(elem, window.event);
	      };
	      elem.attachEvent("on" + event, fn2);
	      return fn2;
	    }
	  }

	  function removeEvent(elem, event, fn) {
	    if (elem.removeEventListener) {
	      elem.removeEventListener(event, fn, false);
	    } else {
	      elem.detachEvent("on" + event, fn);
	    }
	  }

	  // https://gist.github.com/shawnbot/4166283
	  function childOf(p, c) {
	    if (p === c) {
	      return false;
	    }
	    while (c && c !== p) {
	      c = c.parentNode;
	    }
	    return c === p;
	  }

	  function getAdapterType(library) {
	    if (library) {
	      if (library.product === "Highcharts") {
	        return defaultExport$1;
	      } else if (library.setOnLoadCallback || library.charts) {
	        return defaultExport$2;
	      } else if (isFunction(library)) {
	        return defaultExport;
	      }
	    }
	    throw new Error("Unknown adapter");
	  }

	  function addAdapter(library) {
	    var adapterType = getAdapterType(library);
	    var adapter = new adapterType(library);

	    if (adapters.indexOf(adapter) === -1) {
	      adapters.push(adapter);
	    }
	  }

	  function loadAdapters() {
	    if ("Chart" in window) {
	      addAdapter(window.Chart);
	    }

	    if ("Highcharts" in window) {
	      addAdapter(window.Highcharts);
	    }

	    if (window.google && (window.google.setOnLoadCallback || window.google.charts)) {
	      addAdapter(window.google);
	    }
	  }

	  function dataEmpty(data, chartType) {
	    if (chartType === "PieChart" || chartType === "GeoChart" || chartType === "Timeline") {
	      return data.length === 0;
	    } else {
	      for (var i = 0; i < data.length; i++) {
	        if (data[i].data.length > 0) {
	          return false;
	        }
	      }
	      return true;
	    }
	  }

	  function renderChart(chartType, chart) {
	    if (chart.options.messages && chart.options.messages.empty && dataEmpty(chart.data, chartType)) {
	      setText(chart.element, chart.options.messages.empty);
	    } else {
	      callAdapter(chartType, chart);
	      if (chart.options.download && !chart.__downloadAttached && chart.adapter === "chartjs") {
	        addDownloadButton(chart);
	      }
	    }
	  }

	  // TODO remove chartType if cross-browser way
	  // to get the name of the chart class
	  function callAdapter(chartType, chart) {
	    var i, adapter, fnName, adapterName;
	    fnName = "render" + chartType;
	    adapterName = chart.options.adapter;

	    loadAdapters();

	    for (i = 0; i < adapters.length; i++) {
	      adapter = adapters[i];
	      if ((!adapterName || adapterName === adapter.name) && isFunction(adapter[fnName])) {
	        chart.adapter = adapter.name;
	        chart.__adapterObject = adapter;
	        return adapter[fnName](chart);
	      }
	    }

	    if (adapters.length > 0) {
	      throw new Error("No charting library found for " + chartType);
	    } else {
	      throw new Error("No charting libraries found - be sure to include one before your charts");
	    }
	  }

	  // process data

	  var toFormattedKey = function toFormattedKey(key, keyType) {
	    if (keyType === "number") {
	      key = toFloat(key);
	    } else if (keyType === "datetime") {
	      key = toDate(key);
	    } else {
	      key = toStr(key);
	    }
	    return key;
	  };

	  var formatSeriesData = function formatSeriesData(data, keyType) {
	    var r = [],
	        key,
	        j;
	    for (j = 0; j < data.length; j++) {
	      if (keyType === "bubble") {
	        r.push([toFloat(data[j][0]), toFloat(data[j][1]), toFloat(data[j][2])]);
	      } else {
	        key = toFormattedKey(data[j][0], keyType);
	        r.push([key, toFloat(data[j][1])]);
	      }
	    }
	    if (keyType === "datetime") {
	      r.sort(sortByTime);
	    } else if (keyType === "number") {
	      r.sort(sortByNumberSeries);
	    }
	    return r;
	  };

	  function detectDiscrete(series) {
	    var i, j, data;
	    for (i = 0; i < series.length; i++) {
	      data = toArr(series[i].data);
	      for (j = 0; j < data.length; j++) {
	        if (!isDate(data[j][0])) {
	          return true;
	        }
	      }
	    }
	    return false;
	  }

	  // creates a shallow copy of each element of the array
	  // elements are expected to be objects
	  function copySeries(series) {
	    var newSeries = [],
	        i,
	        j;
	    for (i = 0; i < series.length; i++) {
	      var copy = {};
	      for (j in series[i]) {
	        if (series[i].hasOwnProperty(j)) {
	          copy[j] = series[i][j];
	        }
	      }
	      newSeries.push(copy);
	    }
	    return newSeries;
	  }

	  function processSeries(chart, keyType) {
	    var i;

	    var opts = chart.options;
	    var series = chart.rawData;

	    // see if one series or multiple
	    if (!isArray(series) || _typeof(series[0]) !== "object" || isArray(series[0])) {
	      series = [{ name: opts.label || "Value", data: series }];
	      chart.hideLegend = true;
	    } else {
	      chart.hideLegend = false;
	    }
	    if ((opts.discrete === null || opts.discrete === undefined) && keyType !== "bubble" && keyType !== "number") {
	      chart.discrete = detectDiscrete(series);
	    } else {
	      chart.discrete = opts.discrete;
	    }
	    if (chart.discrete) {
	      keyType = "string";
	    }
	    if (chart.options.xtype) {
	      keyType = chart.options.xtype;
	    }

	    // right format
	    series = copySeries(series);
	    for (i = 0; i < series.length; i++) {
	      series[i].data = formatSeriesData(toArr(series[i].data), keyType);
	    }

	    return series;
	  }

	  function processSimple(chart) {
	    var perfectData = toArr(chart.rawData),
	        i;
	    for (i = 0; i < perfectData.length; i++) {
	      perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
	    }
	    return perfectData;
	  }

	  // define classes

	  var Chart = function Chart(element, dataSource, options) {
	    var elementId;
	    if (typeof element === "string") {
	      elementId = element;
	      element = document.getElementById(element);
	      if (!element) {
	        throw new Error("No element with id " + elementId);
	      }
	    }
	    this.element = element;
	    this.options = merge(Chartkick.options, options || {});
	    this.dataSource = dataSource;

	    Chartkick.charts[element.id] = this;

	    fetchDataSource(this, dataSource);

	    if (this.options.refresh) {
	      this.startRefresh();
	    }
	  };

	  Chart.prototype.getElement = function getElement() {
	    return this.element;
	  };

	  Chart.prototype.getDataSource = function getDataSource() {
	    return this.dataSource;
	  };

	  Chart.prototype.getData = function getData() {
	    return this.data;
	  };

	  Chart.prototype.getOptions = function getOptions() {
	    return this.options;
	  };

	  Chart.prototype.getChartObject = function getChartObject() {
	    return this.chart;
	  };

	  Chart.prototype.getAdapter = function getAdapter() {
	    return this.adapter;
	  };

	  Chart.prototype.updateData = function updateData(dataSource, options) {
	    this.dataSource = dataSource;
	    if (options) {
	      this.__updateOptions(options);
	    }
	    fetchDataSource(this, dataSource);
	  };

	  Chart.prototype.setOptions = function setOptions(options) {
	    this.__updateOptions(options);
	    this.redraw();
	  };

	  Chart.prototype.redraw = function redraw() {
	    fetchDataSource(this, this.rawData);
	  };

	  Chart.prototype.refreshData = function refreshData() {
	    if (typeof this.dataSource === "string") {
	      // prevent browser from caching
	      var sep = this.dataSource.indexOf("?") === -1 ? "?" : "&";
	      var url = this.dataSource + sep + "_=" + new Date().getTime();
	      fetchDataSource(this, url);
	    }
	  };

	  Chart.prototype.startRefresh = function startRefresh() {
	    var this$1 = this;

	    var refresh = this.options.refresh;

	    if (!this.intervalId) {
	      if (refresh) {
	        this.intervalId = setInterval(function () {
	          this$1.refreshData();
	        }, refresh * 1000);
	      } else {
	        throw new Error("No refresh interval");
	      }
	    }
	  };

	  Chart.prototype.stopRefresh = function stopRefresh() {
	    if (this.intervalId) {
	      clearInterval(this.intervalId);
	      this.intervalId = null;
	    }
	  };

	  Chart.prototype.toImage = function toImage() {
	    if (this.adapter === "chartjs") {
	      return this.chart.toBase64Image();
	    } else {
	      return null;
	    }
	  };

	  Chart.prototype.destroy = function destroy() {
	    if (this.__adapterObject) {
	      this.__adapterObject.destroy(this);
	    }

	    if (this.__enterEvent) {
	      removeEvent(this.element, "mouseover", this.__enterEvent);
	    }

	    if (this.__leaveEvent) {
	      removeEvent(this.element, "mouseout", this.__leaveEvent);
	    }
	  };

	  Chart.prototype.__updateOptions = function __updateOptions(options) {
	    var updateRefresh = options.refresh && options.refresh !== this.options.refresh;
	    this.options = merge(Chartkick.options, options);
	    if (updateRefresh) {
	      this.stopRefresh();
	      this.startRefresh();
	    }
	  };

	  Chart.prototype.__render = function __render() {
	    this.data = this.__processData();
	    renderChart(this.__chartName(), this);
	  };

	  Chart.prototype.__config = function __config() {
	    return config;
	  };

	  var LineChart = function (Chart) {
	    function LineChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) LineChart.__proto__ = Chart;
	    LineChart.prototype = Object.create(Chart && Chart.prototype);
	    LineChart.prototype.constructor = LineChart;

	    LineChart.prototype.__processData = function __processData() {
	      return processSeries(this, "datetime");
	    };

	    LineChart.prototype.__chartName = function __chartName() {
	      return "LineChart";
	    };

	    return LineChart;
	  }(Chart);

	  var PieChart = function (Chart) {
	    function PieChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) PieChart.__proto__ = Chart;
	    PieChart.prototype = Object.create(Chart && Chart.prototype);
	    PieChart.prototype.constructor = PieChart;

	    PieChart.prototype.__processData = function __processData() {
	      return processSimple(this);
	    };

	    PieChart.prototype.__chartName = function __chartName() {
	      return "PieChart";
	    };

	    return PieChart;
	  }(Chart);

	  var ColumnChart = function (Chart) {
	    function ColumnChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) ColumnChart.__proto__ = Chart;
	    ColumnChart.prototype = Object.create(Chart && Chart.prototype);
	    ColumnChart.prototype.constructor = ColumnChart;

	    ColumnChart.prototype.__processData = function __processData() {
	      return processSeries(this, "string");
	    };

	    ColumnChart.prototype.__chartName = function __chartName() {
	      return "ColumnChart";
	    };

	    return ColumnChart;
	  }(Chart);

	  var BarChart = function (Chart) {
	    function BarChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) BarChart.__proto__ = Chart;
	    BarChart.prototype = Object.create(Chart && Chart.prototype);
	    BarChart.prototype.constructor = BarChart;

	    BarChart.prototype.__processData = function __processData() {
	      return processSeries(this, "string");
	    };

	    BarChart.prototype.__chartName = function __chartName() {
	      return "BarChart";
	    };

	    return BarChart;
	  }(Chart);

	  var AreaChart = function (Chart) {
	    function AreaChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) AreaChart.__proto__ = Chart;
	    AreaChart.prototype = Object.create(Chart && Chart.prototype);
	    AreaChart.prototype.constructor = AreaChart;

	    AreaChart.prototype.__processData = function __processData() {
	      return processSeries(this, "datetime");
	    };

	    AreaChart.prototype.__chartName = function __chartName() {
	      return "AreaChart";
	    };

	    return AreaChart;
	  }(Chart);

	  var GeoChart = function (Chart) {
	    function GeoChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) GeoChart.__proto__ = Chart;
	    GeoChart.prototype = Object.create(Chart && Chart.prototype);
	    GeoChart.prototype.constructor = GeoChart;

	    GeoChart.prototype.__processData = function __processData() {
	      return processSimple(this);
	    };

	    GeoChart.prototype.__chartName = function __chartName() {
	      return "GeoChart";
	    };

	    return GeoChart;
	  }(Chart);

	  var ScatterChart = function (Chart) {
	    function ScatterChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) ScatterChart.__proto__ = Chart;
	    ScatterChart.prototype = Object.create(Chart && Chart.prototype);
	    ScatterChart.prototype.constructor = ScatterChart;

	    ScatterChart.prototype.__processData = function __processData() {
	      return processSeries(this, "number");
	    };

	    ScatterChart.prototype.__chartName = function __chartName() {
	      return "ScatterChart";
	    };

	    return ScatterChart;
	  }(Chart);

	  var BubbleChart = function (Chart) {
	    function BubbleChart() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) BubbleChart.__proto__ = Chart;
	    BubbleChart.prototype = Object.create(Chart && Chart.prototype);
	    BubbleChart.prototype.constructor = BubbleChart;

	    BubbleChart.prototype.__processData = function __processData() {
	      return processSeries(this, "bubble");
	    };

	    BubbleChart.prototype.__chartName = function __chartName() {
	      return "BubbleChart";
	    };

	    return BubbleChart;
	  }(Chart);

	  var Timeline = function (Chart) {
	    function Timeline() {
	      Chart.apply(this, arguments);
	    }

	    if (Chart) Timeline.__proto__ = Chart;
	    Timeline.prototype = Object.create(Chart && Chart.prototype);
	    Timeline.prototype.constructor = Timeline;

	    Timeline.prototype.__processData = function __processData() {
	      var i,
	          data = this.rawData;
	      for (i = 0; i < data.length; i++) {
	        data[i][1] = toDate(data[i][1]);
	        data[i][2] = toDate(data[i][2]);
	      }
	      return data;
	    };

	    Timeline.prototype.__chartName = function __chartName() {
	      return "Timeline";
	    };

	    return Timeline;
	  }(Chart);

	  var Chartkick = {
	    LineChart: LineChart,
	    PieChart: PieChart,
	    ColumnChart: ColumnChart,
	    BarChart: BarChart,
	    AreaChart: AreaChart,
	    GeoChart: GeoChart,
	    ScatterChart: ScatterChart,
	    BubbleChart: BubbleChart,
	    Timeline: Timeline,
	    charts: {},
	    configure: function configure(options) {
	      for (var key in options) {
	        if (options.hasOwnProperty(key)) {
	          config[key] = options[key];
	        }
	      }
	    },
	    eachChart: function eachChart(callback) {
	      for (var chartId in Chartkick.charts) {
	        if (Chartkick.charts.hasOwnProperty(chartId)) {
	          callback(Chartkick.charts[chartId]);
	        }
	      }
	    },
	    config: config,
	    options: {},
	    adapters: adapters,
	    addAdapter: addAdapter
	  };

	  return Chartkick;
	});

/***/ },
/* 373 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
		value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 * Creates a tooltip with user informations given a login 
	 * @memberof common
	 * @example
	 * = user_tooltip(User.find('jbailhac'))
	 */
	var UserTooltip = function () {
		_createClass(UserTooltip, [{
			key: "setCookie",
			value: function setCookie(name, value) {
				document.cookie = name + "=" + (value || "") + "; path=/";
			}
		}, {
			key: "getCookie",
			value: function getCookie(name) {
				var nameEQ = name + "=";
				var ca = document.cookie.split(';');
				for (var i = 0; i < ca.length; i++) {
					var c = ca[i];
					while (c.charAt(0) === ' ') {
						c = c.substring(1, c.length);
					}if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
				}
				return null;
			}
		}]);

		function UserTooltip() {
			_classCallCheck(this, UserTooltip);

			var self = this;
			var delay = 500;
			var timer = null;

			(0, _jquery2.default)(".page").on('mouseenter', "[data-tooltip-login]", function () {
				var login = (0, _jquery2.default)(this).data('tooltip-login');
				var url = (0, _jquery2.default)(this).data('tooltip-url');
				var elt = (0, _jquery2.default)(this);
				timer = setTimeout(function (_) {
					if ((0, _jquery2.default)("[data-tooltip=" + login + "]").length == 0) {
						if (self.checkIfOldTooltip(elt, login) == false) self.request(elt, login, url);
					} else self.displayTooltip(elt);
				}, delay);
			});
			(0, _jquery2.default)(".page").on('mouseout', "[data-tooltip-login]", function () {
				clearTimeout(timer);
				(0, _jquery2.default)("[data-tooltip=" + (0, _jquery2.default)(this).data('tooltip-login') + "]").css('visibility', 'hidden');
				(0, _jquery2.default)("[data-tooltip]").css("visibility", "hidden");
			});
		}

		_createClass(UserTooltip, [{
			key: "displayTooltip",
			value: function displayTooltip(elt) {
				(0, _jquery2.default)("[data-tooltip]").css("visibility", "hidden");
				var login = elt.data('tooltip-login');

				if ((0, _jquery2.default)("[data-tooltip-login=" + login + "]:hover")[0] == undefined) return;
				var position = elt.first().offset();
				var width = elt.first().innerWidth();
				var tooltipWidth = (0, _jquery2.default)("[data-tooltip=" + login + "]").innerWidth();
				(0, _jquery2.default)("[data-tooltip=" + login + "]").css('top', position.top - 90 + 'px').css('left', position.left - tooltipWidth / 2 + width / 2 + 'px').css('position', 'absolute').css('visibility', 'visible');
			}
		}, {
			key: "checkIfOldTooltip",
			value: function checkIfOldTooltip(elt, username) {
				var storedUser = JSON.parse(sessionStorage.getItem(username));

				if (storedUser == null) return false;else {
					this.addTooltipTemplate(storedUser);
					this.displayTooltip(elt);
					return true;
				}
			}
		}, {
			key: "request",
			value: function request(elt, username, url) {
				var _this = this;

				var self = this;
				var oldCookie = this.getCookie('intra');

				this.setCookie('intra', 'v2');

				_jquery2.default.ajax({
					url: url + "/users/" + username + "?ams=true",
					type: 'GET',
					headers: {
						Accept: "application/json; charset=utf-8",
						"Content-Type": "application/json; charset=utf-8"
					},
					xhrFields: { withCredentials: true },
					async: true,
					success: function success(data) {
						self.addUserTooltip(data);
						self.displayTooltip(elt);
						if (oldCookie) _this.setCookie('intra', oldCookie);
					},
					error: function error(_error) {
						console.error("ajax error " + username + ":");
						console.log(_error);
						if (oldCookie) _this.setCookie('intra', oldCookie);
						return null;
					}
				});
			}
		}, {
			key: "_isLocalStorageNameSupported",
			value: function _isLocalStorageNameSupported() {
				var testKey = 'test',
				    storage = window.sessionStorage;
				try {
					storage.setItem(testKey, '1');
					storage.removeItem(testKey);
					return true;
				} catch (error) {
					return false;
				}
			}
		}, {
			key: "cleanInfo",
			value: function cleanInfo(userInfo) {
				var isStaff = false;

				if (!userInfo.location || userInfo.location == null) userInfo.location = "unavailable";
				if (userInfo.groups.length > 0) {
					var groups = _.map(userInfo.groups, 'name').join(", ");

					userInfo.groups = " – " + groups;
					if (groups.search("staff") >= 0) {
						isStaff = true;
						userInfo.cursus = groups;
						userInfo.groups = "";
					}
				}
				if (userInfo.cursus.length > 0 && !isStaff) {
					var cursus = _.map(userInfo.cursus, function (e) {
						var name = _.keys(e)[0];
						var level = Math.round(e[name].level * 100) / 100;

						return name + ": lvl " + level;
					}).join(", ");
					userInfo.cursus = cursus;
				}
				return userInfo;
			}
		}, {
			key: "addTooltipTemplate",
			value: function addTooltipTemplate(storedUser) {
				(0, _jquery2.default)("body").append("<div data-tooltip='" + storedUser.login + "' class='tooltip-content'>\n\t\t<div class='tooltip-img bg-image-item rounded' style='background-image: url(" + storedUser.image_url + ")'></div>\n\t\t<small><p class='tooltip-title'>" + storedUser.usual_full_name + "</p>\n\t\t<p>" + storedUser.location + "\n\t\t" + storedUser.groups + "</br>\n\t\t" + storedUser.cursus + "</p></small></div>");
			}
		}, {
			key: "addUserTooltip",
			value: function addUserTooltip(info) {
				var user = this.cleanInfo(info);

				if (this._isLocalStorageNameSupported()) {
					sessionStorage.setItem(user.login, JSON.stringify(user));
				}
				this.addTooltipTemplate(user);
			}
		}]);

		return UserTooltip;
	}();

	exports.default = UserTooltip;

/***/ },
/* 374 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _corejsTypeahead = __webpack_require__(211);

	var _corejsTypeahead2 = _interopRequireDefault(_corejsTypeahead);

	var _search = __webpack_require__(375);

	var _search2 = _interopRequireDefault(_search);

	var _multi = __webpack_require__(376);

	var _multi2 = _interopRequireDefault(_multi);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var TypeaheadHelper = function () {
	  function TypeaheadHelper() {
	    _classCallCheck(this, TypeaheadHelper);

	    var self = this;

	    (0, _jquery2.default)('.typeahead').each(function () {
	      var $input = (0, _jquery2.default)(this);
	      var bloodhound = self._getBloodhound.call(this);
	      bloodhound.initialize();
	      $input.typeahead({
	        highlight: true,
	        hint: false
	      }, {
	        display: "displayKey",
	        source: bloodhound.ttAdapter()
	      }).on('typeahead:selected', function (obj, datum) {
	        // Todo -> set value to input without using a hidden input
	        //$input.parents('form').find('input[type="hidden"][data-typeahead-'+$input.data('displayKey')+']').val(datum.value)
	        (0, _jquery2.default)('[data-typeahead-' + $input.data('displayKey') + ']').val(datum.value);
	      });
	    });
	    new _search2.default();
	    new _multi2.default();
	  }

	  _createClass(TypeaheadHelper, [{
	    key: '_getBloodhound',
	    value: function _getBloodhound() {
	      var $input = (0, _jquery2.default)(this);
	      return new _corejsTypeahead2.default({
	        datumTokenizer: function datumTokenizer(datum) {
	          _corejsTypeahead2.default.tokenizers.whitespace(datum.displayKey);
	        },
	        queryTokenizer: _corejsTypeahead2.default.tokenizers.whitespace,
	        remote: {
	          url: $input.data('url') + 'query=%QUERY',
	          wildcard: '%QUERY',
	          prepare: function prepare(q, o) {
	            o.xhrFields = { withCredentials: true };
	            o.url = o.url.replace('%QUERY', encodeURIComponent(q));
	            _lodash2.default.each($input.data('url-param'), function (value, key) {
	              o.url = o.url.replace('%' + key, encodeURIComponent((0, _jquery2.default)('' + value).val()));
	            });
	            return o;
	          },
	          transform: function transform(values) {
	            return _jquery2.default.map(values, function (value) {
	              return { displayKey: value[$input.data('displayKey')],
	                value: value[$input.data('valueKey') || 'id'],
	                data: value };
	            });
	          }
	        }
	      });
	    }
	  }]);

	  return TypeaheadHelper;
	}();

	exports.default = TypeaheadHelper;

/***/ },
/* 375 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _corejsTypeahead = __webpack_require__(211);

	var _corejsTypeahead2 = _interopRequireDefault(_corejsTypeahead);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var TypeaheadSearch = function () {
	  function TypeaheadSearch() {
	    _classCallCheck(this, TypeaheadSearch);

	    this.WILDCARD = '%QUERY';
	    this.form = (0, _jquery2.default)(".main-navbar-search");
	    this.input = this.form.find(".search-input");
	    this.fetch_url = this.form.attr("action");
	    this.userUrl = this.form.attr('data-user-url');
	    this.forumUrl = this.form.attr('data-forum-url');
	    this.projectUrl = this.form.attr('data-project-url');
	    if (this.input.length && this.form.find('.twitter-typeahead').length == 0) this._setupTypeahead();
	  }

	  _createClass(TypeaheadSearch, [{
	    key: '_setupTypeahead',
	    value: function _setupTypeahead() {
	      var self = this;
	      this._bindEnter();
	      this.form.addClass("js-search");
	      var users = this._getBloodhound();
	      var projects = this._getBloodhound2("project", "search");
	      var topics = this._getBloodhound2("topic", "project");

	      users.initialize();
	      projects.initialize();
	      topics.initialize();

	      _corejsTypeahead2.default.noConflict();
	      this.input.typeahead({
	        highlight: true,
	        hint: false
	      }, [{
	        display: "login",
	        source: users,
	        limit: 10000,
	        templates: {
	          header: '<h3 class="search-header-name searches-title">Login</h3>',
	          suggestion: function suggestion(_ref) {
	            var login = _ref.login,
	                cdn_uri = _ref.cdn_uri;

	            return '<a href=\'' + self.userUrl + login + '\' class=\'search-suggestion-item\'>\n                        <div class=\'search-user-picture bg-image-item rounded square-xs\' style=\'background-image: url(' + cdn_uri + ')\'></div>\n                        <span>' + login + '</span>\n                    </a>';
	          }
	        }
	      }, {
	        display: 'slug',
	        source: projects,
	        limit: 10000,
	        templates: {
	          header: '<h3 class="search-header-name searches-title">Projects</h3>',
	          suggestion: function suggestion(_ref2) {
	            var name = _ref2.name,
	                url = _ref2.url;

	            console.log(name, url);
	            return '<a href="' + url + '" class=\'search-suggestion-item\'>\n                    <span>' + name + '</span>\n                </a>';
	          }
	        }
	      }]);
	    }
	  }, {
	    key: '_bindEnter',
	    value: function _bindEnter() {
	      var _this = this;

	      var submit = function submit(e) {
	        if (e.keyCode == 13) {
	          (0, _jquery2.default)(_this.form).submit();
	        }
	      };

	      this.input.on('typeahead:cursorchange', function (ev, data) {
	        _this.input.off('keyup', submit);
	        if (!data == null && !data.login && !data.name) {
	          _this.input.on('keyup', submit);
	        }
	      });

	      this.input.on('typeahead:select', function (ev, data) {
	        _this.input.off('keyup', submit);
	        var url = data.url ? '' + data.url : '' + _this.userUrl + data.login;
	        document.location = url;
	      });

	      this.input.on('keyup', submit);
	    }
	  }, {
	    key: '_getBloodhound',
	    value: function _getBloodhound() {
	      var _this2 = this;

	      return new _corejsTypeahead2.default({
	        datumTokenizer: function datumTokenizer(d) {
	          return _corejsTypeahead2.default.tokenizers.obj.whitespace(d.value);
	        },
	        queryTokenizer: _corejsTypeahead2.default.tokenizers.whitespace,
	        remote: {
	          url: this.fetch_url + ('.json?query=' + this.WILDCARD),
	          wildcard: this.WILDCARD,
	          prepare: function prepare(q, o) {
	            o.xhrFields = { withCredentials: true };
	            o.url = o.url.replace(_this2.WILDCARD, encodeURIComponent(q));
	            return o;
	          }
	        }
	      });
	    }
	  }, {
	    key: '_getBloodhound2',
	    value: function _getBloodhound2(type, partDel) {
	      var _this3 = this;

	      this.fetch_url = this.fetch_url.substring(0, this.fetch_url.length - partDel.length);
	      this.fetch_url = this.fetch_url + type;
	      return new _corejsTypeahead2.default({
	        datumTokenizer: _corejsTypeahead2.default.tokenizers.obj.whitespace('login'),
	        queryTokenizer: _corejsTypeahead2.default.tokenizers.whitespace,
	        remote: {
	          url: this.fetch_url + ('.json?query=' + this.WILDCARD),
	          wildcard: this.WILDCARD,
	          prepare: function prepare(q, o) {
	            o.xhrFields = { withCredentials: true };
	            o.url = o.url.replace(_this3.WILDCARD, encodeURIComponent(q));
	            return o;
	          }
	        }
	      });
	    }
	  }]);

	  return TypeaheadSearch;
	}();

	exports.default = TypeaheadSearch;

/***/ },
/* 376 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _corejsTypeahead = __webpack_require__(211);

	var _corejsTypeahead2 = _interopRequireDefault(_corejsTypeahead);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var MultiTypeahead = function () {
	  function MultiTypeahead() {
	    _classCallCheck(this, MultiTypeahead);

	    var self = this;
	    this._bindTypeahead();
	    (0, _jquery2.default)(document).on('click', '.btn', function () {
	      self._bindTypeahead();
	    });
	  }

	  _createClass(MultiTypeahead, [{
	    key: '_bindTypeahead',
	    value: function _bindTypeahead() {
	      var self = this;
	      (0, _jquery2.default)('.multi-typeahead').each(function () {
	        var $input = (0, _jquery2.default)(this);
	        var bloodhound = self._getBloodhound.call(this);

	        bloodhound.initialize();
	        $input.typeahead({
	          highlight: true,
	          hint: false
	        }, {
	          limit: 100,
	          templates: {
	            suggestion: function suggestion(datum) {
	              return '<div class=\'autocomplete-item\'>\n                              <span>' + datum.displayKey + '</span>\n                              <code class=\'search-suggestion-tag\'>' + datum.group + '</code>\n                          </div>';
	            }
	          },
	          display: "displayKey",
	          source: bloodhound.ttAdapter()
	        }).on('typeahead:selected', function (obj, datum) {
	          // Todo -> set value to input without using a hidden input
	          //$input.parents('form').find('input[type="hidden"][data-typeahead-'+$input.data('displayKey')+']').val(datum.value)
	          (0, _jquery2.default)('[data-typeahead-' + $input.data('displayKey') + ']').val(datum.value);
	        });
	        $input.removeClass('multi-typeahead');
	        $input.parent().addClass('autocomplete');
	      });
	    }
	  }, {
	    key: '_getBloodhound',
	    value: function _getBloodhound() {
	      var $input = (0, _jquery2.default)(this);
	      return new _corejsTypeahead2.default({
	        datumTokenizer: function datumTokenizer(datum) {
	          _corejsTypeahead2.default.tokenizers.whitespace(datum.displayKey);
	        },
	        queryTokenizer: _corejsTypeahead2.default.tokenizers.whitespace,
	        remote: {
	          url: $input.data('url') + 'query=%QUERY',
	          wildcard: '%QUERY',
	          prepare: function prepare(q, o) {
	            o.xhrFields = { withCredentials: true };
	            o.url = o.url.replace('%QUERY', encodeURIComponent(q));
	            _.each($input.data('url-param'), function (value, key) {
	              o.url = o.url.replace('%' + key, encodeURIComponent((0, _jquery2.default)('' + value).val()));
	            });
	            return o;
	          },
	          transform: function transform(json) {
	            return _jquery2.default.map(json, function (values, key) {
	              return _jquery2.default.map(values, function (value) {
	                return {
	                  displayKey: value[$input.data('displayKey')],
	                  value: value[$input.data('valueKey') || 'id'],
	                  data: value,
	                  group: key
	                };
	              });
	            });
	          }
	        }
	      });
	    }
	  }]);

	  return MultiTypeahead;
	}();

	exports.default = MultiTypeahead;

/***/ },
/* 377 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	__webpack_require__(12);

	var _smart = __webpack_require__(378);

	var _smart2 = _interopRequireDefault(_smart);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var ModalHelper = function ModalHelper() {
	  _classCallCheck(this, ModalHelper);

	  new _smart2.default();
	  //     let self = this;
	  //     $('input[data-modal-id]').on('click', (e) => {
	  //       let condition = true
	  //       let conditionModuleName = $(this).data('condition')
	  //       if (conditionModuleName && require(conditionModuleName)) {
	  //         let module = require($(this).data('condition'))
	  //         if (module.modalCondition)
	  //           condition = module.modalCondition()
	  //       }
	  //       let $modal = $(`.modal[data-modal-id='${$(this).data('modal-id')}']`)
	  //       self._initModal($modal, $(this).data('confirmation'))
	  //       if (condition) {
	  //         e.preventDefault()
	  //         $modal.modal('show')
	  //       }
	  //     });
	}

	// _initModal($modal, confirmationModuleName) {
	//    if (confirmationModuleName) {
	//     $modal.one('click', '.btn-primary', _ => {
	// Fix data-modal, c'est l'enfer
	//        let module = require(confirmationModuleName)
	//      if (module.modalConfirmation)
	//      module.modalConfirmation();
	//    })
	//  }
	// }
	;

	exports.default = ModalHelper;

/***/ },
/* 378 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	__webpack_require__(12);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Smart = function () {
	  function Smart() {
	    var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

	    _classCallCheck(this, Smart);

	    var defaults = {
	      selector: 'data-smart-modal',
	      url: 'data-url',
	      container: 'data-selector',
	      titleSelector: 'data-title',
	      footerSelector: 'data-footer',
	      class: 'data-class',
	      modal: '#smartModal'
	    };
	    this.opts = _lodash2.default.extend(defaults, opts);
	    this._bind();
	  }

	  _createClass(Smart, [{
	    key: '_bind',
	    value: function _bind() {
	      var _this = this;

	      var s = function s(m) {
	        return '[' + m + ']';
	      };
	      (0, _jquery2.default)('[' + this.opts.selector + ']').each(function (q, e) {
	        var url = (0, _jquery2.default)(e).attr(_this.opts.url);
	        var container = (0, _jquery2.default)(e).attr(_this.opts.container) || '.container-item';
	        var title = (0, _jquery2.default)(e).attr(_this.opts.titleSelector);
	        var footer = (0, _jquery2.default)(e).attr(_this.opts.footerSelector);
	        if (!url) console.warn("Undefined url for trigger ", e);else (0, _jquery2.default)(e).click(function () {
	          _jquery2.default.signedAjax({ url: url, method: "GET" }).done(function (data) {
	            var html = (0, _jquery2.default)(data).find(container).html();
	            var titleHtml = title ? (0, _jquery2.default)(data).find(title).html() : false;
	            var footerHtml = footer ? (0, _jquery2.default)(data).find(footer).html() : false;
	            (0, _jquery2.default)(_this.opts.modal).find('.modal-body').html(html);

	            (0, _jquery2.default)(_this.opts.modal).addClass((0, _jquery2.default)(e).attr(_this.opts.class) || 'smart-modal');

	            // Si il y a un titre, on le met, sinon on le cache
	            if (titleHtml) (0, _jquery2.default)(_this.opts.modal).find('.modal-header').html(titleHtml).show();else (0, _jquery2.default)(_this.opts.modal).find('.modal-header').html("").hide();

	            // Si il y a un footer, on le met, sinon on le cache
	            if (footerHtml) (0, _jquery2.default)(_this.opts.modal).find('.modal-footer').html(footerHtml).show();else (0, _jquery2.default)(_this.opts.modal).find('.modal-footer').html("").hide();

	            (0, _jquery2.default)(_this.opts.modal).modal('show');
	          });
	        });
	      });
	    }
	  }]);

	  return Smart;
	}();

	exports.default = Smart;

/***/ },
/* 379 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _array = __webpack_require__(380);

	var _array2 = _interopRequireDefault(_array);

	var _chosen = __webpack_require__(381);

	var _chosen2 = _interopRequireDefault(_chosen);

	var _date_picker = __webpack_require__(383);

	var _date_picker2 = _interopRequireDefault(_date_picker);

	var _group = __webpack_require__(385);

	var _group2 = _interopRequireDefault(_group);

	var _limit = __webpack_require__(386);

	var _limit2 = _interopRequireDefault(_limit);

	var _textarea = __webpack_require__(388);

	var _textarea2 = _interopRequireDefault(_textarea);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var SimpleFormHelper = function SimpleFormHelper() {
	  _classCallCheck(this, SimpleFormHelper);

	  new _array2.default();
	  new _chosen2.default();
	  new _date_picker2.default();
	  new _group2.default();
	  new _limit2.default();
	  new _textarea2.default();
	};

	exports.default = SimpleFormHelper;

/***/ },
/* 380 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var SimpleFormArray = function SimpleFormArray() {
	  _classCallCheck(this, SimpleFormArray);

	  (0, _jquery2.default)("input.array, textarea.array").after('<a href="javascript:;" class="input_remove_elem">x</a>');

	  _.each((0, _jquery2.default)(".form-group:has(input.array), .form-group:has(textarea.array)"), function (form) {
	    (0, _jquery2.default)(form).find("input.array + a.input_remove_elem:last, textarea.array + a.input_remove_elem:last").after('<a class="input_add_elem" href="javascript:;">+</a>');

	    var templateInput = (0, _jquery2.default)(form).find("input.array:last, textarea.array:last")[0].cloneNode();
	    (0, _jquery2.default)(form).find('a.input_add_elem').on('click', function () {
	      var newInput = this.parentElement.insertBefore(templateInput.cloneNode(), this);

	      (0, _jquery2.default)(newInput).after('<a href="javascript:;" class="input_remove_elem">x</a>');
	    });
	  });

	  (0, _jquery2.default)(".form-group").on('click', 'a.input_remove_elem', function () {
	    this.previousSibling.remove();
	    this.remove();
	  });
	};

	exports.default = SimpleFormArray;

/***/ },
/* 381 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	__webpack_require__(382);

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var selector = ".chosen-select";

	var SimpleFormChosen = function () {
	  function SimpleFormChosen() {
	    _classCallCheck(this, SimpleFormChosen);

	    (0, _jquery2.default)(document).on('nested:fieldAdded', this.bind);
	    (0, _jquery2.default)(document).on('cocoon:after-insert', this.bind);
	    this.bind();
	  }

	  _createClass(SimpleFormChosen, [{
	    key: 'bind',
	    value: function bind() {
	      (0, _jquery2.default)(selector).each(function () {
	        (0, _jquery2.default)(this).chosen({
	          allow_single_deselect: true,
	          no_results_text: "No results matched",
	          width: (0, _jquery2.default)(this).width() + "px"
	        });
	      });
	    }
	  }]);

	  return SimpleFormChosen;
	}();

	exports.default = SimpleFormChosen;

/***/ },
/* 382 */
/***/ function(module, exports) {

	/*!
	Chosen, a Select Box Enhancer for jQuery and Prototype
	by Patrick Filler for Harvest, http://getharvest.com

	Version 1.2.0
	Full source at https://github.com/harvesthq/chosen
	Copyright (c) 2011-2014 Harvest http://getharvest.com

	MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
	This file is generated by `grunt build`, do not edit it by hand.
	*/

	(function() {
	  var $, AbstractChosen, Chosen, SelectParser, _ref,
	    __hasProp = {}.hasOwnProperty,
	    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

	  SelectParser = (function() {
	    function SelectParser() {
	      this.options_index = 0;
	      this.parsed = [];
	    }

	    SelectParser.prototype.add_node = function(child) {
	      if (child.nodeName.toUpperCase() === "OPTGROUP") {
	        return this.add_group(child);
	      } else {
	        return this.add_option(child);
	      }
	    };

	    SelectParser.prototype.add_group = function(group) {
	      var group_position, option, _i, _len, _ref, _results;
	      group_position = this.parsed.length;
	      this.parsed.push({
	        array_index: group_position,
	        group: true,
	        label: this.escapeExpression(group.label),
	        children: 0,
	        disabled: group.disabled
	      });
	      _ref = group.childNodes;
	      _results = [];
	      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
	        option = _ref[_i];
	        _results.push(this.add_option(option, group_position, group.disabled));
	      }
	      return _results;
	    };

	    SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
	      if (option.nodeName.toUpperCase() === "OPTION") {
	        if (option.text !== "") {
	          if (group_position != null) {
	            this.parsed[group_position].children += 1;
	          }
	          this.parsed.push({
	            array_index: this.parsed.length,
	            options_index: this.options_index,
	            value: option.value,
	            text: option.text,
	            html: option.innerHTML,
	            selected: option.selected,
	            disabled: group_disabled === true ? group_disabled : option.disabled,
	            group_array_index: group_position,
	            classes: option.className,
	            style: option.style.cssText
	          });
	        } else {
	          this.parsed.push({
	            array_index: this.parsed.length,
	            options_index: this.options_index,
	            empty: true
	          });
	        }
	        return this.options_index += 1;
	      }
	    };

	    SelectParser.prototype.escapeExpression = function(text) {
	      var map, unsafe_chars;
	      if ((text == null) || text === false) {
	        return "";
	      }
	      if (!/[\&\<\>\"\'\`]/.test(text)) {
	        return text;
	      }
	      map = {
	        "<": "&lt;",
	        ">": "&gt;",
	        '"': "&quot;",
	        "'": "&#x27;",
	        "`": "&#x60;"
	      };
	      unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
	      return text.replace(unsafe_chars, function(chr) {
	        return map[chr] || "&amp;";
	      });
	    };

	    return SelectParser;

	  })();

	  SelectParser.select_to_array = function(select) {
	    var child, parser, _i, _len, _ref;
	    parser = new SelectParser();
	    _ref = select.childNodes;
	    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
	      child = _ref[_i];
	      parser.add_node(child);
	    }
	    return parser.parsed;
	  };

	  AbstractChosen = (function() {
	    function AbstractChosen(form_field, options) {
	      this.form_field = form_field;
	      this.options = options != null ? options : {};
	      if (!AbstractChosen.browser_is_supported()) {
	        return;
	      }
	      this.is_multiple = this.form_field.multiple;
	      this.set_default_text();
	      this.set_default_values();
	      this.setup();
	      this.set_up_html();
	      this.register_observers();
	    }

	    AbstractChosen.prototype.set_default_values = function() {
	      var _this = this;
	      this.click_test_action = function(evt) {
	        return _this.test_active_click(evt);
	      };
	      this.activate_action = function(evt) {
	        return _this.activate_field(evt);
	      };
	      this.active_field = false;
	      this.mouse_on_container = false;
	      this.results_showing = false;
	      this.result_highlighted = null;
	      this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
	      this.disable_search_threshold = this.options.disable_search_threshold || 0;
	      this.disable_search = this.options.disable_search || false;
	      this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
	      this.group_search = this.options.group_search != null ? this.options.group_search : true;
	      this.search_contains = this.options.search_contains || false;
	      this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
	      this.max_selected_options = this.options.max_selected_options || Infinity;
	      this.inherit_select_classes = this.options.inherit_select_classes || false;
	      this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
	      return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
	    };

	    AbstractChosen.prototype.set_default_text = function() {
	      if (this.form_field.getAttribute("data-placeholder")) {
	        this.default_text = this.form_field.getAttribute("data-placeholder");
	      } else if (this.is_multiple) {
	        this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
	      } else {
	        this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
	      }
	      return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
	    };

	    AbstractChosen.prototype.mouse_enter = function() {
	      return this.mouse_on_container = true;
	    };

	    AbstractChosen.prototype.mouse_leave = function() {
	      return this.mouse_on_container = false;
	    };

	    AbstractChosen.prototype.input_focus = function(evt) {
	      var _this = this;
	      if (this.is_multiple) {
	        if (!this.active_field) {
	          return setTimeout((function() {
	            return _this.container_mousedown();
	          }), 50);
	        }
	      } else {
	        if (!this.active_field) {
	          return this.activate_field();
	        }
	      }
	    };

	    AbstractChosen.prototype.input_blur = function(evt) {
	      var _this = this;
	      if (!this.mouse_on_container) {
	        this.active_field = false;
	        return setTimeout((function() {
	          return _this.blur_test();
	        }), 100);
	      }
	    };

	    AbstractChosen.prototype.results_option_build = function(options) {
	      var content, data, _i, _len, _ref;
	      content = '';
	      _ref = this.results_data;
	      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
	        data = _ref[_i];
	        if (data.group) {
	          content += this.result_add_group(data);
	        } else {
	          content += this.result_add_option(data);
	        }
	        if (options != null ? options.first : void 0) {
	          if (data.selected && this.is_multiple) {
	            this.choice_build(data);
	          } else if (data.selected && !this.is_multiple) {
	            this.single_set_selected_text(data.text);
	          }
	        }
	      }
	      return content;
	    };

	    AbstractChosen.prototype.result_add_option = function(option) {
	      var classes, option_el;
	      if (!option.search_match) {
	        return '';
	      }
	      if (!this.include_option_in_results(option)) {
	        return '';
	      }
	      classes = [];
	      if (!option.disabled && !(option.selected && this.is_multiple)) {
	        classes.push("active-result");
	      }
	      if (option.disabled && !(option.selected && this.is_multiple)) {
	        classes.push("disabled-result");
	      }
	      if (option.selected) {
	        classes.push("result-selected");
	      }
	      if (option.group_array_index != null) {
	        classes.push("group-option");
	      }
	      if (option.classes !== "") {
	        classes.push(option.classes);
	      }
	      option_el = document.createElement("li");
	      option_el.className = classes.join(" ");
	      option_el.style.cssText = option.style;
	      option_el.setAttribute("data-option-array-index", option.array_index);
	      option_el.innerHTML = option.search_text;
	      return this.outerHTML(option_el);
	    };

	    AbstractChosen.prototype.result_add_group = function(group) {
	      var group_el;
	      if (!(group.search_match || group.group_match)) {
	        return '';
	      }
	      if (!(group.active_options > 0)) {
	        return '';
	      }
	      group_el = document.createElement("li");
	      group_el.className = "group-result";
	      group_el.innerHTML = group.search_text;
	      return this.outerHTML(group_el);
	    };

	    AbstractChosen.prototype.results_update_field = function() {
	      this.set_default_text();
	      if (!this.is_multiple) {
	        this.results_reset_cleanup();
	      }
	      this.result_clear_highlight();
	      this.results_build();
	      if (this.results_showing) {
	        return this.winnow_results();
	      }
	    };

	    AbstractChosen.prototype.reset_single_select_options = function() {
	      var result, _i, _len, _ref, _results;
	      _ref = this.results_data;
	      _results = [];
	      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
	        result = _ref[_i];
	        if (result.selected) {
	          _results.push(result.selected = false);
	        } else {
	          _results.push(void 0);
	        }
	      }
	      return _results;
	    };

	    AbstractChosen.prototype.results_toggle = function() {
	      if (this.results_showing) {
	        return this.results_hide();
	      } else {
	        return this.results_show();
	      }
	    };

	    AbstractChosen.prototype.results_search = function(evt) {
	      if (this.results_showing) {
	        return this.winnow_results();
	      } else {
	        return this.results_show();
	      }
	    };

	    AbstractChosen.prototype.winnow_results = function() {
	      var escapedSearchText, option, regex, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
	      this.no_results_clear();
	      results = 0;
	      searchText = this.get_search_text();
	      escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
	      zregex = new RegExp(escapedSearchText, 'i');
	      regex = this.get_search_regex(escapedSearchText);
	      _ref = this.results_data;
	      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
	        option = _ref[_i];
	        option.search_match = false;
	        results_group = null;
	        if (this.include_option_in_results(option)) {
	          if (option.group) {
	            option.group_match = false;
	            option.active_options = 0;
	          }
	          if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
	            results_group = this.results_data[option.group_array_index];
	            if (results_group.active_options === 0 && results_group.search_match) {
	              results += 1;
	            }
	            results_group.active_options += 1;
	          }
	          if (!(option.group && !this.group_search)) {
	            option.search_text = option.group ? option.label : option.text;
	            option.search_match = this.search_string_match(option.search_text, regex);
	            if (option.search_match && !option.group) {
	              results += 1;
	            }
	            if (option.search_match) {
	              if (searchText.length) {
	                startpos = option.search_text.search(zregex);
	                text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
	                option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
	              }
	              if (results_group != null) {
	                results_group.group_match = true;
	              }
	            } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
	              option.search_match = true;
	            }
	          }
	        }
	      }
	      this.result_clear_highlight();
	      if (results < 1 && searchText.length) {
	        this.update_results_content("");
	        return this.no_results(searchText);
	      } else {
	        this.update_results_content(this.results_option_build());
	        return this.winnow_results_set_highlight();
	      }
	    };

	    AbstractChosen.prototype.get_search_regex = function(escaped_search_string) {
	      var regex_anchor;
	      regex_anchor = this.search_contains ? "" : "^";
	      return new RegExp(regex_anchor + escaped_search_string, 'i');
	    };

	    AbstractChosen.prototype.search_string_match = function(search_string, regex) {
	      var part, parts, _i, _len;
	      if (regex.test(search_string)) {
	        return true;
	      } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
	        parts = search_string.replace(/\[|\]/g, "").split(" ");
	        if (parts.length) {
	          for (_i = 0, _len = parts.length; _i < _len; _i++) {
	            part = parts[_i];
	            if (regex.test(part)) {
	              return true;
	            }
	          }
	        }
	      }
	    };

	    AbstractChosen.prototype.choices_count = function() {
	      var option, _i, _len, _ref;
	      if (this.selected_option_count != null) {
	        return this.selected_option_count;
	      }
	      this.selected_option_count = 0;
	      _ref = this.form_field.options;
	      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
	        option = _ref[_i];
	        if (option.selected) {
	          this.selected_option_count += 1;
	        }
	      }
	      return this.selected_option_count;
	    };

	    AbstractChosen.prototype.choices_click = function(evt) {
	      evt.preventDefault();
	      if (!(this.results_showing || this.is_disabled)) {
	        return this.results_show();
	      }
	    };

	    AbstractChosen.prototype.keyup_checker = function(evt) {
	      var stroke, _ref;
	      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
	      this.search_field_scale();
	      switch (stroke) {
	        case 8:
	          if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
	            return this.keydown_backstroke();
	          } else if (!this.pending_backstroke) {
	            this.result_clear_highlight();
	            return this.results_search();
	          }
	          break;
	        case 13:
	          evt.preventDefault();
	          if (this.results_showing) {
	            return this.result_select(evt);
	          }
	          break;
	        case 27:
	          if (this.results_showing) {
	            this.results_hide();
	          }
	          return true;
	        case 9:
	        case 38:
	        case 40:
	        case 16:
	        case 91:
	        case 17:
	          break;
	        default:
	          return this.results_search();
	      }
	    };

	    AbstractChosen.prototype.clipboard_event_checker = function(evt) {
	      var _this = this;
	      return setTimeout((function() {
	        return _this.results_search();
	      }), 50);
	    };

	    AbstractChosen.prototype.container_width = function() {
	      if (this.options.width != null) {
	        return this.options.width;
	      } else {
	        return "" + this.form_field.offsetWidth + "px";
	      }
	    };

	    AbstractChosen.prototype.include_option_in_results = function(option) {
	      if (this.is_multiple && (!this.display_selected_options && option.selected)) {
	        return false;
	      }
	      if (!this.display_disabled_options && option.disabled) {
	        return false;
	      }
	      if (option.empty) {
	        return false;
	      }
	      return true;
	    };

	    AbstractChosen.prototype.search_results_touchstart = function(evt) {
	      this.touch_started = true;
	      return this.search_results_mouseover(evt);
	    };

	    AbstractChosen.prototype.search_results_touchmove = function(evt) {
	      this.touch_started = false;
	      return this.search_results_mouseout(evt);
	    };

	    AbstractChosen.prototype.search_results_touchend = function(evt) {
	      if (this.touch_started) {
	        return this.search_results_mouseup(evt);
	      }
	    };

	    AbstractChosen.prototype.outerHTML = function(element) {
	      var tmp;
	      if (element.outerHTML) {
	        return element.outerHTML;
	      }
	      tmp = document.createElement("div");
	      tmp.appendChild(element);
	      return tmp.innerHTML;
	    };

	    AbstractChosen.browser_is_supported = function() {
	      if (window.navigator.appName === "Microsoft Internet Explorer") {
	        return document.documentMode >= 8;
	      }
	      if (/iP(od|hone)/i.test(window.navigator.userAgent)) {
	        return false;
	      }
	      if (/Android/i.test(window.navigator.userAgent)) {
	        if (/Mobile/i.test(window.navigator.userAgent)) {
	          return false;
	        }
	      }
	      return true;
	    };

	    AbstractChosen.default_multiple_text = "Select Some Options";

	    AbstractChosen.default_single_text = "Select an Option";

	    AbstractChosen.default_no_result_text = "No results match";

	    return AbstractChosen;

	  })();

	  $ = jQuery;

	  $.fn.extend({
	    chosen: function(options) {
	      if (!AbstractChosen.browser_is_supported()) {
	        return this;
	      }
	      return this.each(function(input_field) {
	        var $this, chosen;
	        $this = $(this);
	        chosen = $this.data('chosen');
	        if (options === 'destroy' && chosen instanceof Chosen) {
	          chosen.destroy();
	        } else if (!(chosen instanceof Chosen)) {
	          $this.data('chosen', new Chosen(this, options));
	        }
	      });
	    }
	  });

	  Chosen = (function(_super) {
	    __extends(Chosen, _super);

	    function Chosen() {
	      _ref = Chosen.__super__.constructor.apply(this, arguments);
	      return _ref;
	    }

	    Chosen.prototype.setup = function() {
	      this.form_field_jq = $(this.form_field);
	      this.current_selectedIndex = this.form_field.selectedIndex;
	      return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl");
	    };

	    Chosen.prototype.set_up_html = function() {
	      var container_classes, container_props;
	      container_classes = ["chosen-container"];
	      container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
	      if (this.inherit_select_classes && this.form_field.className) {
	        container_classes.push(this.form_field.className);
	      }
	      if (this.is_rtl) {
	        container_classes.push("chosen-rtl");
	      }
	      container_props = {
	        'class': container_classes.join(' '),
	        'style': "width: " + (this.container_width()) + ";",
	        'title': this.form_field.title
	      };
	      if (this.form_field.id.length) {
	        container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
	      }
	      this.container = $("<div />", container_props);
	      if (this.is_multiple) {
	        this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
	      } else {
	        this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
	      }
	      this.form_field_jq.hide().after(this.container);
	      this.dropdown = this.container.find('div.chosen-drop').first();
	      this.search_field = this.container.find('input').first();
	      this.search_results = this.container.find('ul.chosen-results').first();
	      this.search_field_scale();
	      this.search_no_results = this.container.find('li.no-results').first();
	      if (this.is_multiple) {
	        this.search_choices = this.container.find('ul.chosen-choices').first();
	        this.search_container = this.container.find('li.search-field').first();
	      } else {
	        this.search_container = this.container.find('div.chosen-search').first();
	        this.selected_item = this.container.find('.chosen-single').first();
	      }
	      this.results_build();
	      this.set_tab_index();
	      this.set_label_behavior();
	      return this.form_field_jq.trigger("chosen:ready", {
	        chosen: this
	      });
	    };

	    Chosen.prototype.register_observers = function() {
	      var _this = this;
	      this.container.bind('touchstart.chosen', function(evt) {
	        _this.container_mousedown(evt);
	      });
	      this.container.bind('touchend.chosen', function(evt) {
	        _this.container_mouseup(evt);
	      });
	      this.container.bind('mousedown.chosen', function(evt) {
	        _this.container_mousedown(evt);
	      });
	      this.container.bind('mouseup.chosen', function(evt) {
	        _this.container_mouseup(evt);
	      });
	      this.container.bind('mouseenter.chosen', function(evt) {
	        _this.mouse_enter(evt);
	      });
	      this.container.bind('mouseleave.chosen', function(evt) {
	        _this.mouse_leave(evt);
	      });
	      this.search_results.bind('mouseup.chosen', function(evt) {
	        _this.search_results_mouseup(evt);
	      });
	      this.search_results.bind('mouseover.chosen', function(evt) {
	        _this.search_results_mouseover(evt);
	      });
	      this.search_results.bind('mouseout.chosen', function(evt) {
	        _this.search_results_mouseout(evt);
	      });
	      this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {
	        _this.search_results_mousewheel(evt);
	      });
	      this.search_results.bind('touchstart.chosen', function(evt) {
	        _this.search_results_touchstart(evt);
	      });
	      this.search_results.bind('touchmove.chosen', function(evt) {
	        _this.search_results_touchmove(evt);
	      });
	      this.search_results.bind('touchend.chosen', function(evt) {
	        _this.search_results_touchend(evt);
	      });
	      this.form_field_jq.bind("chosen:updated.chosen", function(evt) {
	        _this.results_update_field(evt);
	      });
	      this.form_field_jq.bind("chosen:activate.chosen", function(evt) {
	        _this.activate_field(evt);
	      });
	      this.form_field_jq.bind("chosen:open.chosen", function(evt) {
	        _this.container_mousedown(evt);
	      });
	      this.form_field_jq.bind("chosen:close.chosen", function(evt) {
	        _this.input_blur(evt);
	      });
	      this.search_field.bind('blur.chosen', function(evt) {
	        _this.input_blur(evt);
	      });
	      this.search_field.bind('keyup.chosen', function(evt) {
	        _this.keyup_checker(evt);
	      });
	      this.search_field.bind('keydown.chosen', function(evt) {
	        _this.keydown_checker(evt);
	      });
	      this.search_field.bind('focus.chosen', function(evt) {
	        _this.input_focus(evt);
	      });
	      this.search_field.bind('cut.chosen', function(evt) {
	        _this.clipboard_event_checker(evt);
	      });
	      this.search_field.bind('paste.chosen', function(evt) {
	        _this.clipboard_event_checker(evt);
	      });
	      if (this.is_multiple) {
	        return this.search_choices.bind('click.chosen', function(evt) {
	          _this.choices_click(evt);
	        });
	      } else {
	        return this.container.bind('click.chosen', function(evt) {
	          evt.preventDefault();
	        });
	      }
	    };

	    Chosen.prototype.destroy = function() {
	      $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
	      if (this.search_field[0].tabIndex) {
	        this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
	      }
	      this.container.remove();
	      this.form_field_jq.removeData('chosen');
	      return this.form_field_jq.show();
	    };

	    Chosen.prototype.search_field_disabled = function() {
	      this.is_disabled = this.form_field_jq[0].disabled;
	      if (this.is_disabled) {
	        this.container.addClass('chosen-disabled');
	        this.search_field[0].disabled = true;
	        if (!this.is_multiple) {
	          this.selected_item.unbind("focus.chosen", this.activate_action);
	        }
	        return this.close_field();
	      } else {
	        this.container.removeClass('chosen-disabled');
	        this.search_field[0].disabled = false;
	        if (!this.is_multiple) {
	          return this.selected_item.bind("focus.chosen", this.activate_action);
	        }
	      }
	    };

	    Chosen.prototype.container_mousedown = function(evt) {
	      if (!this.is_disabled) {
	        if (evt && evt.type === "mousedown" && !this.results_showing) {
	          evt.preventDefault();
	        }
	        if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
	          if (!this.active_field) {
	            if (this.is_multiple) {
	              this.search_field.val("");
	            }
	            $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action);
	            this.results_show();
	          } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
	            evt.preventDefault();
	            this.results_toggle();
	          }
	          return this.activate_field();
	        }
	      }
	    };

	    Chosen.prototype.container_mouseup = function(evt) {
	      if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
	        return this.results_reset(evt);
	      }
	    };

	    Chosen.prototype.search_results_mousewheel = function(evt) {
	      var delta;
	      if (evt.originalEvent) {
	        delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
	      }
	      if (delta != null) {
	        evt.preventDefault();
	        if (evt.type === 'DOMMouseScroll') {
	          delta = delta * 40;
	        }
	        return this.search_results.scrollTop(delta + this.search_results.scrollTop());
	      }
	    };

	    Chosen.prototype.blur_test = function(evt) {
	      if (!this.active_field && this.container.hasClass("chosen-container-active")) {
	        return this.close_field();
	      }
	    };

	    Chosen.prototype.close_field = function() {
	      $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
	      this.active_field = false;
	      this.results_hide();
	      this.container.removeClass("chosen-container-active");
	      this.clear_backstroke();
	      this.show_search_field_default();
	      return this.search_field_scale();
	    };

	    Chosen.prototype.activate_field = function() {
	      this.container.addClass("chosen-container-active");
	      this.active_field = true;
	      this.search_field.val(this.search_field.val());
	      return this.search_field.focus();
	    };

	    Chosen.prototype.test_active_click = function(evt) {
	      var active_container;
	      active_container = $(evt.target).closest('.chosen-container');
	      if (active_container.length && this.container[0] === active_container[0]) {
	        return this.active_field = true;
	      } else {
	        return this.close_field();
	      }
	    };

	    Chosen.prototype.results_build = function() {
	      this.parsing = true;
	      this.selected_option_count = null;
	      this.results_data = SelectParser.select_to_array(this.form_field);
	      if (this.is_multiple) {
	        this.search_choices.find("li.search-choice").remove();
	      } else if (!this.is_multiple) {
	        this.single_set_selected_text();
	        if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
	          this.search_field[0].readOnly = true;
	          this.container.addClass("chosen-container-single-nosearch");
	        } else {
	          this.search_field[0].readOnly = false;
	          this.container.removeClass("chosen-container-single-nosearch");
	        }
	      }
	      this.update_results_content(this.results_option_build({
	        first: true
	      }));
	      this.search_field_disabled();
	      this.show_search_field_default();
	      this.search_field_scale();
	      return this.parsing = false;
	    };

	    Chosen.prototype.result_do_highlight = function(el) {
	      var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
	      if (el.length) {
	        this.result_clear_highlight();
	        this.result_highlight = el;
	        this.result_highlight.addClass("highlighted");
	        maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
	        visible_top = this.search_results.scrollTop();
	        visible_bottom = maxHeight + visible_top;
	        high_top = this.result_highlight.position().top + this.search_results.scrollTop();
	        high_bottom = high_top + this.result_highlight.outerHeight();
	        if (high_bottom >= visible_bottom) {
	          return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
	        } else if (high_top < visible_top) {
	          return this.search_results.scrollTop(high_top);
	        }
	      }
	    };

	    Chosen.prototype.result_clear_highlight = function() {
	      if (this.result_highlight) {
	        this.result_highlight.removeClass("highlighted");
	      }
	      return this.result_highlight = null;
	    };

	    Chosen.prototype.results_show = function() {
	      if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
	        this.form_field_jq.trigger("chosen:maxselected", {
	          chosen: this
	        });
	        return false;
	      }
	      this.container.addClass("chosen-with-drop");
	      this.results_showing = true;
	      this.search_field.focus();
	      this.search_field.val(this.search_field.val());
	      this.winnow_results();
	      return this.form_field_jq.trigger("chosen:showing_dropdown", {
	        chosen: this
	      });
	    };

	    Chosen.prototype.update_results_content = function(content) {
	      return this.search_results.html(content);
	    };

	    Chosen.prototype.results_hide = function() {
	      if (this.results_showing) {
	        this.result_clear_highlight();
	        this.container.removeClass("chosen-with-drop");
	        this.form_field_jq.trigger("chosen:hiding_dropdown", {
	          chosen: this
	        });
	      }
	      return this.results_showing = false;
	    };

	    Chosen.prototype.set_tab_index = function(el) {
	      var ti;
	      if (this.form_field.tabIndex) {
	        ti = this.form_field.tabIndex;
	        this.form_field.tabIndex = -1;
	        return this.search_field[0].tabIndex = ti;
	      }
	    };

	    Chosen.prototype.set_label_behavior = function() {
	      var _this = this;
	      this.form_field_label = this.form_field_jq.parents("label");
	      if (!this.form_field_label.length && this.form_field.id.length) {
	        this.form_field_label = $("label[for='" + this.form_field.id + "']");
	      }
	      if (this.form_field_label.length > 0) {
	        return this.form_field_label.bind('click.chosen', function(evt) {
	          if (_this.is_multiple) {
	            return _this.container_mousedown(evt);
	          } else {
	            return _this.activate_field();
	          }
	        });
	      }
	    };

	    Chosen.prototype.show_search_field_default = function() {
	      if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
	        this.search_field.val(this.default_text);
	        return this.search_field.addClass("default");
	      } else {
	        this.search_field.val("");
	        return this.search_field.removeClass("default");
	      }
	    };

	    Chosen.prototype.search_results_mouseup = function(evt) {
	      var target;
	      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
	      if (target.length) {
	        this.result_highlight = target;
	        this.result_select(evt);
	        return this.search_field.focus();
	      }
	    };

	    Chosen.prototype.search_results_mouseover = function(evt) {
	      var target;
	      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
	      if (target) {
	        return this.result_do_highlight(target);
	      }
	    };

	    Chosen.prototype.search_results_mouseout = function(evt) {
	      if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
	        return this.result_clear_highlight();
	      }
	    };

	    Chosen.prototype.choice_build = function(item) {
	      var choice, close_link,
	        _this = this;
	      choice = $('<li />', {
	        "class": "search-choice"
	      }).html("<span>" + item.html + "</span>");
	      if (item.disabled) {
	        choice.addClass('search-choice-disabled');
	      } else {
	        close_link = $('<a />', {
	          "class": 'search-choice-close',
	          'data-option-array-index': item.array_index
	        });
	        close_link.bind('click.chosen', function(evt) {
	          return _this.choice_destroy_link_click(evt);
	        });
	        choice.append(close_link);
	      }
	      return this.search_container.before(choice);
	    };

	    Chosen.prototype.choice_destroy_link_click = function(evt) {
	      evt.preventDefault();
	      evt.stopPropagation();
	      if (!this.is_disabled) {
	        return this.choice_destroy($(evt.target));
	      }
	    };

	    Chosen.prototype.choice_destroy = function(link) {
	      if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
	        this.show_search_field_default();
	        if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
	          this.results_hide();
	        }
	        link.parents('li').first().remove();
	        return this.search_field_scale();
	      }
	    };

	    Chosen.prototype.results_reset = function() {
	      this.reset_single_select_options();
	      this.form_field.options[0].selected = true;
	      this.single_set_selected_text();
	      this.show_search_field_default();
	      this.results_reset_cleanup();
	      this.form_field_jq.trigger("change");
	      if (this.active_field) {
	        return this.results_hide();
	      }
	    };

	    Chosen.prototype.results_reset_cleanup = function() {
	      this.current_selectedIndex = this.form_field.selectedIndex;
	      return this.selected_item.find("abbr").remove();
	    };

	    Chosen.prototype.result_select = function(evt) {
	      var high, item;
	      if (this.result_highlight) {
	        high = this.result_highlight;
	        this.result_clear_highlight();
	        if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
	          this.form_field_jq.trigger("chosen:maxselected", {
	            chosen: this
	          });
	          return false;
	        }
	        if (this.is_multiple) {
	          high.removeClass("active-result");
	        } else {
	          this.reset_single_select_options();
	        }
	        item = this.results_data[high[0].getAttribute("data-option-array-index")];
	        item.selected = true;
	        this.form_field.options[item.options_index].selected = true;
	        this.selected_option_count = null;
	        if (this.is_multiple) {
	          this.choice_build(item);
	        } else {
	          this.single_set_selected_text(item.text);
	        }
	        if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
	          this.results_hide();
	        }
	        this.search_field.val("");
	        if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
	          this.form_field_jq.trigger("change", {
	            'selected': this.form_field.options[item.options_index].value
	          });
	        }
	        this.current_selectedIndex = this.form_field.selectedIndex;
	        return this.search_field_scale();
	      }
	    };

	    Chosen.prototype.single_set_selected_text = function(text) {
	      if (text == null) {
	        text = this.default_text;
	      }
	      if (text === this.default_text) {
	        this.selected_item.addClass("chosen-default");
	      } else {
	        this.single_deselect_control_build();
	        this.selected_item.removeClass("chosen-default");
	      }
	      return this.selected_item.find("span").text(text);
	    };

	    Chosen.prototype.result_deselect = function(pos) {
	      var result_data;
	      result_data = this.results_data[pos];
	      if (!this.form_field.options[result_data.options_index].disabled) {
	        result_data.selected = false;
	        this.form_field.options[result_data.options_index].selected = false;
	        this.selected_option_count = null;
	        this.result_clear_highlight();
	        if (this.results_showing) {
	          this.winnow_results();
	        }
	        this.form_field_jq.trigger("change", {
	          deselected: this.form_field.options[result_data.options_index].value
	        });
	        this.search_field_scale();
	        return true;
	      } else {
	        return false;
	      }
	    };

	    Chosen.prototype.single_deselect_control_build = function() {
	      if (!this.allow_single_deselect) {
	        return;
	      }
	      if (!this.selected_item.find("abbr").length) {
	        this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
	      }
	      return this.selected_item.addClass("chosen-single-with-deselect");
	    };

	    Chosen.prototype.get_search_text = function() {
	      if (this.search_field.val() === this.default_text) {
	        return "";
	      } else {
	        return $('<div/>').text($.trim(this.search_field.val())).html();
	      }
	    };

	    Chosen.prototype.winnow_results_set_highlight = function() {
	      var do_high, selected_results;
	      selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
	      do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
	      if (do_high != null) {
	        return this.result_do_highlight(do_high);
	      }
	    };

	    Chosen.prototype.no_results = function(terms) {
	      var no_results_html;
	      no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
	      no_results_html.find("span").first().html(terms);
	      this.search_results.append(no_results_html);
	      return this.form_field_jq.trigger("chosen:no_results", {
	        chosen: this
	      });
	    };

	    Chosen.prototype.no_results_clear = function() {
	      return this.search_results.find(".no-results").remove();
	    };

	    Chosen.prototype.keydown_arrow = function() {
	      var next_sib;
	      if (this.results_showing && this.result_highlight) {
	        next_sib = this.result_highlight.nextAll("li.active-result").first();
	        if (next_sib) {
	          return this.result_do_highlight(next_sib);
	        }
	      } else {
	        return this.results_show();
	      }
	    };

	    Chosen.prototype.keyup_arrow = function() {
	      var prev_sibs;
	      if (!this.results_showing && !this.is_multiple) {
	        return this.results_show();
	      } else if (this.result_highlight) {
	        prev_sibs = this.result_highlight.prevAll("li.active-result");
	        if (prev_sibs.length) {
	          return this.result_do_highlight(prev_sibs.first());
	        } else {
	          if (this.choices_count() > 0) {
	            this.results_hide();
	          }
	          return this.result_clear_highlight();
	        }
	      }
	    };

	    Chosen.prototype.keydown_backstroke = function() {
	      var next_available_destroy;
	      if (this.pending_backstroke) {
	        this.choice_destroy(this.pending_backstroke.find("a").first());
	        return this.clear_backstroke();
	      } else {
	        next_available_destroy = this.search_container.siblings("li.search-choice").last();
	        if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
	          this.pending_backstroke = next_available_destroy;
	          if (this.single_backstroke_delete) {
	            return this.keydown_backstroke();
	          } else {
	            return this.pending_backstroke.addClass("search-choice-focus");
	          }
	        }
	      }
	    };

	    Chosen.prototype.clear_backstroke = function() {
	      if (this.pending_backstroke) {
	        this.pending_backstroke.removeClass("search-choice-focus");
	      }
	      return this.pending_backstroke = null;
	    };

	    Chosen.prototype.keydown_checker = function(evt) {
	      var stroke, _ref1;
	      stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
	      this.search_field_scale();
	      if (stroke !== 8 && this.pending_backstroke) {
	        this.clear_backstroke();
	      }
	      switch (stroke) {
	        case 8:
	          this.backstroke_length = this.search_field.val().length;
	          break;
	        case 9:
	          if (this.results_showing && !this.is_multiple) {
	            this.result_select(evt);
	          }
	          this.mouse_on_container = false;
	          break;
	        case 13:
	          if (this.results_showing) {
	            evt.preventDefault();
	          }
	          break;
	        case 32:
	          if (this.disable_search) {
	            evt.preventDefault();
	          }
	          break;
	        case 38:
	          evt.preventDefault();
	          this.keyup_arrow();
	          break;
	        case 40:
	          evt.preventDefault();
	          this.keydown_arrow();
	          break;
	      }
	    };

	    Chosen.prototype.search_field_scale = function() {
	      var div, f_width, h, style, style_block, styles, w, _i, _len;
	      if (this.is_multiple) {
	        h = 0;
	        w = 0;
	        style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
	        styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
	        for (_i = 0, _len = styles.length; _i < _len; _i++) {
	          style = styles[_i];
	          style_block += style + ":" + this.search_field.css(style) + ";";
	        }
	        div = $('<div />', {
	          'style': style_block
	        });
	        div.text(this.search_field.val());
	        $('body').append(div);
	        w = div.width() + 25;
	        div.remove();
	        f_width = this.container.outerWidth();
	        if (w > f_width - 10) {
	          w = f_width - 10;
	        }
	        return this.search_field.css({
	          'width': w + 'px'
	        });
	      }
	    };

	    return Chosen;

	  })(AbstractChosen);

	}).call(this);


/***/ },
/* 383 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _moment = __webpack_require__(215);

	var _moment2 = _interopRequireDefault(_moment);

	__webpack_require__(384);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	// #
	// # Pour les datetimepicker et les datepicker, les options disponibles
	// # en data attributes sont:
	// #
	// # - data-date-without="["#date_1", "#date_2",...]" => enleve les dates passées en parametre
	// # - data-date-with="["#date_1", "#date_2",...]" => ne garde que les dates passées en parametre
	// # - data-date-min="#date" => Pose une date minimum
	// # - data-date-max="#date" => Pose une date maximum
	// #
	// # Rappel:
	// # Pour utiliser avec SimpleForm, utiliser 'as: :datetimepicker'
	// # Pour passer des data-attributes avec SimpleForm, utiliser 'input_html'.
	// # ex: (...), as: :datetimepicker, input_html: {:'data-date-min' => '2015-10-02', :'data-date-max' => '2015-10-09'}

	var SimpleFormDatePicker = function () {
	  function SimpleFormDatePicker() {
	    var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

	    _classCallCheck(this, SimpleFormDatePicker);

	    this.DEFAULTS = {
	      excludeDateAttr: 'data-date-without',
	      includeDateAttr: 'data-date-with',
	      minDateAttr: 'data-date-min',
	      maxDateAttr: 'data-date-max',
	      noWeekends: 'data-date-no-weekends'
	    };

	    this.opts = _lodash2.default.merge(this.DEFAULTS, opts);

	    if (_jquery2.default.fn.datetimepicker) {
	      this._setDefaults();
	      this._bindAll();
	      (0, _jquery2.default)(document).on('nested:fieldAdded', this._bindAll.bind(this));
	      (0, _jquery2.default)(document).on('cocoon:after-insert', this._bindAll.bind(this));
	    }
	  }

	  _createClass(SimpleFormDatePicker, [{
	    key: '_bindAll',
	    value: function _bindAll() {
	      this._bindDateTimePicker("input.datetimepicker");
	      this._bindDatePicker("input.datepicker");
	    }
	  }, {
	    key: '_setDefaults',
	    value: function _setDefaults() {
	      _lodash2.default.merge(_jquery2.default.fn.datetimepicker.defaults, {
	        icons: {
	          time: 'icon-clock-3',
	          date: 'icon-calendar-1',
	          up: 'icon-arrow-9',
	          down: 'icon-arrow-10',
	          previous: 'icon-arrow-7',
	          next: 'icon-arrow-8',
	          today: 'icon-target',
	          clear: 'icon-bin-2'
	        },
	        useStrict: false,
	        sideBySide: false,
	        useCurrent: false
	      });
	    }
	  }, {
	    key: '_bindDateTimePicker',
	    value: function _bindDateTimePicker(tag) {
	      var _this = this;

	      (0, _jquery2.default)(tag).each(function (__, e) {
	        (0, _jquery2.default)(e).datetimepicker(_this._computeOptions(e));
	      });
	    }
	  }, {
	    key: '_bindDatePicker',
	    value: function _bindDatePicker(tag) {
	      var _this2 = this;

	      (0, _jquery2.default)(tag).each(function (__, e) {
	        (0, _jquery2.default)(e).datetimepicker(_this2._computeOptions(e));
	      });
	    }
	  }, {
	    key: '_computeOptions',
	    value: function _computeOptions(elt) {
	      var o = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

	      if ((0, _jquery2.default)(elt).attr(this.opts.excludeDateAttr)) {
	        var disabled_dates = _jquery2.default.parseJSON((0, _jquery2.default)(elt).attr(this.opts.excludeDateAttr));

	        o.disabledDates = _lodash2.default.map(disabled_dates, function (e) {
	          return (0, _moment2.default)(e);
	        });
	      }

	      if ((0, _jquery2.default)(elt).attr(this.opts.includeDateAttr)) {
	        var enabled_dates = _jquery2.default.parseJSON((0, _jquery2.default)(elt).attr(this.opts.includeDateAttr));

	        o.enabledDates = _lodash2.default.map(enabled_dates, function (e) {
	          return (0, _moment2.default)(e);
	        });
	      }

	      if ((0, _jquery2.default)(elt).attr(this.opts.minDateAttr)) o.minDate = (0, _moment2.default)((0, _jquery2.default)(elt).attr(this.opts.minDateAttr));
	      if ((0, _jquery2.default)(elt).attr(this.opts.maxDateAttr)) o.maxDate = (0, _moment2.default)((0, _jquery2.default)(elt).attr(this.opts.maxDateAttr));
	      if ((0, _jquery2.default)(elt).attr(this.opts.noWeekends) != undefined) o.daysOfWeekDisabled = [0, 6];
	      return o;
	    }
	  }]);

	  return SimpleFormDatePicker;
	}();

	exports.default = SimpleFormDatePicker;

/***/ },
/* 384 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! version : 4.17.37
	 =========================================================
	 bootstrap-datetimejs
	 https://github.com/Eonasdan/bootstrap-datetimepicker
	 Copyright (c) 2015 Jonathan Peterson
	 =========================================================
	 */
	/*
	 The MIT License (MIT)

	 Copyright (c) 2015 Jonathan Peterson

	 Permission is hereby granted, free of charge, to any person obtaining a copy
	 of this software and associated documentation files (the "Software"), to deal
	 in the Software without restriction, including without limitation the rights
	 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	 copies of the Software, and to permit persons to whom the Software is
	 furnished to do so, subject to the following conditions:

	 The above copyright notice and this permission notice shall be included in
	 all copies or substantial portions of the Software.

	 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	 THE SOFTWARE.
	 */
	/*global define:false */
	/*global exports:false */
	/*global require:false */
	/*global jQuery:false */
	/*global moment:false */
	(function (factory) {
	    'use strict';
	    if (true) {
	        // AMD is used - Register as an anonymous module.
	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(5), __webpack_require__(215)], __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 {
	        // Neither AMD nor CommonJS used. Use global variables.
	        if (typeof jQuery === 'undefined') {
	            throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
	        }
	        if (typeof moment === 'undefined') {
	            throw 'bootstrap-datetimepicker requires Moment.js to be loaded first';
	        }
	        factory(jQuery, moment);
	    }
	}(function ($, moment) {
	    'use strict';
	    if (!moment) {
	        throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first');
	    }

	    var dateTimePicker = function (element, options) {
	        var picker = {},
	            date,
	            viewDate,
	            unset = true,
	            input,
	            component = false,
	            widget = false,
	            use24Hours,
	            minViewModeNumber = 0,
	            actualFormat,
	            parseFormats,
	            currentViewMode,
	            datePickerModes = [
	                {
	                    clsName: 'days',
	                    navFnc: 'M',
	                    navStep: 1
	                },
	                {
	                    clsName: 'months',
	                    navFnc: 'y',
	                    navStep: 1
	                },
	                {
	                    clsName: 'years',
	                    navFnc: 'y',
	                    navStep: 10
	                },
	                {
	                    clsName: 'decades',
	                    navFnc: 'y',
	                    navStep: 100
	                }
	            ],
	            viewModes = ['days', 'months', 'years', 'decades'],
	            verticalModes = ['top', 'bottom', 'auto'],
	            horizontalModes = ['left', 'right', 'auto'],
	            toolbarPlacements = ['default', 'top', 'bottom'],
	            keyMap = {
	                'up': 38,
	                38: 'up',
	                'down': 40,
	                40: 'down',
	                'left': 37,
	                37: 'left',
	                'right': 39,
	                39: 'right',
	                'tab': 9,
	                9: 'tab',
	                'escape': 27,
	                27: 'escape',
	                'enter': 13,
	                13: 'enter',
	                'pageUp': 33,
	                33: 'pageUp',
	                'pageDown': 34,
	                34: 'pageDown',
	                'shift': 16,
	                16: 'shift',
	                'control': 17,
	                17: 'control',
	                'space': 32,
	                32: 'space',
	                't': 84,
	                84: 't',
	                'delete': 46,
	                46: 'delete'
	            },
	            keyState = {},

	            /********************************************************************************
	             *
	             * Private functions
	             *
	             ********************************************************************************/
	            getMoment = function (d) {
	                var tzEnabled = false,
	                    returnMoment,
	                    currentZoneOffset,
	                    incomingZoneOffset,
	                    timeZoneIndicator,
	                    dateWithTimeZoneInfo;

	                if (moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '') {
	                    tzEnabled = true;
	                }
	                if (d === undefined || d === null) {
	                    if (tzEnabled) {
	                        returnMoment = moment().tz(options.timeZone).startOf('d');
	                    } else {
	                        returnMoment = moment().startOf('d');
	                    }
	                } else {
	                    if (tzEnabled) {
	                        currentZoneOffset = moment().tz(options.timeZone).utcOffset();
	                        incomingZoneOffset = moment(d, parseFormats, options.useStrict).utcOffset();
	                        if (incomingZoneOffset !== currentZoneOffset) {
	                            timeZoneIndicator = moment().tz(options.timeZone).format('Z');
	                            dateWithTimeZoneInfo = moment(d, parseFormats, options.useStrict).format('YYYY-MM-DD[T]HH:mm:ss') + timeZoneIndicator;
	                            returnMoment = moment(dateWithTimeZoneInfo, parseFormats, options.useStrict).tz(options.timeZone);
	                        } else {
	                            returnMoment = moment(d, parseFormats, options.useStrict).tz(options.timeZone);
	                        }
	                    } else {
	                        returnMoment = moment(d, parseFormats, options.useStrict);
	                    }
	                }
	                return returnMoment;
	            },
	            isEnabled = function (granularity) {
	                if (typeof granularity !== 'string' || granularity.length > 1) {
	                    throw new TypeError('isEnabled expects a single character string parameter');
	                }
	                switch (granularity) {
	                    case 'y':
	                        return actualFormat.indexOf('Y') !== -1;
	                    case 'M':
	                        return actualFormat.indexOf('M') !== -1;
	                    case 'd':
	                        return actualFormat.toLowerCase().indexOf('d') !== -1;
	                    case 'h':
	                    case 'H':
	                        return actualFormat.toLowerCase().indexOf('h') !== -1;
	                    case 'm':
	                        return actualFormat.indexOf('m') !== -1;
	                    case 's':
	                        return actualFormat.indexOf('s') !== -1;
	                    default:
	                        return false;
	                }
	            },
	            hasTime = function () {
	                return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
	            },

	            hasDate = function () {
	                return (isEnabled('y') || isEnabled('M') || isEnabled('d'));
	            },

	            getDatePickerTemplate = function () {
	                var headTemplate = $('<thead>')
	                        .append($('<tr>')
	                            .append($('<th>').addClass('prev').attr('data-action', 'previous')
	                                .append($('<span>').addClass(options.icons.previous))
	                                )
	                            .append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5')))
	                            .append($('<th>').addClass('next').attr('data-action', 'next')
	                                .append($('<span>').addClass(options.icons.next))
	                                )
	                            ),
	                    contTemplate = $('<tbody>')
	                        .append($('<tr>')
	                            .append($('<td>').attr('colspan', (options.calendarWeeks ? '8' : '7')))
	                            );

	                return [
	                    $('<div>').addClass('datepicker-days')
	                        .append($('<table>').addClass('table-condensed')
	                            .append(headTemplate)
	                            .append($('<tbody>'))
	                            ),
	                    $('<div>').addClass('datepicker-months')
	                        .append($('<table>').addClass('table-condensed')
	                            .append(headTemplate.clone())
	                            .append(contTemplate.clone())
	                            ),
	                    $('<div>').addClass('datepicker-years')
	                        .append($('<table>').addClass('table-condensed')
	                            .append(headTemplate.clone())
	                            .append(contTemplate.clone())
	                            ),
	                    $('<div>').addClass('datepicker-decades')
	                        .append($('<table>').addClass('table-condensed')
	                            .append(headTemplate.clone())
	                            .append(contTemplate.clone())
	                            )
	                ];
	            },

	            getTimePickerMainTemplate = function () {
	                var topRow = $('<tr>'),
	                    middleRow = $('<tr>'),
	                    bottomRow = $('<tr>');

	                if (isEnabled('h')) {
	                    topRow.append($('<td>')
	                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour}).addClass('btn').attr('data-action', 'incrementHours')
	                            .append($('<span>').addClass(options.icons.up))));
	                    middleRow.append($('<td>')
	                        .append($('<span>').addClass('timepicker-hour').attr({'data-time-component':'hours', 'title': options.tooltips.pickHour}).attr('data-action', 'showHours')));
	                    bottomRow.append($('<td>')
	                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour}).addClass('btn').attr('data-action', 'decrementHours')
	                            .append($('<span>').addClass(options.icons.down))));
	                }
	                if (isEnabled('m')) {
	                    if (isEnabled('h')) {
	                        topRow.append($('<td>').addClass('separator'));
	                        middleRow.append($('<td>').addClass('separator').html(':'));
	                        bottomRow.append($('<td>').addClass('separator'));
	                    }
	                    topRow.append($('<td>')
	                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute}).addClass('btn').attr('data-action', 'incrementMinutes')
	                            .append($('<span>').addClass(options.icons.up))));
	                    middleRow.append($('<td>')
	                        .append($('<span>').addClass('timepicker-minute').attr({'data-time-component': 'minutes', 'title': options.tooltips.pickMinute}).attr('data-action', 'showMinutes')));
	                    bottomRow.append($('<td>')
	                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute}).addClass('btn').attr('data-action', 'decrementMinutes')
	                            .append($('<span>').addClass(options.icons.down))));
	                }
	                if (isEnabled('s')) {
	                    if (isEnabled('m')) {
	                        topRow.append($('<td>').addClass('separator'));
	                        middleRow.append($('<td>').addClass('separator').html(':'));
	                        bottomRow.append($('<td>').addClass('separator'));
	                    }
	                    topRow.append($('<td>')
	                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond}).addClass('btn').attr('data-action', 'incrementSeconds')
	                            .append($('<span>').addClass(options.icons.up))));
	                    middleRow.append($('<td>')
	                        .append($('<span>').addClass('timepicker-second').attr({'data-time-component': 'seconds', 'title': options.tooltips.pickSecond}).attr('data-action', 'showSeconds')));
	                    bottomRow.append($('<td>')
	                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond}).addClass('btn').attr('data-action', 'decrementSeconds')
	                            .append($('<span>').addClass(options.icons.down))));
	                }

	                if (!use24Hours) {
	                    topRow.append($('<td>').addClass('separator'));
	                    middleRow.append($('<td>')
	                        .append($('<button>').addClass('btn btn-primary').attr({'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod})));
	                    bottomRow.append($('<td>').addClass('separator'));
	                }

	                return $('<div>').addClass('timepicker-picker')
	                    .append($('<table>').addClass('table-condensed')
	                        .append([topRow, middleRow, bottomRow]));
	            },

	            getTimePickerTemplate = function () {
	                var hoursView = $('<div>').addClass('timepicker-hours')
	                        .append($('<table>').addClass('table-condensed')),
	                    minutesView = $('<div>').addClass('timepicker-minutes')
	                        .append($('<table>').addClass('table-condensed')),
	                    secondsView = $('<div>').addClass('timepicker-seconds')
	                        .append($('<table>').addClass('table-condensed')),
	                    ret = [getTimePickerMainTemplate()];

	                if (isEnabled('h')) {
	                    ret.push(hoursView);
	                }
	                if (isEnabled('m')) {
	                    ret.push(minutesView);
	                }
	                if (isEnabled('s')) {
	                    ret.push(secondsView);
	                }

	                return ret;
	            },

	            getToolbar = function () {
	                var row = [];
	                if (options.showTodayButton) {
	                    row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title': options.tooltips.today}).append($('<span>').addClass(options.icons.today))));
	                }
	                if (!options.sideBySide && hasDate() && hasTime()) {
	                    row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title': options.tooltips.selectTime}).append($('<span>').addClass(options.icons.time))));
	                }
	                if (options.showClear) {
	                    row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title': options.tooltips.clear}).append($('<span>').addClass(options.icons.clear))));
	                }
	                if (options.showClose) {
	                    row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title': options.tooltips.close}).append($('<span>').addClass(options.icons.close))));
	                }
	                return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
	            },

	            getTemplate = function () {
	                var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),
	                    dateView = $('<div>').addClass('datepicker').append(getDatePickerTemplate()),
	                    timeView = $('<div>').addClass('timepicker').append(getTimePickerTemplate()),
	                    content = $('<ul>').addClass('list-unstyled'),
	                    toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar());

	                if (options.inline) {
	                    template.removeClass('dropdown-menu');
	                }

	                if (use24Hours) {
	                    template.addClass('usetwentyfour');
	                }
	                if (isEnabled('s') && !use24Hours) {
	                    template.addClass('wider');
	                }

	                if (options.sideBySide && hasDate() && hasTime()) {
	                    template.addClass('timepicker-sbs');
	                    if (options.toolbarPlacement === 'top') {
	                        template.append(toolbar);
	                    }
	                    template.append(
	                        $('<div>').addClass('row')
	                            .append(dateView.addClass('col-md-6'))
	                            .append(timeView.addClass('col-md-6'))
	                    );
	                    if (options.toolbarPlacement === 'bottom') {
	                        template.append(toolbar);
	                    }
	                    return template;
	                }

	                if (options.toolbarPlacement === 'top') {
	                    content.append(toolbar);
	                }
	                if (hasDate()) {
	                    content.append($('<li>').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView));
	                }
	                if (options.toolbarPlacement === 'default') {
	                    content.append(toolbar);
	                }
	                if (hasTime()) {
	                    content.append($('<li>').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView));
	                }
	                if (options.toolbarPlacement === 'bottom') {
	                    content.append(toolbar);
	                }
	                return template.append(content);
	            },

	            dataToOptions = function () {
	                var eData,
	                    dataOptions = {};

	                if (element.is('input') || options.inline) {
	                    eData = element.data();
	                } else {
	                    eData = element.find('input').data();
	                }

	                if (eData.dateOptions && eData.dateOptions instanceof Object) {
	                    dataOptions = $.extend(true, dataOptions, eData.dateOptions);
	                }

	                $.each(options, function (key) {
	                    var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
	                    if (eData[attributeName] !== undefined) {
	                        dataOptions[key] = eData[attributeName];
	                    }
	                });
	                return dataOptions;
	            },

	            place = function () {
	                var position = (component || element).position(),
	                    offset = (component || element).offset(),
	                    vertical = options.widgetPositioning.vertical,
	                    horizontal = options.widgetPositioning.horizontal,
	                    parent;

	                if (options.widgetParent) {
	                    parent = options.widgetParent.append(widget);
	                } else if (element.is('input')) {
	                    parent = element.after(widget).parent();
	                } else if (options.inline) {
	                    parent = element.append(widget);
	                    return;
	                } else {
	                    parent = element;
	                    element.children().first().after(widget);
	                }

	                // Top and bottom logic
	                if (vertical === 'auto') {
	                    if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() &&
	                        widget.height() + element.outerHeight() < offset.top) {
	                        vertical = 'top';
	                    } else {
	                        vertical = 'bottom';
	                    }
	                }

	                // Left and right logic
	                if (horizontal === 'auto') {
	                    if (parent.width() < offset.left + widget.outerWidth() / 2 &&
	                        offset.left + widget.outerWidth() > $(window).width()) {
	                        horizontal = 'right';
	                    } else {
	                        horizontal = 'left';
	                    }
	                }

	                if (vertical === 'top') {
	                    widget.addClass('top').removeClass('bottom');
	                } else {
	                    widget.addClass('bottom').removeClass('top');
	                }

	                if (horizontal === 'right') {
	                    widget.addClass('pull-right');
	                } else {
	                    widget.removeClass('pull-right');
	                }

	                // find the first parent element that has a relative css positioning
	                if (parent.css('position') !== 'relative') {
	                    parent = parent.parents().filter(function () {
	                        return $(this).css('position') === 'relative';
	                    }).first();
	                }

	                if (parent.length === 0) {
	                    throw new Error('datetimepicker component should be placed within a relative positioned container');
	                }

	                widget.css({
	                    top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
	                    bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
	                    left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
	                    right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
	                });
	            },

	            notifyEvent = function (e) {
	                if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) {
	                    return;
	                }
	                element.trigger(e);
	            },

	            viewUpdate = function (e) {
	                if (e === 'y') {
	                    e = 'YYYY';
	                }
	                notifyEvent({
	                    type: 'dp.update',
	                    change: e,
	                    viewDate: viewDate.clone()
	                });
	            },

	            showMode = function (dir) {
	                if (!widget) {
	                    return;
	                }
	                if (dir) {
	                    currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
	                }
	                widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
	            },

	            fillDow = function () {
	                var row = $('<tr>'),
	                    currentDate = viewDate.clone().startOf('w').startOf('d');

	                if (options.calendarWeeks === true) {
	                    row.append($('<th>').addClass('cw').text('#'));
	                }

	                while (currentDate.isBefore(viewDate.clone().endOf('w'))) {
	                    row.append($('<th>').addClass('dow').text(currentDate.format('dd')));
	                    currentDate.add(1, 'd');
	                }
	                widget.find('.datepicker-days thead').append(row);
	            },

	            isInDisabledDates = function (testDate) {
	                return options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
	            },

	            isInEnabledDates = function (testDate) {
	                return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
	            },

	            isInDisabledHours = function (testDate) {
	                return options.disabledHours[testDate.format('H')] === true;
	            },

	            isInEnabledHours = function (testDate) {
	                return options.enabledHours[testDate.format('H')] === true;
	            },

	            isValid = function (targetMoment, granularity) {
	                if (!targetMoment.isValid()) {
	                    return false;
	                }
	                if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) {
	                    return false;
	                }
	                if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) {
	                    return false;
	                }
	                if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
	                    return false;
	                }
	                if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
	                    return false;
	                }
	                if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
	                    return false;
	                }
	                if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
	                    return false;
	                }
	                if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
	                    return false;
	                }
	                if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
	                    var found = false;
	                    $.each(options.disabledTimeIntervals, function () {
	                        if (targetMoment.isBetween(this[0], this[1])) {
	                            found = true;
	                            return false;
	                        }
	                    });
	                    if (found) {
	                        return false;
	                    }
	                }
	                return true;
	            },

	            fillMonths = function () {
	                var spans = [],
	                    monthsShort = viewDate.clone().startOf('y').startOf('d');
	                while (monthsShort.isSame(viewDate, 'y')) {
	                    spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
	                    monthsShort.add(1, 'M');
	                }
	                widget.find('.datepicker-months td').empty().append(spans);
	            },

	            updateMonths = function () {
	                var monthsView = widget.find('.datepicker-months'),
	                    monthsViewHeader = monthsView.find('th'),
	                    months = monthsView.find('tbody').find('span');

	                monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear);
	                monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear);
	                monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear);

	                monthsView.find('.disabled').removeClass('disabled');

	                if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
	                    monthsViewHeader.eq(0).addClass('disabled');
	                }

	                monthsViewHeader.eq(1).text(viewDate.year());

	                if (!isValid(viewDate.clone().add(1, 'y'), 'y')) {
	                    monthsViewHeader.eq(2).addClass('disabled');
	                }

	                months.removeClass('active');
	                if (date.isSame(viewDate, 'y') && !unset) {
	                    months.eq(date.month()).addClass('active');
	                }

	                months.each(function (index) {
	                    if (!isValid(viewDate.clone().month(index), 'M')) {
	                        $(this).addClass('disabled');
	                    }
	                });
	            },

	            updateYears = function () {
	                var yearsView = widget.find('.datepicker-years'),
	                    yearsViewHeader = yearsView.find('th'),
	                    startYear = viewDate.clone().subtract(5, 'y'),
	                    endYear = viewDate.clone().add(6, 'y'),
	                    html = '';

	                yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevDecade);
	                yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade);
	                yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextDecade);

	                yearsView.find('.disabled').removeClass('disabled');

	                if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
	                    yearsViewHeader.eq(0).addClass('disabled');
	                }

	                yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year());

	                if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) {
	                    yearsViewHeader.eq(2).addClass('disabled');
	                }

	                while (!startYear.isAfter(endYear, 'y')) {
	                    html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
	                    startYear.add(1, 'y');
	                }

	                yearsView.find('td').html(html);
	            },

	            updateDecades = function () {
	                var decadesView = widget.find('.datepicker-decades'),
	                    decadesViewHeader = decadesView.find('th'),
	                    startDecade = moment({y: viewDate.year() - (viewDate.year() % 100) - 1}),
	                    endDecade = startDecade.clone().add(100, 'y'),
	                    startedAt = startDecade.clone(),
	                    html = '';

	                decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
	                decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury);

	                decadesView.find('.disabled').removeClass('disabled');

	                if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
	                    decadesViewHeader.eq(0).addClass('disabled');
	                }

	                decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());

	                if (startDecade.isSame(moment({y: 2000})) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
	                    decadesViewHeader.eq(2).addClass('disabled');
	                }

	                while (!startDecade.isAfter(endDecade, 'y')) {
	                    html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') +
	                        (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
	                    startDecade.add(12, 'y');
	                }
	                html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even

	                decadesView.find('td').html(html);
	                decadesViewHeader.eq(1).text((startedAt.year() + 1) + '-' + (startDecade.year()));
	            },

	            fillDate = function () {
	                var daysView = widget.find('.datepicker-days'),
	                    daysViewHeader = daysView.find('th'),
	                    currentDate,
	                    html = [],
	                    row,
	                    clsName,
	                    i;

	                if (!hasDate()) {
	                    return;
	                }

	                daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth);
	                daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth);
	                daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth);

	                daysView.find('.disabled').removeClass('disabled');
	                daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));

	                if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) {
	                    daysViewHeader.eq(0).addClass('disabled');
	                }
	                if (!isValid(viewDate.clone().add(1, 'M'), 'M')) {
	                    daysViewHeader.eq(2).addClass('disabled');
	                }

	                currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');

	                for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
	                    if (currentDate.weekday() === 0) {
	                        row = $('<tr>');
	                        if (options.calendarWeeks) {
	                            row.append('<td class="cw">' + currentDate.week() + '</td>');
	                        }
	                        html.push(row);
	                    }
	                    clsName = '';
	                    if (currentDate.isBefore(viewDate, 'M')) {
	                        clsName += ' old';
	                    }
	                    if (currentDate.isAfter(viewDate, 'M')) {
	                        clsName += ' new';
	                    }
	                    if (currentDate.isSame(date, 'd') && !unset) {
	                        clsName += ' active';
	                    }
	                    if (!isValid(currentDate, 'd')) {
	                        clsName += ' disabled';
	                    }
	                    if (currentDate.isSame(getMoment(), 'd')) {
	                        clsName += ' today';
	                    }
	                    if (currentDate.day() === 0 || currentDate.day() === 6) {
	                        clsName += ' weekend';
	                    }
	                    row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="day' + clsName + '">' + currentDate.date() + '</td>');
	                    currentDate.add(1, 'd');
	                }

	                daysView.find('tbody').empty().append(html);

	                updateMonths();

	                updateYears();

	                updateDecades();
	            },

	            fillHours = function () {
	                var table = widget.find('.timepicker-hours table'),
	                    currentHour = viewDate.clone().startOf('d'),
	                    html = [],
	                    row = $('<tr>');

	                if (viewDate.hour() > 11 && !use24Hours) {
	                    currentHour.hour(12);
	                }
	                while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) {
	                    if (currentHour.hour() % 4 === 0) {
	                        row = $('<tr>');
	                        html.push(row);
	                    }
	                    row.append('<td data-action="selectHour" class="hour' + (!isValid(currentHour, 'h') ? ' disabled' : '') + '">' + currentHour.format(use24Hours ? 'HH' : 'hh') + '</td>');
	                    currentHour.add(1, 'h');
	                }
	                table.empty().append(html);
	            },

	            fillMinutes = function () {
	                var table = widget.find('.timepicker-minutes table'),
	                    currentMinute = viewDate.clone().startOf('h'),
	                    html = [],
	                    row = $('<tr>'),
	                    step = options.stepping === 1 ? 5 : options.stepping;

	                while (viewDate.isSame(currentMinute, 'h')) {
	                    if (currentMinute.minute() % (step * 4) === 0) {
	                        row = $('<tr>');
	                        html.push(row);
	                    }
	                    row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>');
	                    currentMinute.add(step, 'm');
	                }
	                table.empty().append(html);
	            },

	            fillSeconds = function () {
	                var table = widget.find('.timepicker-seconds table'),
	                    currentSecond = viewDate.clone().startOf('m'),
	                    html = [],
	                    row = $('<tr>');

	                while (viewDate.isSame(currentSecond, 'm')) {
	                    if (currentSecond.second() % 20 === 0) {
	                        row = $('<tr>');
	                        html.push(row);
	                    }
	                    row.append('<td data-action="selectSecond" class="second' + (!isValid(currentSecond, 's') ? ' disabled' : '') + '">' + currentSecond.format('ss') + '</td>');
	                    currentSecond.add(5, 's');
	                }

	                table.empty().append(html);
	            },

	            fillTime = function () {
	                var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]');

	                if (!use24Hours) {
	                    toggle = widget.find('.timepicker [data-action=togglePeriod]');
	                    newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');

	                    toggle.text(date.format('A'));

	                    if (isValid(newDate, 'h')) {
	                        toggle.removeClass('disabled');
	                    } else {
	                        toggle.addClass('disabled');
	                    }
	                }
	                timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
	                timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
	                timeComponents.filter('[data-time-component=seconds]').text(date.format('ss'));

	                fillHours();
	                fillMinutes();
	                fillSeconds();
	            },

	            update = function () {
	                if (!widget) {
	                    return;
	                }
	                fillDate();
	                fillTime();
	            },

	            setValue = function (targetMoment) {
	                var oldDate = unset ? null : date;

	                // case of calling setValue(null or false)
	                if (!targetMoment) {
	                    unset = true;
	                    input.val('');
	                    element.data('date', '');
	                    notifyEvent({
	                        type: 'dp.change',
	                        date: false,
	                        oldDate: oldDate
	                    });
	                    update();
	                    return;
	                }

	                targetMoment = targetMoment.clone().locale(options.locale);

	                if (options.stepping !== 1) {
	                    targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0);
	                }

	                if (isValid(targetMoment)) {
	                    date = targetMoment;
	                    viewDate = date.clone();
	                    input.val(date.format(actualFormat));
	                    element.data('date', date.format(actualFormat));
	                    unset = false;
	                    update();
	                    notifyEvent({
	                        type: 'dp.change',
	                        date: date.clone(),
	                        oldDate: oldDate
	                    });
	                } else {
	                    if (!options.keepInvalid) {
	                        input.val(unset ? '' : date.format(actualFormat));
	                    }
	                    notifyEvent({
	                        type: 'dp.error',
	                        date: targetMoment
	                    });
	                }
	            },

	            hide = function () {
	                ///<summary>Hides the widget. Possibly will emit dp.hide</summary>
	                var transitioning = false;
	                if (!widget) {
	                    return picker;
	                }
	                // Ignore event if in the middle of a picker transition
	                widget.find('.collapse').each(function () {
	                    var collapseData = $(this).data('collapse');
	                    if (collapseData && collapseData.transitioning) {
	                        transitioning = true;
	                        return false;
	                    }
	                    return true;
	                });
	                if (transitioning) {
	                    return picker;
	                }
	                if (component && component.hasClass('btn')) {
	                    component.toggleClass('active');
	                }
	                widget.hide();

	                $(window).off('resize', place);
	                widget.off('click', '[data-action]');
	                widget.off('mousedown', false);

	                widget.remove();
	                widget = false;

	                notifyEvent({
	                    type: 'dp.hide',
	                    date: date.clone()
	                });

	                input.blur();

	                return picker;
	            },

	            clear = function () {
	                setValue(null);
	            },

	            /********************************************************************************
	             *
	             * Widget UI interaction functions
	             *
	             ********************************************************************************/
	            actions = {
	                next: function () {
	                    var navFnc = datePickerModes[currentViewMode].navFnc;
	                    viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
	                    fillDate();
	                    viewUpdate(navFnc);
	                },

	                previous: function () {
	                    var navFnc = datePickerModes[currentViewMode].navFnc;
	                    viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
	                    fillDate();
	                    viewUpdate(navFnc);
	                },

	                pickerSwitch: function () {
	                    showMode(1);
	                },

	                selectMonth: function (e) {
	                    var month = $(e.target).closest('tbody').find('span').index($(e.target));
	                    viewDate.month(month);
	                    if (currentViewMode === minViewModeNumber) {
	                        setValue(date.clone().year(viewDate.year()).month(viewDate.month()));
	                        if (!options.inline) {
	                            hide();
	                        }
	                    } else {
	                        showMode(-1);
	                        fillDate();
	                    }
	                    viewUpdate('M');
	                },

	                selectYear: function (e) {
	                    var year = parseInt($(e.target).text(), 10) || 0;
	                    viewDate.year(year);
	                    if (currentViewMode === minViewModeNumber) {
	                        setValue(date.clone().year(viewDate.year()));
	                        if (!options.inline) {
	                            hide();
	                        }
	                    } else {
	                        showMode(-1);
	                        fillDate();
	                    }
	                    viewUpdate('YYYY');
	                },

	                selectDecade: function (e) {
	                    var year = parseInt($(e.target).data('selection'), 10) || 0;
	                    viewDate.year(year);
	                    if (currentViewMode === minViewModeNumber) {
	                        setValue(date.clone().year(viewDate.year()));
	                        if (!options.inline) {
	                            hide();
	                        }
	                    } else {
	                        showMode(-1);
	                        fillDate();
	                    }
	                    viewUpdate('YYYY');
	                },

	                selectDay: function (e) {
	                    var day = viewDate.clone();
	                    if ($(e.target).is('.old')) {
	                        day.subtract(1, 'M');
	                    }
	                    if ($(e.target).is('.new')) {
	                        day.add(1, 'M');
	                    }
	                    setValue(day.date(parseInt($(e.target).text(), 10)));
	                    if (!hasTime() && !options.keepOpen && !options.inline) {
	                        hide();
	                    }
	                },

	                incrementHours: function () {
	                    var newDate = date.clone().add(1, 'h');
	                    if (isValid(newDate, 'h')) {
	                        setValue(newDate);
	                    }
	                },

	                incrementMinutes: function () {
	                    var newDate = date.clone().add(options.stepping, 'm');
	                    if (isValid(newDate, 'm')) {
	                        setValue(newDate);
	                    }
	                },

	                incrementSeconds: function () {
	                    var newDate = date.clone().add(1, 's');
	                    if (isValid(newDate, 's')) {
	                        setValue(newDate);
	                    }
	                },

	                decrementHours: function () {
	                    var newDate = date.clone().subtract(1, 'h');
	                    if (isValid(newDate, 'h')) {
	                        setValue(newDate);
	                    }
	                },

	                decrementMinutes: function () {
	                    var newDate = date.clone().subtract(options.stepping, 'm');
	                    if (isValid(newDate, 'm')) {
	                        setValue(newDate);
	                    }
	                },

	                decrementSeconds: function () {
	                    var newDate = date.clone().subtract(1, 's');
	                    if (isValid(newDate, 's')) {
	                        setValue(newDate);
	                    }
	                },

	                togglePeriod: function () {
	                    setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'));
	                },

	                togglePicker: function (e) {
	                    var $this = $(e.target),
	                        $parent = $this.closest('ul'),
	                        expanded = $parent.find('.in'),
	                        closed = $parent.find('.collapse:not(.in)'),
	                        collapseData;

	                    if (expanded && expanded.length) {
	                        collapseData = expanded.data('collapse');
	                        if (collapseData && collapseData.transitioning) {
	                            return;
	                        }
	                        if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it
	                            expanded.collapse('hide');
	                            closed.collapse('show');
	                        } else { // otherwise just toggle in class on the two views
	                            expanded.removeClass('in');
	                            closed.addClass('in');
	                        }
	                        if ($this.is('span')) {
	                            $this.toggleClass(options.icons.time + ' ' + options.icons.date);
	                        } else {
	                            $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
	                        }

	                        // NOTE: uncomment if toggled state will be restored in show()
	                        //if (component) {
	                        //    component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
	                        //}
	                    }
	                },

	                showPicker: function () {
	                    widget.find('.timepicker > div:not(.timepicker-picker)').hide();
	                    widget.find('.timepicker .timepicker-picker').show();
	                },

	                showHours: function () {
	                    widget.find('.timepicker .timepicker-picker').hide();
	                    widget.find('.timepicker .timepicker-hours').show();
	                },

	                showMinutes: function () {
	                    widget.find('.timepicker .timepicker-picker').hide();
	                    widget.find('.timepicker .timepicker-minutes').show();
	                },

	                showSeconds: function () {
	                    widget.find('.timepicker .timepicker-picker').hide();
	                    widget.find('.timepicker .timepicker-seconds').show();
	                },

	                selectHour: function (e) {
	                    var hour = parseInt($(e.target).text(), 10);

	                    if (!use24Hours) {
	                        if (date.hours() >= 12) {
	                            if (hour !== 12) {
	                                hour += 12;
	                            }
	                        } else {
	                            if (hour === 12) {
	                                hour = 0;
	                            }
	                        }
	                    }
	                    setValue(date.clone().hours(hour));
	                    actions.showPicker.call(picker);
	                },

	                selectMinute: function (e) {
	                    setValue(date.clone().minutes(parseInt($(e.target).text(), 10)));
	                    actions.showPicker.call(picker);
	                },

	                selectSecond: function (e) {
	                    setValue(date.clone().seconds(parseInt($(e.target).text(), 10)));
	                    actions.showPicker.call(picker);
	                },

	                clear: clear,

	                today: function () {
	                    var todaysDate = getMoment();
	                    if (isValid(todaysDate, 'd')) {
	                        setValue(todaysDate);
	                    }
	                },

	                close: hide
	            },

	            doAction = function (e) {
	                if ($(e.currentTarget).is('.disabled')) {
	                    return false;
	                }
	                actions[$(e.currentTarget).data('action')].apply(picker, arguments);
	                return false;
	            },

	            show = function () {
	                ///<summary>Shows the widget. Possibly will emit dp.show and dp.change</summary>
	                var currentMoment,
	                    useCurrentGranularity = {
	                        'year': function (m) {
	                            return m.month(0).date(1).hours(0).seconds(0).minutes(0);
	                        },
	                        'month': function (m) {
	                            return m.date(1).hours(0).seconds(0).minutes(0);
	                        },
	                        'day': function (m) {
	                            return m.hours(0).seconds(0).minutes(0);
	                        },
	                        'hour': function (m) {
	                            return m.seconds(0).minutes(0);
	                        },
	                        'minute': function (m) {
	                            return m.seconds(0);
	                        }
	                    };

	                if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
	                    return picker;
	                }
	                if (input.val() !== undefined && input.val().trim().length !== 0) {
	                    setValue(parseInputDate(input.val().trim()));
	                } else if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
	                    currentMoment = getMoment();
	                    if (typeof options.useCurrent === 'string') {
	                        currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
	                    }
	                    setValue(currentMoment);
	                }

	                widget = getTemplate();

	                fillDow();
	                fillMonths();

	                widget.find('.timepicker-hours').hide();
	                widget.find('.timepicker-minutes').hide();
	                widget.find('.timepicker-seconds').hide();

	                update();
	                showMode();

	                $(window).on('resize', place);
	                widget.on('click', '[data-action]', doAction); // this handles clicks on the widget
	                widget.on('mousedown', false);

	                if (component && component.hasClass('btn')) {
	                    component.toggleClass('active');
	                }
	                widget.show();
	                place();

	                if (options.focusOnShow && !input.is(':focus')) {
	                    input.focus();
	                }

	                notifyEvent({
	                    type: 'dp.show'
	                });
	                return picker;
	            },

	            toggle = function () {
	                /// <summary>Shows or hides the widget</summary>
	                return (widget ? hide() : show());
	            },

	            parseInputDate = function (inputDate) {
	                if (options.parseInputDate === undefined) {
	                    if (moment.isMoment(inputDate) || inputDate instanceof Date) {
	                        inputDate = moment(inputDate);
	                    } else {
	                        inputDate = getMoment(inputDate);
	                    }
	                } else {
	                    inputDate = options.parseInputDate(inputDate);
	                }
	                inputDate.locale(options.locale);
	                return inputDate;
	            },

	            keydown = function (e) {
	                var handler = null,
	                    index,
	                    index2,
	                    pressedKeys = [],
	                    pressedModifiers = {},
	                    currentKey = e.which,
	                    keyBindKeys,
	                    allModifiersPressed,
	                    pressed = 'p';

	                keyState[currentKey] = pressed;

	                for (index in keyState) {
	                    if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
	                        pressedKeys.push(index);
	                        if (parseInt(index, 10) !== currentKey) {
	                            pressedModifiers[index] = true;
	                        }
	                    }
	                }

	                for (index in options.keyBinds) {
	                    if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') {
	                        keyBindKeys = index.split(' ');
	                        if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
	                            allModifiersPressed = true;
	                            for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
	                                if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) {
	                                    allModifiersPressed = false;
	                                    break;
	                                }
	                            }
	                            if (allModifiersPressed) {
	                                handler = options.keyBinds[index];
	                                break;
	                            }
	                        }
	                    }
	                }

	                if (handler) {
	                    handler.call(picker, widget);
	                    e.stopPropagation();
	                    e.preventDefault();
	                }
	            },

	            keyup = function (e) {
	                keyState[e.which] = 'r';
	                e.stopPropagation();
	                e.preventDefault();
	            },

	            change = function (e) {
	                var val = $(e.target).val().trim(),
	                    parsedDate = val ? parseInputDate(val) : null;
	                setValue(parsedDate);
	                e.stopImmediatePropagation();
	                return false;
	            },

	            attachDatePickerElementEvents = function () {
	                input.on({
	                    'change': change,
	                    'blur': options.debug ? '' : hide,
	                    'keydown': keydown,
	                    'keyup': keyup,
	                    'focus': options.allowInputToggle ? show : ''
	                });

	                if (element.is('input')) {
	                    input.on({
	                        'focus': show
	                    });
	                } else if (component) {
	                    component.on('click', toggle);
	                    component.on('mousedown', false);
	                }
	            },

	            detachDatePickerElementEvents = function () {
	                input.off({
	                    'change': change,
	                    'blur': blur,
	                    'keydown': keydown,
	                    'keyup': keyup,
	                    'focus': options.allowInputToggle ? hide : ''
	                });

	                if (element.is('input')) {
	                    input.off({
	                        'focus': show
	                    });
	                } else if (component) {
	                    component.off('click', toggle);
	                    component.off('mousedown', false);
	                }
	            },

	            indexGivenDates = function (givenDatesArray) {
	                // Store given enabledDates and disabledDates as keys.
	                // This way we can check their existence in O(1) time instead of looping through whole array.
	                // (for example: options.enabledDates['2014-02-27'] === true)
	                var givenDatesIndexed = {};
	                $.each(givenDatesArray, function () {
	                    var dDate = parseInputDate(this);
	                    if (dDate.isValid()) {
	                        givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
	                    }
	                });
	                return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
	            },

	            indexGivenHours = function (givenHoursArray) {
	                // Store given enabledHours and disabledHours as keys.
	                // This way we can check their existence in O(1) time instead of looping through whole array.
	                // (for example: options.enabledHours['2014-02-27'] === true)
	                var givenHoursIndexed = {};
	                $.each(givenHoursArray, function () {
	                    givenHoursIndexed[this] = true;
	                });
	                return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
	            },

	            initFormatting = function () {
	                var format = options.format || 'L LT';

	                actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
	                    var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
	                    return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740
	                        return date.localeData().longDateFormat(formatInput2) || formatInput2;
	                    });
	                });


	                parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
	                if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
	                    parseFormats.push(actualFormat);
	                }

	                use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);

	                if (isEnabled('y')) {
	                    minViewModeNumber = 2;
	                }
	                if (isEnabled('M')) {
	                    minViewModeNumber = 1;
	                }
	                if (isEnabled('d')) {
	                    minViewModeNumber = 0;
	                }

	                currentViewMode = Math.max(minViewModeNumber, currentViewMode);

	                if (!unset) {
	                    setValue(date);
	                }
	            };

	        /********************************************************************************
	         *
	         * Public API functions
	         * =====================
	         *
	         * Important: Do not expose direct references to private objects or the options
	         * object to the outer world. Always return a clone when returning values or make
	         * a clone when setting a private variable.
	         *
	         ********************************************************************************/
	        picker.destroy = function () {
	            ///<summary>Destroys the widget and removes all attached event listeners</summary>
	            hide();
	            detachDatePickerElementEvents();
	            element.removeData('DateTimePicker');
	            element.removeData('date');
	        };

	        picker.toggle = toggle;

	        picker.show = show;

	        picker.hide = hide;

	        picker.disable = function () {
	            ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
	            ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
	            hide();
	            if (component && component.hasClass('btn')) {
	                component.addClass('disabled');
	            }
	            input.prop('disabled', true);
	            return picker;
	        };

	        picker.enable = function () {
	            ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
	            if (component && component.hasClass('btn')) {
	                component.removeClass('disabled');
	            }
	            input.prop('disabled', false);
	            return picker;
	        };

	        picker.ignoreReadonly = function (ignoreReadonly) {
	            if (arguments.length === 0) {
	                return options.ignoreReadonly;
	            }
	            if (typeof ignoreReadonly !== 'boolean') {
	                throw new TypeError('ignoreReadonly () expects a boolean parameter');
	            }
	            options.ignoreReadonly = ignoreReadonly;
	            return picker;
	        };

	        picker.options = function (newOptions) {
	            if (arguments.length === 0) {
	                return $.extend(true, {}, options);
	            }

	            if (!(newOptions instanceof Object)) {
	                throw new TypeError('options() options parameter should be an object');
	            }
	            $.extend(true, options, newOptions);
	            $.each(options, function (key, value) {
	                if (picker[key] !== undefined) {
	                    picker[key](value);
	                } else {
	                    throw new TypeError('option ' + key + ' is not recognized!');
	                }
	            });
	            return picker;
	        };

	        picker.date = function (newDate) {
	            ///<signature helpKeyword="$.fn.datetimepicker.date">
	            ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
	            ///<returns type="Moment">date.clone()</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
	            ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                if (unset) {
	                    return null;
	                }
	                return date.clone();
	            }

	            if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
	                throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
	            }

	            setValue(newDate === null ? null : parseInputDate(newDate));
	            return picker;
	        };

	        picker.format = function (newFormat) {
	            ///<summary>test su</summary>
	            ///<param name="newFormat">info about para</param>
	            ///<returns type="string|boolean">returns foo</returns>
	            if (arguments.length === 0) {
	                return options.format;
	            }

	            if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
	                throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat);
	            }

	            options.format = newFormat;
	            if (actualFormat) {
	                initFormatting(); // reinit formatting
	            }
	            return picker;
	        };

	        picker.timeZone = function (newZone) {
	            if (arguments.length === 0) {
	                return options.timeZone;
	            }

	            options.timeZone = newZone;

	            return picker;
	        };

	        picker.dayViewHeaderFormat = function (newFormat) {
	            if (arguments.length === 0) {
	                return options.dayViewHeaderFormat;
	            }

	            if (typeof newFormat !== 'string') {
	                throw new TypeError('dayViewHeaderFormat() expects a string parameter');
	            }

	            options.dayViewHeaderFormat = newFormat;
	            return picker;
	        };

	        picker.extraFormats = function (formats) {
	            if (arguments.length === 0) {
	                return options.extraFormats;
	            }

	            if (formats !== false && !(formats instanceof Array)) {
	                throw new TypeError('extraFormats() expects an array or false parameter');
	            }

	            options.extraFormats = formats;
	            if (parseFormats) {
	                initFormatting(); // reinit formatting
	            }
	            return picker;
	        };

	        picker.disabledDates = function (dates) {
	            ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
	            ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
	            ///<returns type="array">options.disabledDates</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
	            ///options.enabledDates if such exist.</summary>
	            ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
	            }

	            if (!dates) {
	                options.disabledDates = false;
	                update();
	                return picker;
	            }
	            if (!(dates instanceof Array)) {
	                throw new TypeError('disabledDates() expects an array parameter');
	            }
	            options.disabledDates = indexGivenDates(dates);
	            options.enabledDates = false;
	            update();
	            return picker;
	        };

	        picker.enabledDates = function (dates) {
	            ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
	            ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
	            ///<returns type="array">options.enabledDates</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
	            ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
	            }

	            if (!dates) {
	                options.enabledDates = false;
	                update();
	                return picker;
	            }
	            if (!(dates instanceof Array)) {
	                throw new TypeError('enabledDates() expects an array parameter');
	            }
	            options.enabledDates = indexGivenDates(dates);
	            options.disabledDates = false;
	            update();
	            return picker;
	        };

	        picker.daysOfWeekDisabled = function (daysOfWeekDisabled) {
	            if (arguments.length === 0) {
	                return options.daysOfWeekDisabled.splice(0);
	            }

	            if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
	                options.daysOfWeekDisabled = false;
	                update();
	                return picker;
	            }

	            if (!(daysOfWeekDisabled instanceof Array)) {
	                throw new TypeError('daysOfWeekDisabled() expects an array parameter');
	            }
	            options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
	                currentValue = parseInt(currentValue, 10);
	                if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
	                    return previousValue;
	                }
	                if (previousValue.indexOf(currentValue) === -1) {
	                    previousValue.push(currentValue);
	                }
	                return previousValue;
	            }, []).sort();
	            if (options.useCurrent && !options.keepInvalid) {
	                var tries = 0;
	                while (!isValid(date, 'd')) {
	                    date.add(1, 'd');
	                    if (tries === 7) {
	                        throw 'Tried 7 times to find a valid date';
	                    }
	                    tries++;
	                }
	                setValue(date);
	            }
	            update();
	            return picker;
	        };

	        picker.maxDate = function (maxDate) {
	            if (arguments.length === 0) {
	                return options.maxDate ? options.maxDate.clone() : options.maxDate;
	            }

	            if ((typeof maxDate === 'boolean') && maxDate === false) {
	                options.maxDate = false;
	                update();
	                return picker;
	            }

	            if (typeof maxDate === 'string') {
	                if (maxDate === 'now' || maxDate === 'moment') {
	                    maxDate = getMoment();
	                }
	            }

	            var parsedDate = parseInputDate(maxDate);

	            if (!parsedDate.isValid()) {
	                throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate);
	            }
	            if (options.minDate && parsedDate.isBefore(options.minDate)) {
	                throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
	            }
	            options.maxDate = parsedDate;
	            if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
	                setValue(options.maxDate);
	            }
	            if (viewDate.isAfter(parsedDate)) {
	                viewDate = parsedDate.clone().subtract(options.stepping, 'm');
	            }
	            update();
	            return picker;
	        };

	        picker.minDate = function (minDate) {
	            if (arguments.length === 0) {
	                return options.minDate ? options.minDate.clone() : options.minDate;
	            }

	            if ((typeof minDate === 'boolean') && minDate === false) {
	                options.minDate = false;
	                update();
	                return picker;
	            }

	            if (typeof minDate === 'string') {
	                if (minDate === 'now' || minDate === 'moment') {
	                    minDate = getMoment();
	                }
	            }

	            var parsedDate = parseInputDate(minDate);

	            if (!parsedDate.isValid()) {
	                throw new TypeError('minDate() Could not parse date parameter: ' + minDate);
	            }
	            if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
	                throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
	            }
	            options.minDate = parsedDate;
	            if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
	                setValue(options.minDate);
	            }
	            if (viewDate.isBefore(parsedDate)) {
	                viewDate = parsedDate.clone().add(options.stepping, 'm');
	            }
	            update();
	            return picker;
	        };

	        picker.defaultDate = function (defaultDate) {
	            ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
	            ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
	            ///<returns type="Moment">date.clone()</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
	            ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
	            }
	            if (!defaultDate) {
	                options.defaultDate = false;
	                return picker;
	            }

	            if (typeof defaultDate === 'string') {
	                if (defaultDate === 'now' || defaultDate === 'moment') {
	                    defaultDate = getMoment();
	                }
	            }

	            var parsedDate = parseInputDate(defaultDate);
	            if (!parsedDate.isValid()) {
	                throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate);
	            }
	            if (!isValid(parsedDate)) {
	                throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
	            }

	            options.defaultDate = parsedDate;

	            if ((options.defaultDate && options.inline) || input.val().trim() === '') {
	                setValue(options.defaultDate);
	            }
	            return picker;
	        };

	        picker.locale = function (locale) {
	            if (arguments.length === 0) {
	                return options.locale;
	            }

	            if (!moment.localeData(locale)) {
	                throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!');
	            }

	            options.locale = locale;
	            date.locale(options.locale);
	            viewDate.locale(options.locale);

	            if (actualFormat) {
	                initFormatting(); // reinit formatting
	            }
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.stepping = function (stepping) {
	            if (arguments.length === 0) {
	                return options.stepping;
	            }

	            stepping = parseInt(stepping, 10);
	            if (isNaN(stepping) || stepping < 1) {
	                stepping = 1;
	            }
	            options.stepping = stepping;
	            return picker;
	        };

	        picker.useCurrent = function (useCurrent) {
	            var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
	            if (arguments.length === 0) {
	                return options.useCurrent;
	            }

	            if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) {
	                throw new TypeError('useCurrent() expects a boolean or string parameter');
	            }
	            if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) {
	                throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));
	            }
	            options.useCurrent = useCurrent;
	            return picker;
	        };

	        picker.collapse = function (collapse) {
	            if (arguments.length === 0) {
	                return options.collapse;
	            }

	            if (typeof collapse !== 'boolean') {
	                throw new TypeError('collapse() expects a boolean parameter');
	            }
	            if (options.collapse === collapse) {
	                return picker;
	            }
	            options.collapse = collapse;
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.icons = function (icons) {
	            if (arguments.length === 0) {
	                return $.extend({}, options.icons);
	            }

	            if (!(icons instanceof Object)) {
	                throw new TypeError('icons() expects parameter to be an Object');
	            }
	            $.extend(options.icons, icons);
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.tooltips = function (tooltips) {
	            if (arguments.length === 0) {
	                return $.extend({}, options.tooltips);
	            }

	            if (!(tooltips instanceof Object)) {
	                throw new TypeError('tooltips() expects parameter to be an Object');
	            }
	            $.extend(options.tooltips, tooltips);
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.useStrict = function (useStrict) {
	            if (arguments.length === 0) {
	                return options.useStrict;
	            }

	            if (typeof useStrict !== 'boolean') {
	                throw new TypeError('useStrict() expects a boolean parameter');
	            }
	            options.useStrict = useStrict;
	            return picker;
	        };

	        picker.sideBySide = function (sideBySide) {
	            if (arguments.length === 0) {
	                return options.sideBySide;
	            }

	            if (typeof sideBySide !== 'boolean') {
	                throw new TypeError('sideBySide() expects a boolean parameter');
	            }
	            options.sideBySide = sideBySide;
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.viewMode = function (viewMode) {
	            if (arguments.length === 0) {
	                return options.viewMode;
	            }

	            if (typeof viewMode !== 'string') {
	                throw new TypeError('viewMode() expects a string parameter');
	            }

	            if (viewModes.indexOf(viewMode) === -1) {
	                throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value');
	            }

	            options.viewMode = viewMode;
	            currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber);

	            showMode();
	            return picker;
	        };

	        picker.toolbarPlacement = function (toolbarPlacement) {
	            if (arguments.length === 0) {
	                return options.toolbarPlacement;
	            }

	            if (typeof toolbarPlacement !== 'string') {
	                throw new TypeError('toolbarPlacement() expects a string parameter');
	            }
	            if (toolbarPlacements.indexOf(toolbarPlacement) === -1) {
	                throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value');
	            }
	            options.toolbarPlacement = toolbarPlacement;

	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.widgetPositioning = function (widgetPositioning) {
	            if (arguments.length === 0) {
	                return $.extend({}, options.widgetPositioning);
	            }

	            if (({}).toString.call(widgetPositioning) !== '[object Object]') {
	                throw new TypeError('widgetPositioning() expects an object variable');
	            }
	            if (widgetPositioning.horizontal) {
	                if (typeof widgetPositioning.horizontal !== 'string') {
	                    throw new TypeError('widgetPositioning() horizontal variable must be a string');
	                }
	                widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase();
	                if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) {
	                    throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')');
	                }
	                options.widgetPositioning.horizontal = widgetPositioning.horizontal;
	            }
	            if (widgetPositioning.vertical) {
	                if (typeof widgetPositioning.vertical !== 'string') {
	                    throw new TypeError('widgetPositioning() vertical variable must be a string');
	                }
	                widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase();
	                if (verticalModes.indexOf(widgetPositioning.vertical) === -1) {
	                    throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')');
	                }
	                options.widgetPositioning.vertical = widgetPositioning.vertical;
	            }
	            update();
	            return picker;
	        };

	        picker.calendarWeeks = function (calendarWeeks) {
	            if (arguments.length === 0) {
	                return options.calendarWeeks;
	            }

	            if (typeof calendarWeeks !== 'boolean') {
	                throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
	            }

	            options.calendarWeeks = calendarWeeks;
	            update();
	            return picker;
	        };

	        picker.showTodayButton = function (showTodayButton) {
	            if (arguments.length === 0) {
	                return options.showTodayButton;
	            }

	            if (typeof showTodayButton !== 'boolean') {
	                throw new TypeError('showTodayButton() expects a boolean parameter');
	            }

	            options.showTodayButton = showTodayButton;
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.showClear = function (showClear) {
	            if (arguments.length === 0) {
	                return options.showClear;
	            }

	            if (typeof showClear !== 'boolean') {
	                throw new TypeError('showClear() expects a boolean parameter');
	            }

	            options.showClear = showClear;
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.widgetParent = function (widgetParent) {
	            if (arguments.length === 0) {
	                return options.widgetParent;
	            }

	            if (typeof widgetParent === 'string') {
	                widgetParent = $(widgetParent);
	            }

	            if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) {
	                throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
	            }

	            options.widgetParent = widgetParent;
	            if (widget) {
	                hide();
	                show();
	            }
	            return picker;
	        };

	        picker.keepOpen = function (keepOpen) {
	            if (arguments.length === 0) {
	                return options.keepOpen;
	            }

	            if (typeof keepOpen !== 'boolean') {
	                throw new TypeError('keepOpen() expects a boolean parameter');
	            }

	            options.keepOpen = keepOpen;
	            return picker;
	        };

	        picker.focusOnShow = function (focusOnShow) {
	            if (arguments.length === 0) {
	                return options.focusOnShow;
	            }

	            if (typeof focusOnShow !== 'boolean') {
	                throw new TypeError('focusOnShow() expects a boolean parameter');
	            }

	            options.focusOnShow = focusOnShow;
	            return picker;
	        };

	        picker.inline = function (inline) {
	            if (arguments.length === 0) {
	                return options.inline;
	            }

	            if (typeof inline !== 'boolean') {
	                throw new TypeError('inline() expects a boolean parameter');
	            }

	            options.inline = inline;
	            return picker;
	        };

	        picker.clear = function () {
	            clear();
	            return picker;
	        };

	        picker.keyBinds = function (keyBinds) {
	            options.keyBinds = keyBinds;
	            return picker;
	        };

	        picker.getMoment = function (d) {
	            return getMoment(d);
	        };

	        picker.debug = function (debug) {
	            if (typeof debug !== 'boolean') {
	                throw new TypeError('debug() expects a boolean parameter');
	            }

	            options.debug = debug;
	            return picker;
	        };

	        picker.allowInputToggle = function (allowInputToggle) {
	            if (arguments.length === 0) {
	                return options.allowInputToggle;
	            }

	            if (typeof allowInputToggle !== 'boolean') {
	                throw new TypeError('allowInputToggle() expects a boolean parameter');
	            }

	            options.allowInputToggle = allowInputToggle;
	            return picker;
	        };

	        picker.showClose = function (showClose) {
	            if (arguments.length === 0) {
	                return options.showClose;
	            }

	            if (typeof showClose !== 'boolean') {
	                throw new TypeError('showClose() expects a boolean parameter');
	            }

	            options.showClose = showClose;
	            return picker;
	        };

	        picker.keepInvalid = function (keepInvalid) {
	            if (arguments.length === 0) {
	                return options.keepInvalid;
	            }

	            if (typeof keepInvalid !== 'boolean') {
	                throw new TypeError('keepInvalid() expects a boolean parameter');
	            }
	            options.keepInvalid = keepInvalid;
	            return picker;
	        };

	        picker.datepickerInput = function (datepickerInput) {
	            if (arguments.length === 0) {
	                return options.datepickerInput;
	            }

	            if (typeof datepickerInput !== 'string') {
	                throw new TypeError('datepickerInput() expects a string parameter');
	            }

	            options.datepickerInput = datepickerInput;
	            return picker;
	        };

	        picker.parseInputDate = function (parseInputDate) {
	            if (arguments.length === 0) {
	                return options.parseInputDate;
	            }

	            if (typeof parseInputDate !== 'function') {
	                throw new TypeError('parseInputDate() sholud be as function');
	            }

	            options.parseInputDate = parseInputDate;

	            return picker;
	        };

	        picker.disabledTimeIntervals = function (disabledTimeIntervals) {
	            ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
	            ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
	            ///<returns type="array">options.disabledTimeIntervals</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
	            ///options.enabledDates if such exist.</summary>
	            ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
	            }

	            if (!disabledTimeIntervals) {
	                options.disabledTimeIntervals = false;
	                update();
	                return picker;
	            }
	            if (!(disabledTimeIntervals instanceof Array)) {
	                throw new TypeError('disabledTimeIntervals() expects an array parameter');
	            }
	            options.disabledTimeIntervals = disabledTimeIntervals;
	            update();
	            return picker;
	        };

	        picker.disabledHours = function (hours) {
	            ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
	            ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
	            ///<returns type="array">options.disabledHours</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
	            ///options.enabledHours if such exist.</summary>
	            ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
	            }

	            if (!hours) {
	                options.disabledHours = false;
	                update();
	                return picker;
	            }
	            if (!(hours instanceof Array)) {
	                throw new TypeError('disabledHours() expects an array parameter');
	            }
	            options.disabledHours = indexGivenHours(hours);
	            options.enabledHours = false;
	            if (options.useCurrent && !options.keepInvalid) {
	                var tries = 0;
	                while (!isValid(date, 'h')) {
	                    date.add(1, 'h');
	                    if (tries === 24) {
	                        throw 'Tried 24 times to find a valid date';
	                    }
	                    tries++;
	                }
	                setValue(date);
	            }
	            update();
	            return picker;
	        };

	        picker.enabledHours = function (hours) {
	            ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
	            ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
	            ///<returns type="array">options.enabledHours</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
	            ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
	            }

	            if (!hours) {
	                options.enabledHours = false;
	                update();
	                return picker;
	            }
	            if (!(hours instanceof Array)) {
	                throw new TypeError('enabledHours() expects an array parameter');
	            }
	            options.enabledHours = indexGivenHours(hours);
	            options.disabledHours = false;
	            if (options.useCurrent && !options.keepInvalid) {
	                var tries = 0;
	                while (!isValid(date, 'h')) {
	                    date.add(1, 'h');
	                    if (tries === 24) {
	                        throw 'Tried 24 times to find a valid date';
	                    }
	                    tries++;
	                }
	                setValue(date);
	            }
	            update();
	            return picker;
	        };

	        picker.viewDate = function (newDate) {
	            ///<signature helpKeyword="$.fn.datetimepicker.viewDate">
	            ///<summary>Returns the component's model current viewDate, a moment object or null if not set.</summary>
	            ///<returns type="Moment">viewDate.clone()</returns>
	            ///</signature>
	            ///<signature>
	            ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
	            ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, viewDate, moment, null parameter.</param>
	            ///</signature>
	            if (arguments.length === 0) {
	                return viewDate.clone();
	            }

	            if (!newDate) {
	                viewDate = date.clone();
	                return picker;
	            }

	            if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
	                throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
	            }

	            viewDate = parseInputDate(newDate);
	            viewUpdate();
	            return picker;
	        };

	        // initializing element and component attributes
	        if (element.is('input')) {
	            input = element;
	        } else {
	            input = element.find(options.datepickerInput);
	            if (input.size() === 0) {
	                input = element.find('input');
	            } else if (!input.is('input')) {
	                throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
	            }
	        }

	        if (element.hasClass('input-group')) {
	            // in case there is more then one 'input-group-addon' Issue #48
	            if (element.find('.datepickerbutton').size() === 0) {
	                component = element.find('.input-group-addon');
	            } else {
	                component = element.find('.datepickerbutton');
	            }
	        }

	        if (!options.inline && !input.is('input')) {
	            throw new Error('Could not initialize DateTimePicker without an input element');
	        }

	        // Set defaults for date here now instead of in var declaration
	        date = getMoment();
	        viewDate = date.clone();

	        $.extend(true, options, dataToOptions());

	        picker.options(options);

	        initFormatting();

	        attachDatePickerElementEvents();

	        if (input.prop('disabled')) {
	            picker.disable();
	        }
	        if (input.is('input') && input.val().trim().length !== 0) {
	            setValue(parseInputDate(input.val().trim()));
	        }
	        else if (options.defaultDate && input.attr('placeholder') === undefined) {
	            setValue(options.defaultDate);
	        }
	        if (options.inline) {
	            show();
	        }
	        return picker;
	    };

	    /********************************************************************************
	     *
	     * jQuery plugin constructor and defaults object
	     *
	     ********************************************************************************/

	    $.fn.datetimepicker = function (options) {
	        return this.each(function () {
	            var $this = $(this);
	            if (!$this.data('DateTimePicker')) {
	                // create a private copy of the defaults object
	                options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
	                $this.data('DateTimePicker', dateTimePicker($this, options));
	            }
	        });
	    };

	    $.fn.datetimepicker.defaults = {
	        timeZone: 'Etc/UTC',
	        format: false,
	        dayViewHeaderFormat: 'MMMM YYYY',
	        extraFormats: false,
	        stepping: 1,
	        minDate: false,
	        maxDate: false,
	        useCurrent: true,
	        collapse: true,
	        locale: moment.locale(),
	        defaultDate: false,
	        disabledDates: false,
	        enabledDates: false,
	        icons: {
	            time: 'glyphicon glyphicon-time',
	            date: 'glyphicon glyphicon-calendar',
	            up: 'glyphicon glyphicon-chevron-up',
	            down: 'glyphicon glyphicon-chevron-down',
	            previous: 'glyphicon glyphicon-chevron-left',
	            next: 'glyphicon glyphicon-chevron-right',
	            today: 'glyphicon glyphicon-screenshot',
	            clear: 'glyphicon glyphicon-trash',
	            close: 'glyphicon glyphicon-remove'
	        },
	        tooltips: {
	            today: 'Go to today',
	            clear: 'Clear selection',
	            close: 'Close the picker',
	            selectMonth: 'Select Month',
	            prevMonth: 'Previous Month',
	            nextMonth: 'Next Month',
	            selectYear: 'Select Year',
	            prevYear: 'Previous Year',
	            nextYear: 'Next Year',
	            selectDecade: 'Select Decade',
	            prevDecade: 'Previous Decade',
	            nextDecade: 'Next Decade',
	            prevCentury: 'Previous Century',
	            nextCentury: 'Next Century',
	            pickHour: 'Pick Hour',
	            incrementHour: 'Increment Hour',
	            decrementHour: 'Decrement Hour',
	            pickMinute: 'Pick Minute',
	            incrementMinute: 'Increment Minute',
	            decrementMinute: 'Decrement Minute',
	            pickSecond: 'Pick Second',
	            incrementSecond: 'Increment Second',
	            decrementSecond: 'Decrement Second',
	            togglePeriod: 'Toggle Period',
	            selectTime: 'Select Time'
	        },
	        useStrict: false,
	        sideBySide: false,
	        daysOfWeekDisabled: false,
	        calendarWeeks: false,
	        viewMode: 'days',
	        toolbarPlacement: 'default',
	        showTodayButton: false,
	        showClear: false,
	        showClose: false,
	        widgetPositioning: {
	            horizontal: 'auto',
	            vertical: 'auto'
	        },
	        widgetParent: null,
	        ignoreReadonly: false,
	        keepOpen: false,
	        focusOnShow: true,
	        inline: false,
	        keepInvalid: false,
	        datepickerInput: '.datepickerinput',
	        keyBinds: {
	            up: function (widget) {
	                if (!widget) {
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().subtract(7, 'd'));
	                } else {
	                    this.date(d.clone().add(this.stepping(), 'm'));
	                }
	            },
	            down: function (widget) {
	                if (!widget) {
	                    this.show();
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().add(7, 'd'));
	                } else {
	                    this.date(d.clone().subtract(this.stepping(), 'm'));
	                }
	            },
	            'control up': function (widget) {
	                if (!widget) {
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().subtract(1, 'y'));
	                } else {
	                    this.date(d.clone().add(1, 'h'));
	                }
	            },
	            'control down': function (widget) {
	                if (!widget) {
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().add(1, 'y'));
	                } else {
	                    this.date(d.clone().subtract(1, 'h'));
	                }
	            },
	            left: function (widget) {
	                if (!widget) {
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().subtract(1, 'd'));
	                }
	            },
	            right: function (widget) {
	                if (!widget) {
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().add(1, 'd'));
	                }
	            },
	            pageUp: function (widget) {
	                if (!widget) {
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().subtract(1, 'M'));
	                }
	            },
	            pageDown: function (widget) {
	                if (!widget) {
	                    return;
	                }
	                var d = this.date() || this.getMoment();
	                if (widget.find('.datepicker').is(':visible')) {
	                    this.date(d.clone().add(1, 'M'));
	                }
	            },
	            enter: function () {
	                this.hide();
	            },
	            escape: function () {
	                this.hide();
	            },
	            //tab: function (widget) { //this break the flow of the form. disabling for now
	            //    var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
	            //    if(toggle.length > 0) toggle.click();
	            //},
	            'control space': function (widget) {
	                if (widget.find('.timepicker').is(':visible')) {
	                    widget.find('.btn[data-action="togglePeriod"]').click();
	                }
	            },
	            t: function () {
	                this.date(this.getMoment());
	            },
	            'delete': function () {
	                this.clear();
	            }
	        },
	        debug: false,
	        allowInputToggle: false,
	        disabledTimeIntervals: false,
	        disabledHours: false,
	        enabledHours: false,
	        viewDate: false
	    };
	}));


/***/ },
/* 385 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var SimpleFormGroup = function SimpleFormGroup() {
	  var _this = this;

	  _classCallCheck(this, SimpleFormGroup);

	  (0, _jquery2.default)(".form-group.other").each(function (_) {
	    var select = (0, _jquery2.default)(_this).find("select");
	    var elem = (0, _jquery2.default)(select).next("input");

	    if ((0, _jquery2.default)(select).find("option:selected").html() != (0, _jquery2.default)(select).find("option:last").html()) (0, _jquery2.default)(elem).hide();
	    select.change(function (_) {
	      if ((0, _jquery2.default)(select).find("option:selected").html() == (0, _jquery2.default)(select).find("option:last").html()) elem.show();else elem.hide();
	    });
	  });
	};

	exports.default = SimpleFormGroup;

/***/ },
/* 386 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	__webpack_require__(387);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var SimpleFormLimit = function SimpleFormLimit() {
	  var _this = this;

	  _classCallCheck(this, SimpleFormLimit);

	  (0, _jquery2.default)("[data-limit]").each(function (_) {
	    (0, _jquery2.default)(_this).maxlength({
	      maxCharacters: (0, _jquery2.default)(_this).data("limit"),
	      zeroStatusText: (0, _jquery2.default)(_this).data("zero"),
	      oneStatusText: (0, _jquery2.default)(_this).data("one"),
	      moreStatusText: (0, _jquery2.default)(_this).data("more")
	    });
	  });
	};

	exports.default = SimpleFormLimit;

/***/ },
/* 387 */
/***/ function(module, exports) {

	"use strict";

	/**
	 * jQuery Maxlength plugin
	 * @version		$Id: jquery.maxlength.js 18 2009-05-16 15:37:08Z emil@anon-design.se $
	 * @package		jQuery maxlength 1.0.5
	 * @copyright	Copyright (C) 2009 Emil Stjerneman / http://www.anon-design.se
	 * @license		GNU/GPL, see LICENSE.txt
	 */

	(function ($) {

	    $.fn.maxlength = function (options) {
	        var settings = jQuery.extend({
	            events: [], // Array of events to be triggerd
	            maxCharacters: 10, // Characters limit
	            status: true, // True to show status indicator bewlow the element
	            statusClass: "status", // The class on the status div
	            statusText: "character left", // The status text
	            notificationClass: "notification", // Will be added to the emement when maxlength is reached
	            showAlert: false, // True to show a regular alert message
	            alertText: "You have typed too many characters.", // Text in the alert message
	            slider: false // Use counter slider
	        }, options);

	        // Add the default event
	        $.merge(settings.events, ['keyup']);

	        return this.each(function () {
	            var item = $(this);
	            var charactersLength = item.val().length;

	            // Update the status text
	            function updateStatus() {
	                var charactersLeft = settings.maxCharacters - charactersLength;

	                charactersLeft = charactersLeft < 0 ? 0 : charactersLeft;

	                item.next("div").html(charactersLeft + " " + settings.statusText);
	            }

	            function checkChars() {
	                var valid = true;

	                // Too many chars?
	                if (charactersLength >= settings.maxCharacters) {
	                    // Too may chars, set the valid boolean to false
	                    valid = false;
	                    // Add the notification class when we have too many chars
	                    item.addClass(settings.notificationClass);
	                    // Cut down the string
	                    item.val(item.val().substr(0, settings.maxCharacters));
	                    // Show the alert dialog box, if its set to true
	                    showAlert();
	                } else if (item.hasClass(settings.notificationClass)) {
	                    item.removeClass(settings.notificationClass);
	                }

	                if (settings.status) {
	                    updateStatus();
	                }
	            }

	            // Shows an alert msg
	            function showAlert() {
	                if (settings.showAlert) {
	                    alert(settings.alertText);
	                }
	            }

	            // Check if the element is valid.
	            function validateElement() {
	                return item.is('textarea') || item.filter("input[type=text]") || item.filter("input[type=password]");
	            }

	            // Validate
	            if (!validateElement()) {
	                return false;
	            }

	            // Loop through the events and bind them to the element
	            $.each(settings.events, function (i, n) {
	                item.bind(n, function (e) {
	                    charactersLength = item.val().length;
	                    checkChars();
	                });
	            });

	            // Insert the status div
	            if (settings.status) {
	                item.after($("<div/>").addClass(settings.statusClass).html('-'));
	                updateStatus();
	            }

	            // Remove the status div
	            if (!settings.status) {
	                var removeThisDiv = item.next("div." + settings.statusClass);

	                if (removeThisDiv) {
	                    removeThisDiv.remove();
	                }
	            }

	            // Slide counter
	            if (settings.slider) {
	                item.next().hide();

	                item.focus(function () {
	                    item.next().slideDown('fast');
	                });

	                item.blur(function () {
	                    item.next().slideUp('fast');
	                });
	            }
	        });
	    };
	})(jQuery);

/***/ },
/* 388 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var SimpleFormTextarea = function SimpleFormTextarea() {
	  _classCallCheck(this, SimpleFormTextarea);

	  (0, _jquery2.default)("textarea").keydown(function (e) {
	    if (e.keyCode == 9) {
	      var start = this.selectionStart;
	      var end = this.selectionEnd;
	      var $this = (0, _jquery2.default)(this);
	      var value = $this.val();

	      $this.val(value.substring(0, start) + "\t" + value.substring(end));
	      this.selectionStart = this.selectionEnd = start + 1;
	      e.preventDefault();
	    }
	  });
	};

	exports.default = SimpleFormTextarea;

/***/ },
/* 389 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _array = __webpack_require__(390);

	var _array2 = _interopRequireDefault(_array);

	var _string = __webpack_require__(392);

	var _string2 = _interopRequireDefault(_string);

	var _jquery = __webpack_require__(393);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _bootstrap = __webpack_require__(394);

	var _bootstrap2 = _interopRequireDefault(_bootstrap);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var AddOn = function AddOn() {
	  _classCallCheck(this, AddOn);

	  (0, _string2.default)();
	  (0, _array2.default)();
	  (0, _jquery2.default)();
	  (0, _bootstrap2.default)();
	};

	exports.default = AddOn;

/***/ },
/* 390 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = arrayHelper;

	__webpack_require__(391);

	function arrayHelper() {
	  NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
	  HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

	  Array.prototype.to_rails_params = function (obj) {
	    var attr_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "id";

	    return Array.from(this, function (attr) {
	      return obj + '[' + attr_name.pluralize() + '][]=' + attr;
	    }).join('&');
	  };
	}

/***/ },
/* 391 */
/***/ function(module, exports, __webpack_require__) {

	/* global define */

	(function (root, pluralize) {
	  /* istanbul ignore else */
	  if (true) {
	    // Node.
	    module.exports = pluralize();
	  } else if (typeof define === 'function' && define.amd) {
	    // AMD, registers as an anonymous module.
	    define(function () {
	      return pluralize();
	    });
	  } else {
	    // Browser global.
	    root.pluralize = pluralize();
	  }
	})(this, function () {
	  // Rule storage - pluralize and singularize need to be run sequentially,
	  // while other rules can be optimized using an object for instant lookups.
	  var pluralRules = [];
	  var singularRules = [];
	  var uncountables = {};
	  var irregularPlurals = {};
	  var irregularSingles = {};

	  /**
	   * Title case a string.
	   *
	   * @param  {string} str
	   * @return {string}
	   */
	  function toTitleCase (str) {
	    return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
	  }

	  /**
	   * Sanitize a pluralization rule to a usable regular expression.
	   *
	   * @param  {(RegExp|string)} rule
	   * @return {RegExp}
	   */
	  function sanitizeRule (rule) {
	    if (typeof rule === 'string') {
	      return new RegExp('^' + rule + '$', 'i');
	    }

	    return rule;
	  }

	  /**
	   * Pass in a word token to produce a function that can replicate the case on
	   * another word.
	   *
	   * @param  {string}   word
	   * @param  {string}   token
	   * @return {Function}
	   */
	  function restoreCase (word, token) {
	    // Upper cased words. E.g. "HELLO".
	    if (word === word.toUpperCase()) {
	      return token.toUpperCase();
	    }

	    // Title cased words. E.g. "Title".
	    if (word[0] === word[0].toUpperCase()) {
	      return toTitleCase(token);
	    }

	    // Lower cased words. E.g. "test".
	    return token.toLowerCase();
	  }

	  /**
	   * Interpolate a regexp string.
	   *
	   * @param  {string} str
	   * @param  {Array}  args
	   * @return {string}
	   */
	  function interpolate (str, args) {
	    return str.replace(/\$(\d{1,2})/g, function (match, index) {
	      return args[index] || '';
	    });
	  }

	  /**
	   * Sanitize a word by passing in the word and sanitization rules.
	   *
	   * @param  {String}   token
	   * @param  {String}   word
	   * @param  {Array}    collection
	   * @return {String}
	   */
	  function sanitizeWord (token, word, collection) {
	    // Empty string or doesn't need fixing.
	    if (!token.length || uncountables.hasOwnProperty(token)) {
	      return word;
	    }

	    var len = collection.length;

	    // Iterate over the sanitization rules and use the first one to match.
	    while (len--) {
	      var rule = collection[len];

	      // If the rule passes, return the replacement.
	      if (rule[0].test(word)) {
	        return word.replace(rule[0], function (match, index, word) {
	          var result = interpolate(rule[1], arguments);

	          if (match === '') {
	            return restoreCase(word[index - 1], result);
	          }

	          return restoreCase(match, result);
	        });
	      }
	    }

	    return word;
	  }

	  /**
	   * Replace a word with the updated word.
	   *
	   * @param  {Object}   replaceMap
	   * @param  {Object}   keepMap
	   * @param  {Array}    rules
	   * @return {Function}
	   */
	  function replaceWord (replaceMap, keepMap, rules) {
	    return function (word) {
	      // Get the correct token and case restoration functions.
	      var token = word.toLowerCase();

	      // Check against the keep object map.
	      if (keepMap.hasOwnProperty(token)) {
	        return restoreCase(word, token);
	      }

	      // Check against the replacement map for a direct word replacement.
	      if (replaceMap.hasOwnProperty(token)) {
	        return restoreCase(word, replaceMap[token]);
	      }

	      // Run all the rules against the word.
	      return sanitizeWord(token, word, rules);
	    };
	  }

	  /**
	   * Pluralize or singularize a word based on the passed in count.
	   *
	   * @param  {String}  word
	   * @param  {Number}  count
	   * @param  {Boolean} inclusive
	   * @return {String}
	   */
	  function pluralize (word, count, inclusive) {
	    var pluralized = count === 1
	      ? pluralize.singular(word) : pluralize.plural(word);

	    return (inclusive ? count + ' ' : '') + pluralized;
	  }

	  /**
	   * Pluralize a word.
	   *
	   * @type {Function}
	   */
	  pluralize.plural = replaceWord(
	    irregularSingles, irregularPlurals, pluralRules
	  );

	  /**
	   * Singularize a word.
	   *
	   * @type {Function}
	   */
	  pluralize.singular = replaceWord(
	    irregularPlurals, irregularSingles, singularRules
	  );

	  /**
	   * Add a pluralization rule to the collection.
	   *
	   * @param {(string|RegExp)} rule
	   * @param {string}          replacement
	   */
	  pluralize.addPluralRule = function (rule, replacement) {
	    pluralRules.push([sanitizeRule(rule), replacement]);
	  };

	  /**
	   * Add a singularization rule to the collection.
	   *
	   * @param {(string|RegExp)} rule
	   * @param {string}          replacement
	   */
	  pluralize.addSingularRule = function (rule, replacement) {
	    singularRules.push([sanitizeRule(rule), replacement]);
	  };

	  /**
	   * Add an uncountable word rule.
	   *
	   * @param {(string|RegExp)} word
	   */
	  pluralize.addUncountableRule = function (word) {
	    if (typeof word === 'string') {
	      uncountables[word.toLowerCase()] = true;
	      return;
	    }

	    // Set singular and plural references for the word.
	    pluralize.addPluralRule(word, '$0');
	    pluralize.addSingularRule(word, '$0');
	  };

	  /**
	   * Add an irregular word definition.
	   *
	   * @param {String} single
	   * @param {String} plural
	   */
	  pluralize.addIrregularRule = function (single, plural) {
	    plural = plural.toLowerCase();
	    single = single.toLowerCase();

	    irregularSingles[single] = plural;
	    irregularPlurals[plural] = single;
	  };

	  /**
	   * Irregular rules.
	   */
	  [
	    // Pronouns.
	    ['I', 'we'],
	    ['me', 'us'],
	    ['he', 'they'],
	    ['she', 'they'],
	    ['them', 'them'],
	    ['myself', 'ourselves'],
	    ['yourself', 'yourselves'],
	    ['itself', 'themselves'],
	    ['herself', 'themselves'],
	    ['himself', 'themselves'],
	    ['themself', 'themselves'],
	    ['is', 'are'],
	    ['was', 'were'],
	    ['has', 'have'],
	    ['this', 'these'],
	    ['that', 'those'],
	    // Words ending in with a consonant and `o`.
	    ['echo', 'echoes'],
	    ['dingo', 'dingoes'],
	    ['volcano', 'volcanoes'],
	    ['tornado', 'tornadoes'],
	    ['torpedo', 'torpedoes'],
	    // Ends with `us`.
	    ['genus', 'genera'],
	    ['viscus', 'viscera'],
	    // Ends with `ma`.
	    ['stigma', 'stigmata'],
	    ['stoma', 'stomata'],
	    ['dogma', 'dogmata'],
	    ['lemma', 'lemmata'],
	    ['schema', 'schemata'],
	    ['anathema', 'anathemata'],
	    // Other irregular rules.
	    ['ox', 'oxen'],
	    ['axe', 'axes'],
	    ['die', 'dice'],
	    ['yes', 'yeses'],
	    ['foot', 'feet'],
	    ['eave', 'eaves'],
	    ['goose', 'geese'],
	    ['tooth', 'teeth'],
	    ['quiz', 'quizzes'],
	    ['human', 'humans'],
	    ['proof', 'proofs'],
	    ['carve', 'carves'],
	    ['valve', 'valves'],
	    ['looey', 'looies'],
	    ['thief', 'thieves'],
	    ['groove', 'grooves'],
	    ['pickaxe', 'pickaxes'],
	    ['whiskey', 'whiskies']
	  ].forEach(function (rule) {
	    return pluralize.addIrregularRule(rule[0], rule[1]);
	  });

	  /**
	   * Pluralization rules.
	   */
	  [
	    [/s?$/i, 's'],
	    [/([^aeiou]ese)$/i, '$1'],
	    [/(ax|test)is$/i, '$1es'],
	    [/(alias|[^aou]us|tlas|gas|ris)$/i, '$1es'],
	    [/(e[mn]u)s?$/i, '$1s'],
	    [/([^l]ias|[aeiou]las|[emjzr]as|[iu]am)$/i, '$1'],
	    [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'],
	    [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'],
	    [/(seraph|cherub)(?:im)?$/i, '$1im'],
	    [/(her|at|gr)o$/i, '$1oes'],
	    [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'],
	    [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'],
	    [/sis$/i, 'ses'],
	    [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'],
	    [/([^aeiouy]|qu)y$/i, '$1ies'],
	    [/([^ch][ieo][ln])ey$/i, '$1ies'],
	    [/(x|ch|ss|sh|zz)$/i, '$1es'],
	    [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'],
	    [/(m|l)(?:ice|ouse)$/i, '$1ice'],
	    [/(pe)(?:rson|ople)$/i, '$1ople'],
	    [/(child)(?:ren)?$/i, '$1ren'],
	    [/eaux$/i, '$0'],
	    [/m[ae]n$/i, 'men'],
	    ['thou', 'you']
	  ].forEach(function (rule) {
	    return pluralize.addPluralRule(rule[0], rule[1]);
	  });

	  /**
	   * Singularization rules.
	   */
	  [
	    [/s$/i, ''],
	    [/(ss)$/i, '$1'],
	    [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(?:sis|ses)$/i, '$1sis'],
	    [/(^analy)(?:sis|ses)$/i, '$1sis'],
	    [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'],
	    [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
	    [/ies$/i, 'y'],
	    [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'],
	    [/\b(mon|smil)ies$/i, '$1ey'],
	    [/(m|l)ice$/i, '$1ouse'],
	    [/(seraph|cherub)im$/i, '$1'],
	    [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|tlas|gas|(?:her|at|gr)o|ris)(?:es)?$/i, '$1'],
	    [/(e[mn]u)s?$/i, '$1'],
	    [/(movie|twelve)s$/i, '$1'],
	    [/(cris|test|diagnos)(?:is|es)$/i, '$1is'],
	    [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'],
	    [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'],
	    [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'],
	    [/(alumn|alg|vertebr)ae$/i, '$1a'],
	    [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
	    [/(matr|append)ices$/i, '$1ix'],
	    [/(pe)(rson|ople)$/i, '$1rson'],
	    [/(child)ren$/i, '$1'],
	    [/(eau)x?$/i, '$1'],
	    [/men$/i, 'man']
	  ].forEach(function (rule) {
	    return pluralize.addSingularRule(rule[0], rule[1]);
	  });

	  /**
	   * Uncountable rules.
	   */
	  [
	    // Singular words with no plurals.
	    'advice',
	    'adulthood',
	    'agenda',
	    'aid',
	    'alcohol',
	    'ammo',
	    'athletics',
	    'bison',
	    'blood',
	    'bream',
	    'buffalo',
	    'butter',
	    'carp',
	    'cash',
	    'chassis',
	    'chess',
	    'clothing',
	    'commerce',
	    'cod',
	    'cooperation',
	    'corps',
	    'digestion',
	    'debris',
	    'diabetes',
	    'energy',
	    'equipment',
	    'elk',
	    'excretion',
	    'expertise',
	    'flounder',
	    'fun',
	    'gallows',
	    'garbage',
	    'graffiti',
	    'headquarters',
	    'health',
	    'herpes',
	    'highjinks',
	    'homework',
	    'housework',
	    'information',
	    'jeans',
	    'justice',
	    'kudos',
	    'labour',
	    'literature',
	    'machinery',
	    'mackerel',
	    'mail',
	    'media',
	    'mews',
	    'moose',
	    'music',
	    'news',
	    'pike',
	    'plankton',
	    'pliers',
	    'pollution',
	    'premises',
	    'rain',
	    'research',
	    'rice',
	    'salmon',
	    'scissors',
	    'series',
	    'sewage',
	    'shambles',
	    'shrimp',
	    'species',
	    'staff',
	    'swine',
	    'trout',
	    'traffic',
	    'transporation',
	    'tuna',
	    'wealth',
	    'welfare',
	    'whiting',
	    'wildebeest',
	    'wildlife',
	    'you',
	    // Regexes.
	    /pox$/i, // "chickpox", "smallpox"
	    /ois$/i,
	    /deer$/i, // "deer", "reindeer"
	    /fish$/i, // "fish", "blowfish", "angelfish"
	    /sheep$/i,
	    /measles$/i,
	    /[^aeiou]ese$/i // "chinese", "japanese"
	  ].forEach(pluralize.addUncountableRule);

	  return pluralize;
	});


/***/ },
/* 392 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = stringHelper;

	var _pluralize = __webpack_require__(391);

	var _pluralize2 = _interopRequireDefault(_pluralize);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function stringHelper() {
	  Object.defineProperty(String.prototype, "to_bool", { get: function get() {
	      return (/^(true|1)$/i.test(this)
	      );
	    } });
	  String.prototype.pluralize = function () {
	    var nb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 42;
	    var include = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

	    return (0, _pluralize2.default)(this, nb, include);
	  };
	}

/***/ },
/* 393 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = jqueryHelper;

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function jqueryHelper() {
	  jQuery.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

	  _jquery2.default.fn.incr = function () {
	    var delta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
	    var inverse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

	    if (!(0, _jquery2.default)(this).length) return;
	    if (inverse) delta = -delta;

	    var html = (0, _jquery2.default)(this).html().trim(),
	        parts = false;
	    if (parts = html.match(/^(\d+)\s*([\D]+)$/m)) return (0, _jquery2.default)(this).html(parts[2].pluralize(parseInt(parts[1], 10) + delta, true));else return (0, _jquery2.default)(this).html(parseInt(html, 10) + delta);
	  };

	  _jquery2.default.fn.decr = function () {
	    var delta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
	    var inverse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

	    return (0, _jquery2.default)(this).incr(-delta, inverse);
	  };

	  _jquery2.default.fn.reverse_state = function (_) {
	    var old_state = (0, _jquery2.default)(this).attr('data-state');
	    (0, _jquery2.default)(this).attr('data-state', { 'true': 'false', 'false': 'true' }[old_state]);
	    return old_state.to_bool;
	  };

	  _jquery2.default.fn.state = function (_) {
	    var state = (0, _jquery2.default)(this).attr('data-state');

	    return state ? state.to_bool : undefined;
	  };

	  _jquery2.default.fn.inputWrapper = function (text) {
	    this.text = text;

	    this.each(function (ctx, item) {
	      span = (0, _jquery2.default)('<span data-input-wrapper>' + this.text + '</span>');
	      (0, _jquery2.default)(item).after(span).css("text-indent", (0, _jquery2.default)(span).outerWidth()).css("padding", 0);
	      (0, _jquery2.default)(item).parent().attr("data-input-container", "");
	    });
	  };

	  _jquery2.default.rails.isCrossDomain = function (_) {
	    return false;
	  };

	  // Short range ajax requests

	  _jquery2.default.signedAjax = function (opts) {
	    opts.xhrFields = {
	      withCredentials: true
	    };

	    return _jquery2.default.ajax(opts);
	  };

	  // API ajax requests
	  _jquery2.default.api = function (opts) {
	    var host = window.api_endpoint || (document.location.hostname == 'localhost' ? 'http://localhost:13000' : 'api.intra.42.fr');

	    if (opts.url && opts.url.match("http") == null) {
	      var url = opts.url[0] == '/' ? opts.url : '/' + opts.url;
	      opts.url = '' + host + url;
	    }

	    if (!intra_credentials) {
	      console.warn("Intra credentials are not accessible !");
	      return false;
	    }
	    opts.xhrFields = {
	      withCredentials: true
	    };
	    opts.headers = {
	      Authorization: 'Bearer ' + intra_credentials.token
	    };
	    return _jquery2.default.ajax(opts);
	  };

	  _jquery2.default.fn.bindBefore = function (name, fn, fn_ref) {
	    this.on(name, fn);
	    this.each(function (_) {
	      var handlers = _jquery2.default._data(this, 'events')[name.split('.')[0]];
	      var handler = handlers.pop();

	      handlers.splice(_jquery2.default.inArray(fn_ref, handlers), 0, handler);
	    });
	  };

	  _jquery2.default.fn.bindAfter = function (name, fn, fn_ref) {
	    this.on(name, fn);
	    this.each(function (_) {
	      var handlers = _jquery2.default._data(this, 'events')[name.split('.')[0]];
	      var handler = handlers.pop();

	      handlers.splice(_jquery2.default.inArray(fn_ref, handlers) + 1, 0, handler);
	    });
	  };

	  _jquery2.default.fn.bindFirst = function (name, fn) {
	    this.on(name, fn);
	    this.each(function (_) {
	      var handlers = _jquery2.default._data(this, 'events')[name.split('.')[0]];
	      var handler = handlers.pop();

	      handlers.splice(0, 0, handler);
	    });
	  };

	  _jquery2.default.turbo = {
	    version: '3.0.0',
	    isReady: false,
	    use: function use(load, fetch) {
	      return (0, _jquery2.default)(document).off('.turbo').on("" + load + ".turbo", this.onLoad).on("" + fetch + ".turbo", this.onFetch);
	    },
	    addCallback: function addCallback(callback) {
	      if (_jquery2.default.turbo.isReady) {
	        callback(_jquery2.default);
	      }
	      return (0, _jquery2.default)(document).on('turbo:ready', function () {
	        return callback(_jquery2.default);
	      });
	    },
	    onLoad: function onLoad() {
	      _jquery2.default.turbo.isReady = true;
	      return (0, _jquery2.default)(document).trigger('turbo:ready');
	    },
	    onFetch: function onFetch() {
	      return _jquery2.default.turbo.isReady = false;
	    },
	    register: function register() {
	      //$(this.onLoad);
	      return _jquery2.default.fn.ready = this.addCallback;
	    }
	  };
	}

/***/ },
/* 394 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
		value: true
	});
	exports.default = bootstrapHelper;

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	__webpack_require__(12);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function bootstrapHelper() {
		(0, _jquery2.default)("a[rel~=popover], .has-popover").popover({ trigger: "hover" });
		(0, _jquery2.default)("a[rel~=tooltip], .has-tooltip").tooltip();
		(0, _jquery2.default)("[data-toggle='tooltip']").tooltip();
		(0, _jquery2.default)('body').scrollspy({ target: '#navbar-scale', offset: 30 });
	}

/***/ },
/* 395 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var DataEvents = function () {
	  function DataEvents() {
	    _classCallCheck(this, DataEvents);

	    this.refresh();
	  }

	  _createClass(DataEvents, [{
	    key: 'refresh',
	    value: function refresh() {
	      this.attachFocusEvents();
	      this.attachToggleEvents();
	    }
	  }, {
	    key: 'attachFocusEvents',
	    value: function attachFocusEvents() {
	      (0, _jquery2.default)("[data-event-focus]").click(function () {
	        (0, _jquery2.default)((0, _jquery2.default)(this).attr('data-event-focus')).focus();
	      });
	    }
	  }, {
	    key: 'attachToggleEvents',
	    value: function attachToggleEvents() {
	      (0, _jquery2.default)("[data-event-toggle]").each(function () {
	        var _this = this;

	        var _container = (0, _jquery2.default)(this).attr('data-event-container');
	        var _tgt = (0, _jquery2.default)(this).attr('data-event-toggle');
	        var _target = _container ? (0, _jquery2.default)(this).parents(_container) : (0, _jquery2.default)(this).parent();
	        (0, _jquery2.default)(_target).find(_tgt).addClass("hidden");
	        (0, _jquery2.default)(this).click(function (e) {
	          e.stopImmediatePropagation();
	          (0, _jquery2.default)(_target).find(_tgt).toggleClass("hidden");
	          (0, _jquery2.default)(_this).toggleClass("active");
	          return false;
	        });
	      });
	    }
	  }]);

	  return DataEvents;
	}();

	DataEvents.singleton = undefined;

	DataEvents.refresh = function () {
	  if (DataEvents.singleton === undefined) {
	    DataEvents.singleton = new DataEvents();
	  }
	  DataEvents.singleton.refresh();
	};

	exports.default = DataEvents;

/***/ },
/* 396 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _message = __webpack_require__(397);

	var _message2 = _interopRequireDefault(_message);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Callbacks = function Callbacks() {
	  _classCallCheck(this, Callbacks);

	  new _message2.default();
	};

	exports.default = Callbacks;

/***/ },
/* 397 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _base = __webpack_require__(398);

	var _base2 = _interopRequireDefault(_base);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var CallbackMessage = function (_CallbackBase) {
	  _inherits(CallbackMessage, _CallbackBase);

	  function CallbackMessage() {
	    _classCallCheck(this, CallbackMessage);

	    return _possibleConstructorReturn(this, (CallbackMessage.__proto__ || Object.getPrototypeOf(CallbackMessage)).apply(this, arguments));
	  }

	  _createClass(CallbackMessage, [{
	    key: 'before_click_star',
	    value: function before_click_star(link) {
	      (0, _jquery2.default)("#favorite_count").incr(1, (0, _jquery2.default)(link).reverse_state());
	    }
	  }, {
	    key: 'before_click_pin',
	    value: function before_click_pin(link) {
	      (0, _jquery2.default)(link).addClass("active");
	    }
	  }, {
	    key: 'before_click_lock',
	    value: function before_click_lock(link) {
	      (0, _jquery2.default)(link).addClass("active");
	    }
	  }, {
	    key: 'before_click_upvote',
	    value: function before_click_upvote(link, uided) {
	      var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

	      // console.log("Before !", this, $)
	      if (callback && (0, _jquery2.default)(uided).siblings('[data-uid=downvote]').state()) this.before_click_downvote(undefined, (0, _jquery2.default)(uided).siblings('[data-uid=downvote]'), false);

	      var old_state = (0, _jquery2.default)(uided).reverse_state();
	      (0, _jquery2.default)(uided).find("span.count").incr(1, old_state);
	      (0, _jquery2.default)(uided).siblings(".vote-summary").incr(1, old_state);
	      if ((0, _jquery2.default)(uided).parents(".reply-actions").length) {
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").incr(1, old_state);
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").attr('data-vote-count', (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").html());
	      }
	    }
	  }, {
	    key: 'before_click_downvote',
	    value: function before_click_downvote(link, uided) {
	      var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

	      // console.log(uided)
	      if (callback && (0, _jquery2.default)(uided).siblings('[data-uid=upvote]').state()) this.before_click_upvote(undefined, (0, _jquery2.default)(uided).siblings('[data-uid=upvote]'), false);

	      var old_state = (0, _jquery2.default)(uided).reverse_state();
	      (0, _jquery2.default)(uided).find("span.count").incr(1, old_state);
	      (0, _jquery2.default)(uided).siblings(".vote-summary").incr(1, !old_state);
	      if ((0, _jquery2.default)(uided).parents(".reply-actions").length) {
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").incr(-1, old_state);
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").attr('data-vote-count', (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").html());
	      }
	    }
	  }, {
	    key: 'before_click_trollvote',
	    value: function before_click_trollvote(link, uided) {
	      (0, _jquery2.default)(uided).find("span.count").incr(1, (0, _jquery2.default)(uided).reverse_state());
	    }
	  }, {
	    key: 'before_click_problem',
	    value: function before_click_problem(link, uided) {
	      (0, _jquery2.default)(uided).find("span.count").incr(1, (0, _jquery2.default)(uided).reverse_state());
	    }
	  }, {
	    key: 'success_click_upvote',
	    value: function success_click_upvote(link, uided, value) {
	      (0, _jquery2.default)(uided).find("span.count").html(value['upvote_count']);

	      if ((0, _jquery2.default)(uided).siblings(".vote-summary").length) (0, _jquery2.default)(uided).siblings(".vote-summary").html(value['totalvote_count']);
	      if ((0, _jquery2.default)(uided).parents(".reply-actions").length) {
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").html(value['totalvote_count']);
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").attr('data-vote-count', (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").html());
	      }
	      (0, _jquery2.default)(uided).siblings('[data-uid=downvote]').find("span.count").html(value['downvote_count']);
	    }
	  }, {
	    key: 'success_click_downvote',
	    value: function success_click_downvote(link, uided, value) {
	      (0, _jquery2.default)(uided).find("span.count").html(value['downvote_count']);

	      if ((0, _jquery2.default)(uided).siblings(".vote-summary").length) (0, _jquery2.default)(uided).siblings(".vote-summary").html(value['totalvote_count']);
	      if ((0, _jquery2.default)(uided).parents(".reply-actions").length) {
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").html(value['totalvote_count']);
	        (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").attr('data-vote-count', (0, _jquery2.default)(uided).parents(".reply-actions").siblings(".reply-vote-summary").html());
	      }
	      (0, _jquery2.default)(uided).siblings('[data-uid=upvote]').find("span.count").html(value['upvote_count']);
	    }
	  }, {
	    key: 'success_click_trollvote',
	    value: function success_click_trollvote(link, uided, value) {
	      (0, _jquery2.default)(uided).find("span.count").html(value['kind_count']);
	    }
	  }, {
	    key: 'success_click_problem',
	    value: function success_click_problem(link, uided, value) {
	      (0, _jquery2.default)(uided).find("span.count").html(value['kind_count']);
	    }
	  }, {
	    key: 'success_click_pin',
	    value: function success_click_pin(link, uided, value) {
	      if (value == "OK") (0, _jquery2.default)(link).reverse_state();
	      return (0, _jquery2.default)(link).state() ? (0, _jquery2.default)(link).addClass("active") : (0, _jquery2.default)(link).removeClass("active");
	    }
	  }, {
	    key: 'success_click_lock',
	    value: function success_click_lock(link, uided, value) {
	      if (value == "OK") (0, _jquery2.default)(link).reverse_state();
	      return (0, _jquery2.default)(link).state() ? (0, _jquery2.default)(link).addClass("active icon-lock").removeClass("icon-unlock") : (0, _jquery2.default)(link).removeClass("active icon-lock").addClass("icon-unlock");
	    }
	  }, {
	    key: 'success_click_star',
	    value: function success_click_star(link, uided, value) {
	      if (value.kind != "Topic") {
	        if (value.starred) {
	          var elt = (0, _jquery2.default)(link).parent().clone();

	          elt.attr("data-tag-kind", "starred");
	          (0, _jquery2.default)("[data-tag-kind='starred']").last().after(elt);
	        } else (0, _jquery2.default)('[data-tag-kind=\'starred\'][data-tag-name=\'' + value.name + '\']').remove();
	      } else return value.starred ? (0, _jquery2.default)(link).html('Unwatch') : (0, _jquery2.default)(link).html('Watch');
	    }
	  }]);

	  return CallbackMessage;
	}(_base2.default);

	(0, _jquery2.default)(function () {
	  (0, _jquery2.default)("ul.pagination li a[href*=messages]").each(function () {
	    (0, _jquery2.default)(this).attr('href', (0, _jquery2.default)(this).attr('href').replace("messages/timed", "messages/pagination/timed"));
	  });
	});

	exports.default = CallbackMessage;

/***/ },
/* 398 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var CallbackBase = function () {
	  function CallbackBase() {
	    _classCallCheck(this, CallbackBase);

	    var self = this;

	    (0, _jquery2.default)('body').on('click', 'a[data-uid], [data-uid] a, button[data-uid], [data-uid] button', function (e) {
	      var link = void 0,
	          uided = void 0,
	          uid = void 0,
	          method = void 0;

	      if ((0, _jquery2.default)(this).is('[data-uid]')) {
	        link = this;
	        uided = this;
	        uid = (0, _jquery2.default)(link).data('uid');
	        method = (0, _jquery2.default)(link).data('method') || 'GET';
	      } else {
	        // @FIXME data-uid nested
	        link = this;
	        uided = (0, _jquery2.default)(link).parents('[data-uid]');
	        uid = (0, _jquery2.default)(uided).data('uid');
	        method = (0, _jquery2.default)(link).parents('[data-method]').data('method') || 'GET';
	      }

	      var callback_base = 'click_' + uid;
	      self.call_callback(self, callback_base, "before", link, uided);

	      _jquery2.default.ajax({ type: method, url: (0, _jquery2.default)(link).parents('form').attr('action') }).success(function (value) {
	        self.call_callback(self, callback_base, "success", link, uided, value);
	      }).error(function (_) {
	        self.call_callback(self, callback_base, "error", link, uided);
	      }).done(function (_) {
	        self.call_callback(self, callback_base, "done", link, uided);
	      });

	      e.stopPropagation();
	      return false;
	    });
	  }

	  _createClass(CallbackBase, [{
	    key: 'call_callback',
	    value: function call_callback(callback_obj, base, type, link, uided, value) {
	      if (typeof callback_obj[type + '_' + base] == "function") callback_obj[type + '_' + base](link, uided, value);
	    }
	  }]);

	  return CallbackBase;
	}();

	exports.default = CallbackBase;

/***/ },
/* 399 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Tags = function () {
	  function Tags() {
	    _classCallCheck(this, Tags);

	    (0, _jquery2.default)("[data-filter-tags]").keyup(function () {
	      var val = _lodash2.default.snakeCase((0, _jquery2.default)(this).val().toLowerCase());
	      (0, _jquery2.default)(".sidebar-tag-item").show();
	      if (val.length > 0) (0, _jquery2.default)('.sidebar-tag-item:not([data-tag-name*=\'' + val + '\'])').hide();
	    });

	    (0, _jquery2.default)("[data-tag-collapse]").each(this.onCollapse());
	    (0, _jquery2.default)("[data-tag-collapse]").click(this.onCollapse());
	  }

	  _createClass(Tags, [{
	    key: 'onCollapse',
	    value: function onCollapse() {
	      var icon_up = "iconf-minus-1";
	      var icon_down = "iconf-add-1";
	      return function () {
	        if ((0, _jquery2.default)(this).hasClass(icon_down)) (0, _jquery2.default)(this).removeClass(icon_down).addClass(icon_up);else (0, _jquery2.default)(this).removeClass(icon_up).addClass(icon_down);
	        var toToggle = (0, _jquery2.default)(this).parent().attr("data-tag-kind");
	        (0, _jquery2.default)('.sidebar-tag-item[data-tag-kind=\'' + toToggle + '\']').toggle();
	      };
	    }
	  }]);

	  return Tags;
	}();

	exports.default = Tags;

/***/ },
/* 400 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function Turbolinks() {

	  // if ('serviceWorker' in navigator) {
	  //   navigator.serviceWorker.register('./service_worker_bg_storage.js').then(registration => console.log('ServiceWorker registration successful with scope: ', registration.scope))
	  //     .catch(err => console.log('ServiceWorker registration failed: ', err));
	  //
	  //   navigator.serviceWorker.addEventListener('message', function(e) {
	  //       if (localStorage.getItem(e.data) !== null) {
	  //         $("body").html(localStorage.getItem(e.data));
	  //       }
	  //       return console.log("ServiceWorkerMessageEvent", e.data);
	  //     }
	  //   );
	  // }


	  document.addEventListener("turbolinks:render", function (event) {
	    if (document.documentElement.hasAttribute("data-turbolinks-preview")) {
	      (0, _jquery2.default)('[data-turbolinks-scaffold]').each(function () {
	        var $el = (0, _jquery2.default)(this);
	        if ($el.find('[data-turbolinks-scaffold]').length === 0) {
	          return $el.data('turbolinks-scaffold') === "inside" ? $el.html('') : $el.hide();
	          // localStorage.setItem($(location).attr('href'), $("body").html());
	        }
	      });
	    }
	  });

	  document.addEventListener("turbolinks:before-visit", function (event) {
	    if (event.data.url.slice(-1) === "#") event.preventDefault();
	  });
	}

	exports.default = Turbolinks;

/***/ },
/* 401 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _marked = __webpack_require__(369);

	var _marked2 = _interopRequireDefault(_marked);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Markdownable = function () {
	  function Markdownable(opts) {
	    _classCallCheck(this, Markdownable);

	    if (_marked2.default == undefined) console.warn("Unable to find marked for client-side markdown compilation.");else {
	      var defaults = {
	        markdownSelector: "[data-markdownable]",
	        markdownAttribute: "data-markdownable"
	      };

	      this.opts = _.extend(defaults, opts);
	      this._generateMarkdown();
	    }
	  }

	  _createClass(Markdownable, [{
	    key: "_generateMarkdown",
	    value: function _generateMarkdown() {
	      var s = this;
	      $(this.opts.markdownSelector).each(function () {
	        $(this).html((0, _marked2.default)($(this).attr(s.opts.markdownAttribute).trim()));
	      });
	    }
	  }]);

	  return Markdownable;
	}();

	Markdownable.singleton = undefined;

	Markdownable.get = function () {
	  if (Markdownable.singleton === undefined) {
	    Markdownable.singleton = new Markdownable();
	  }
	  return Markdownable.singleton;
	};

	Markdownable._generateMarkdown = function () {
	  Markdownable.get()._generateMarkdown();
	};

	exports.default = Markdownable;

/***/ },
/* 402 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var ManageAttachments = function () {
	  function ManageAttachments() {
	    var _this = this;

	    _classCallCheck(this, ManageAttachments);

	    if ((0, _jquery2.default)("[data-attachments-url]").length === 0) return;
	    _jquery2.default.getJSON((0, _jquery2.default)("[data-attachments-url]").data("attachments-url"), function (res) {
	      _this.values = res;
	      (0, _jquery2.default)("form .attachment_kind input:hidden").each(function (i, e) {
	        if ((0, _jquery2.default)(e).parents("form").find(".attachment_fields input").length == 0) _this.changed(e, (0, _jquery2.default)(e).val());
	      });
	    });
	    (0, _jquery2.default)('form').on('change', '#attachment_select', function (e) {
	      _this.changed(e.target);
	    });
	  }

	  _createClass(ManageAttachments, [{
	    key: "changed",
	    value: function changed(elem) {
	      var model = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : (0, _jquery2.default)(elem).find("option:checked").html().toLowerCase();

	      var attachments_fields = (0, _jquery2.default)(elem).parents(".form-group").siblings(".attachment_fields");

	      var time = new Date().getTime();
	      var basename = (0, _jquery2.default)(elem).attr("name");
	      var fields = "<div class='form-group input optional project_attachements'>";

	      _.each(this.values[model], function (value, key) {
	        fields += "<div class='col-sm-12'><input class='hidden optional form-control' value='" + model + "' name='" + basename.replace("[kind]", "[attachable_attributes][" + time + "][attachable_type]]") + "' /></div>";
	        fields += "<label class='select optional col-sm-2 control-label' for='project_attachements_attributes_" + time + "_" + key + "'>" + key + "</label>";
	        fields += "<div class='col-sm-10'>";
	        if (value == "string") fields += "<input class='input optional form-control' id='project_attachements_attributes_" + time + "_" + key + "' name='" + basename.replace("[kind]", "[attachable_attributes][" + time + "][" + key + "]") + "' />";else if (value == "text") fields += "<textarea class='text optional form-control' id='project_attachements_attributes_" + time + "_" + key + "' name='" + basename.replace("[kind]", "[attachable_attributes][" + time + "][" + key + "]") + "' />";else if (value == "upload") {
	          fields += "<input class='file optional form-control' type='file' id='project_attachements_attributes_" + time + "_" + key + "' name='" + basename.replace("[kind]", "[attachable_attributes][" + time + "][" + key + "]") + "' />";

	          var form = (0, _jquery2.default)(elem).parents("form").first();
	          if (form) form.attr("enctype", "multipart/form-data");
	        }

	        fields += "</div>";
	      });

	      fields += "</div>";
	      (0, _jquery2.default)(attachments_fields).html(fields);
	    }
	  }]);

	  return ManageAttachments;
	}();

	exports.default = ManageAttachments;

/***/ },
/* 403 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var SimplePreview = function SimplePreview(opts) {
	  _classCallCheck(this, SimplePreview);

	  var defaults = { bindSelector: "data-simple-preview" };
	  this.opts = _lodash2.default.extend(defaults, opts);
	  var self = this;
	  (0, _jquery2.default)('[' + this.opts.bindSelector + ']').each(function (e) {
	    var elt = this;
	    var attr = (0, _jquery2.default)(this).attr(self.opts.bindSelector);
	    if (attr) {
	      (0, _jquery2.default)(attr).keyup(function () {
	        (0, _jquery2.default)(elt).html((0, _jquery2.default)(this).val());
	      });
	    }
	  });
	};

	exports.default = SimplePreview;

/***/ },
/* 404 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _marked = __webpack_require__(369);

	var _marked2 = _interopRequireDefault(_marked);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var MarkdownPreview = function MarkdownPreview(opts) {
	  _classCallCheck(this, MarkdownPreview);

	  _marked2.default.setOptions({ sanitize: true });
	  var defaults = { bindSelector: "data-markdown-preview" };
	  this.opts = _lodash2.default.extend(defaults, opts);
	  var self = this;

	  (0, _jquery2.default)('[' + this.opts.bindSelector + ']').each(function (e) {
	    var elt = this;
	    var attr = (0, _jquery2.default)(this).attr(self.opts.bindSelector);

	    if (attr) {
	      (0, _jquery2.default)(elt).html((0, _marked2.default)((0, _jquery2.default)(attr).val()));
	      (0, _jquery2.default)(attr).keyup(function () {
	        (0, _jquery2.default)(elt).html((0, _marked2.default)((0, _jquery2.default)(this).val()));
	      });
	    }
	  });
	};

	exports.default = MarkdownPreview;

/***/ },
/* 405 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 * Displays flashes to users on page load
	 * @memberof common
	 */
	var Flashes = function () {
	  function Flashes() {
	    var _this = this;

	    _classCallCheck(this, Flashes);

	    if (window._flashes == undefined) return;
	    this.lock = false;
	    this.base_url = (0, _jquery2.default)("[data-flashes-url]").attr("data-flashes-url");
	    this.flashes = _.map(window._flashes, function (e) {
	      e.seen = false;
	      e.selector = e.selector || "body";
	      return e;
	    });
	    this.modal = (0, _jquery2.default)("#flashModal");
	    this.modal.on('hidden.bs.modal', function (e) {
	      _this.lock = false;
	      console.log("🔓Lock is unlocked");
	      _this._try_to_display();
	    });
	    this._try_to_display();
	  }

	  _createClass(Flashes, [{
	    key: "_try_to_display",
	    value: function _try_to_display() {
	      var _iteratorNormalCompletion = true;
	      var _didIteratorError = false;
	      var _iteratorError = undefined;

	      try {
	        for (var _iterator = this.flashes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	          var flash = _step.value;

	          if (this._isFlashOnPage(flash) && !flash.seen && !this.lock) this._display(flash);else console.log("Flash " + flash.selector + " is seen or isn't on page...");
	        }
	      } catch (err) {
	        _didIteratorError = true;
	        _iteratorError = err;
	      } finally {
	        try {
	          if (!_iteratorNormalCompletion && _iterator.return) {
	            _iterator.return();
	          }
	        } finally {
	          if (_didIteratorError) {
	            throw _iteratorError;
	          }
	        }
	      }
	    }
	  }, {
	    key: "_display",
	    value: function _display(flash) {
	      this.lock = true;
	      console.log("🔒Lock is locked");
	      flash.seen = true;
	      this._show_modal(flash);
	      this._mark_as_seen(flash);
	    }
	  }, {
	    key: "_isFlashOnPage",
	    value: function _isFlashOnPage(f) {
	      // return true
	      return f.selector == "" || (0, _jquery2.default)(f.selector).length > 0;
	    }
	  }, {
	    key: "_mark_as_seen",
	    value: function _mark_as_seen(f) {
	      _jquery2.default.signedAjax({ url: this.base_url + "/" + f.id + "/read", method: "POST" }).success(function (d) {
	        console.log("👀 Readed !", d);
	      }).error(function (d) {
	        console.warn("Error in flash", d);
	      });
	    }
	  }, {
	    key: "_show_modal",
	    value: function _show_modal(flash) {
	      if (flash.title) this.modal.find("#flashModalLabel").html(flash.title);
	      this.modal.find(".modal-body").html(_.unescape(flash.content));
	      this.modal.modal('show');
	    }
	  }]);

	  return Flashes;
	}();

	exports.default = Flashes;

/***/ },
/* 406 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Fullscreen = function Fullscreen() {
	  var _this = this;

	  _classCallCheck(this, Fullscreen);

	  _jquery2.default.fn.setFullScreen = function (_) {
	    if (!_this[0]) return;
	    if (_this[0].requestFullscreen) _this[0].requestFullscreen();else if (_this[0].mozRequestFullScreen) _this[0].mozRequestFullScreen();else if (_this[0].webkitRequestFullscreen) _this[0].webkitRequestFullscreen();
	  };

	  (0, _jquery2.default)("[data-toggle-fullscreen]").click(function (_) {
	    (0, _jquery2.default)(".page-content").setFullScreen();
	  });
	};

	exports.default = Fullscreen;

/***/ },
/* 407 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Importer = function () {
	  function Importer() {
	    var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

	    _classCallCheck(this, Importer);

	    this.opts = _lodash2.default.merge({
	      errorsSelector: "data-import-errors",
	      textSelector: "data-import-text"
	    }, params);
	    this.target = document.querySelector('[' + this.opts.errorsSelector + '][' + this.opts.textSelector + ']');

	    // No pasaran !
	    if (!this.target) return;

	    this.text = this.target.getAttribute(this.opts.textSelector);
	    this.errors = JSON.parse(this.target.getAttribute(this.opts.errorsSelector));

	    if (!this.text) throw 'Unable to find params text for [' + this.opts.textSelector + ']';

	    this.displayErrors();
	  }

	  _createClass(Importer, [{
	    key: 'displayErrors',
	    value: function displayErrors() {
	      console.log("Displaying errors for data: ", this.errors);

	      this.renderText();
	    }
	  }, {
	    key: 'renderText',
	    value: function renderText() {
	      var _this = this;

	      var parsedText = this.text.split("\n");
	      parsedText = _lodash2.default.map(parsedText, function (e) {
	        return e.split(",");
	      });
	      console.log("Parsed: ", parsedText);

	      var lines = [];
	      var toRenderText = _lodash2.default.map(parsedText, function (arr, line) {
	        if (_this.errors[line]) {
	          var computed_line = _lodash2.default.map(arr, function (field, index) {
	            field_errors = [];
	            (0, _lodash2.default)(_this.errors[line]).filter(function (e) {
	              e.meta;
	            }).each(function (err) {
	              console.log('For field ' + field + ', ' + err.meta.index + ' == ' + index);
	              if (err.meta.index == index) field_errors.push(err.error);
	            }).value();

	            if (field_errors.length > 0) return '<b class=\'text-danger\' data-toggle=\'tooltip\' data-placement=\'top\' title=\'' + field_errors.join(', ') + '\'>' + field + '</b>';else return '<span>' + field + '</span>';
	          }).join(",");

	          return '<span class=\'text-danger\'>' + computed_line + '</span>';
	        } else {
	          console.log('No errors on line ' + line);
	          return '<span class=\'text-success\'>' + arr.join(',') + '</span>';
	        }
	      }).join("</br>");

	      var rendered = '<div class="js-import-results">' + toRenderText + '</div>';
	      (0, _jquery2.default)(this.target).append(rendered);
	      (0, _jquery2.default)('[data-toggle="tooltip"]').tooltip();
	    }
	  }]);

	  return Importer;
	}();

	exports.default = Importer;

/***/ },
/* 408 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Cache = function Cache() {
	  _classCallCheck(this, Cache);

	  var _$element = (0, _jquery2.default)('[data-cache]');
	  _$element.find('[data-cache-target]').each(function () {
	    var $content = (0, _jquery2.default)(this);
	    var $target = (0, _jquery2.default)('' + $content.data('cache-target'));
	    $target.html($content.html());
	  });
	};

	exports.default = Cache;

/***/ },
/* 409 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Lockable = function () {
	  function Lockable() {
	    var _this = this;

	    _classCallCheck(this, Lockable);

	    var _formToData = this._form_to_data;

	    if ((0, _jquery2.default)("[data-lockable-url]").length) setInterval(function (_) {
	      return _this._synchronize_locked((0, _jquery2.default)("[data-lockable-url]").data('lockable-url'));
	    }, 10000);
	    if ((0, _jquery2.default)('[data-check-lock-url]').length) setInterval(function (_) {
	      return _this._check_locked((0, _jquery2.default)("[data-check-lock-url]").data('check-lock-url'));
	    }, 10000);

	    (0, _jquery2.default)("#lock_taken .roger").click(function (_) {
	      (0, _jquery2.default)("form").submit(function (_) {
	        _jquery2.default.ajax({
	          url: (0, _jquery2.default)(_this).attr('action'),
	          data: _formToData((0, _jquery2.default)('form')),
	          type: "POST",
	          dataType: "JSON"
	        }).success(function (json) {
	          document.location.href = (0, _jquery2.default)("#lock_taken .roger").attr('href');
	        });
	        return false;
	      });

	      (0, _jquery2.default)("form").submit();
	    });
	  }

	  _createClass(Lockable, [{
	    key: "_synchronize_locked",
	    value: function _synchronize_locked(url) {
	      _jquery2.default.getScript(url);
	    }
	  }, {
	    key: "_check_locked",
	    value: function _check_locked(url) {
	      _jquery2.default.getJSON(url, function (data) {
	        if (data['res'] != "OK") {
	          (0, _jquery2.default)("#lock_taken .modal-body").html(data['res'] || "");
	          (0, _jquery2.default)("#lock_taken").modal("show");
	        }
	      });
	    }
	  }, {
	    key: "_form_to_data",
	    value: function _form_to_data(form) {
	      _jquery2.default.map((0, _jquery2.default)(form).find('input, select, textarea'), function (elem) {
	        return (0, _jquery2.default)(elem).attr('name') + "=" + (0, _jquery2.default)(elem).val();
	      }).join('&');
	    }
	  }]);

	  return Lockable;
	}();

	exports.default = Lockable;

/***/ },
/* 410 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 * @todo
	 * @deprecated
	 */
	var MultipleActions = function () {
	  function MultipleActions() {
	    _classCallCheck(this, MultipleActions);

	    this.selector = ".table.admin_table";

	    if ((0, _jquery2.default)(this.selector).length) {
	      this.bindAll();
	      (0, _jquery2.default)(this.selector).find('.btns').hide();
	      this.on_select_click();
	    }
	  }

	  _createClass(MultipleActions, [{
	    key: 'bindAll',
	    value: function bindAll() {
	      (0, _jquery2.default)(this.selector).on('click', '.select.all', this.on_select_all_click.bind(this));
	      (0, _jquery2.default)(this.selector).on('click', '.select.one', this.on_select_one_click.bind(this));
	      (0, _jquery2.default)(this.selector).on('click', '.select', this.on_select_click.bind(this));
	    }
	  }, {
	    key: 'on_select_click',
	    value: function on_select_click(e) {
	      var _this = this;

	      if (e == undefined) return;
	      (0, _jquery2.default)(e.target).parents(this.selector).find('.btns')[(0, _jquery2.default)(e.target).parents(this.selector).find('.select.one').filter(':checked').length ? 'show' : 'hide']();
	      (0, _jquery2.default)(e.target).parents(this.selector).find('.btns a').each(function (index, btn) {
	        var params = Array.from((0, _jquery2.default)(e.target).parents(_this.selector).find('.select.one').filter(':checked'), function (e) {
	          return (0, _jquery2.default)(e).data('id');
	        });

	        params = params.to_rails_params((0, _jquery2.default)(e.target).parents(_this.selector).data('model'));
	        (0, _jquery2.default)(btn).attr('href', (0, _jquery2.default)(btn).attr('href').split('?')[0] + '?' + params);
	      });
	    }
	  }, {
	    key: 'on_select_all_click',
	    value: function on_select_all_click(e) {
	      (0, _jquery2.default)(e.target).parents(this.selector).find('.select.one').prop('checked', !(0, _jquery2.default)(e.target).parents(this.selector).find('.select.one').filter(':checked').length);
	      (0, _jquery2.default)(e.target).prop('checked', (0, _jquery2.default)(e.target).parents(this.selector).find('.select.one').filter(':checked').length);
	    }
	  }, {
	    key: 'on_select_one_click',
	    value: function on_select_one_click(e) {
	      (0, _jquery2.default)(e.target).parents(this.selector).find('.select.all').prop('checked', !(0, _jquery2.default)(e.target).parents(this.selector).find('.select.one').not(':checked').length);
	    }
	  }]);

	  return MultipleActions;
	}();

	exports.default = MultipleActions;

/***/ },
/* 411 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var RemotePagination = function () {
	  function RemotePagination() {
	    _classCallCheck(this, RemotePagination);

	    if ((0, _jquery2.default)("a[data-remote]").parents("[data-scroll]").length > 0) {
	      (0, _jquery2.default)(window).scroll(function (_) {
	        url = (0, _jquery2.default)('.pagination a[rel=next]').attr('href');
	        if (url && (0, _jquery2.default)(window).scrollTop() > (0, _jquery2.default)(document).height() - (0, _jquery2.default)(window).height() - 50) {
	          (0, _jquery2.default)('.pagination').html('<li><span>Loading...</span></li>');
	          _jquery2.default.getScript(url + "?scroll=true");
	        }
	      });
	    }
	    this.loading_animation();
	    (0, _jquery2.default)(document).ajaxComplete(this.loading_animation);
	  }

	  _createClass(RemotePagination, [{
	    key: "loading_animation",
	    value: function loading_animation() {
	      var _this = this;

	      if ((0, _jquery2.default)('.pagination a[data-remote]').length == 0) return;
	      if ((0, _jquery2.default)("a[data-remote]").length > 0) {
	        if ((0, _jquery2.default)("a[data-remote]").parents("[data-scroll]").length == 0) {
	          (0, _jquery2.default)('.pagination').on('click', "a[data-remote=true]", function (event) {
	            history.pushState('', 'New URL: ' + (0, _jquery2.default)(_this).attr('href'), (0, _jquery2.default)(_this).attr('href'));
	            (0, _jquery2.default)('ul.pagination').empty().html('<li><span>Loading...</span></li>');
	            if ((0, _jquery2.default)(window).scrollTop() > (0, _jquery2.default)('#main-container').offset().top - 50) (0, _jquery2.default)("html, body").animate({ scrollTop: (0, _jquery2.default)('#main-container').offset().top - 50 }, "fast");
	          });
	        }
	      }

	      if ((0, _jquery2.default)("a[data-remote]").parents("[data-scroll]").length > 0) (0, _jquery2.default)('.pagination').hide();
	    }
	  }]);

	  return RemotePagination;
	}();

	exports.default = RemotePagination;

/***/ },
/* 412 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var MenuTrigger = function () {
	  function MenuTrigger() {
	    var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;

	    _classCallCheck(this, MenuTrigger);

	    this.enabled = enabled;
	    this._registerEvents();
	  }

	  _createClass(MenuTrigger, [{
	    key: '_registerEvents',
	    value: function _registerEvents() {
	      var _this = this;

	      if (this.enabled) {
	        (0, _jquery2.default)("[data-trigger-menu]").on('click', function (_) {
	          (0, _jquery2.default)(".left-main-container").toggleClass('opened');
	          (0, _jquery2.default)(_this).toggleClass('closed');
	        });
	      } else (0, _jquery2.default)("[data-trigger-menu]").hide();
	    }
	  }]);

	  return MenuTrigger;
	}();

	exports.default = MenuTrigger;

/***/ },
/* 413 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _sortablejs = __webpack_require__(414);

	var _sortablejs2 = _interopRequireDefault(_sortablejs);

	var _noty = __webpack_require__(415);

	var _noty2 = _interopRequireDefault(_noty);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Sort = function () {
	  function Sort() {
	    var _this = this;

	    _classCallCheck(this, Sort);

	    this.sortables = [];
	    var _updateCB = this._update;

	    (0, _jquery2.default)('ul[data-sortable]').each(function (index, el) {
	      var $el = (0, _jquery2.default)(el);
	      var group = $el.data('group');
	      var config = {
	        group: group,
	        onUpdate: function onUpdate() {
	          if ($el.find("li").length > 0 && group != 'available') _updateCB($el.data('update-url'), group, this.toArray());
	        }
	      };
	      _this.sortables.push(new _sortablejs2.default(el, config));
	    });
	  }

	  _createClass(Sort, [{
	    key: '_update',
	    value: function _update(url, group, values) {
	      var data = {};
	      data[group] = values;
	      _jquery2.default.post(url, data, function (_) {
	        (0, _noty2.default)({
	          layout: 'topRight',
	          type: 'success',
	          text: 'Updated',
	          timeout: 4000
	        });
	      });
	    }
	  }]);

	  return Sort;
	}();

	exports.default = Sort;

/***/ },
/* 414 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/**!
	 * Sortable
	 * @author	RubaXa   <trash@rubaxa.org>
	 * @license MIT
	 */


	(function (factory) {
		"use strict";

		if (true) {
			!(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
		}
		else if (typeof module != "undefined" && typeof module.exports != "undefined") {
			module.exports = factory();
		}
		else if (typeof Package !== "undefined") {
			Sortable = factory();  // export for Meteor.js
		}
		else {
			/* jshint sub:true */
			window["Sortable"] = factory();
		}
	})(function () {
		"use strict";

		var dragEl,
			parentEl,
			ghostEl,
			cloneEl,
			rootEl,
			nextEl,

			scrollEl,
			scrollParentEl,

			lastEl,
			lastCSS,
			lastParentCSS,

			oldIndex,
			newIndex,

			activeGroup,
			autoScroll = {},

			tapEvt,
			touchEvt,

			moved,

			/** @const */
			RSPACE = /\s+/g,

			expando = 'Sortable' + (new Date).getTime(),

			win = window,
			document = win.document,
			parseInt = win.parseInt,

			supportDraggable = !!('draggable' in document.createElement('div')),
			supportCssPointerEvents = (function (el) {
				el = document.createElement('x');
				el.style.cssText = 'pointer-events:auto';
				return el.style.pointerEvents === 'auto';
			})(),

			_silent = false,

			abs = Math.abs,
			slice = [].slice,

			touchDragOverListeners = [],

			_autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
				// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
				if (rootEl && options.scroll) {
					var el,
						rect,
						sens = options.scrollSensitivity,
						speed = options.scrollSpeed,

						x = evt.clientX,
						y = evt.clientY,

						winWidth = window.innerWidth,
						winHeight = window.innerHeight,

						vx,
						vy
					;

					// Delect scrollEl
					if (scrollParentEl !== rootEl) {
						scrollEl = options.scroll;
						scrollParentEl = rootEl;

						if (scrollEl === true) {
							scrollEl = rootEl;

							do {
								if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
									(scrollEl.offsetHeight < scrollEl.scrollHeight)
								) {
									break;
								}
								/* jshint boss:true */
							} while (scrollEl = scrollEl.parentNode);
						}
					}

					if (scrollEl) {
						el = scrollEl;
						rect = scrollEl.getBoundingClientRect();
						vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
						vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
					}


					if (!(vx || vy)) {
						vx = (winWidth - x <= sens) - (x <= sens);
						vy = (winHeight - y <= sens) - (y <= sens);

						/* jshint expr:true */
						(vx || vy) && (el = win);
					}


					if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
						autoScroll.el = el;
						autoScroll.vx = vx;
						autoScroll.vy = vy;

						clearInterval(autoScroll.pid);

						if (el) {
							autoScroll.pid = setInterval(function () {
								if (el === win) {
									win.scrollTo(win.pageXOffset + vx * speed, win.pageYOffset + vy * speed);
								} else {
									vy && (el.scrollTop += vy * speed);
									vx && (el.scrollLeft += vx * speed);
								}
							}, 24);
						}
					}
				}
			}, 30),

			_prepareGroup = function (options) {
				var group = options.group;

				if (!group || typeof group != 'object') {
					group = options.group = {name: group};
				}

				['pull', 'put'].forEach(function (key) {
					if (!(key in group)) {
						group[key] = true;
					}
				});

				options.groups = ' ' + group.name + (group.put.join ? ' ' + group.put.join(' ') : '') + ' ';
			}
		;



		/**
		 * @class  Sortable
		 * @param  {HTMLElement}  el
		 * @param  {Object}       [options]
		 */
		function Sortable(el, options) {
			if (!(el && el.nodeType && el.nodeType === 1)) {
				throw 'Sortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);
			}

			this.el = el; // root element
			this.options = options = _extend({}, options);


			// Export instance
			el[expando] = this;


			// Default options
			var defaults = {
				group: Math.random(),
				sort: true,
				disabled: false,
				store: null,
				handle: null,
				scroll: true,
				scrollSensitivity: 30,
				scrollSpeed: 10,
				draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
				ghostClass: 'sortable-ghost',
				chosenClass: 'sortable-chosen',
				ignore: 'a, img',
				filter: null,
				animation: 0,
				setData: function (dataTransfer, dragEl) {
					dataTransfer.setData('Text', dragEl.textContent);
				},
				dropBubble: false,
				dragoverBubble: false,
				dataIdAttr: 'data-id',
				delay: 0,
				forceFallback: false,
				fallbackClass: 'sortable-fallback',
				fallbackOnBody: false
			};


			// Set default options
			for (var name in defaults) {
				!(name in options) && (options[name] = defaults[name]);
			}

			_prepareGroup(options);

			// Bind all private methods
			for (var fn in this) {
				if (fn.charAt(0) === '_') {
					this[fn] = this[fn].bind(this);
				}
			}

			// Setup drag mode
			this.nativeDraggable = options.forceFallback ? false : supportDraggable;

			// Bind events
			_on(el, 'mousedown', this._onTapStart);
			_on(el, 'touchstart', this._onTapStart);

			if (this.nativeDraggable) {
				_on(el, 'dragover', this);
				_on(el, 'dragenter', this);
			}

			touchDragOverListeners.push(this._onDragOver);

			// Restore sorting
			options.store && this.sort(options.store.get(this));
		}


		Sortable.prototype = /** @lends Sortable.prototype */ {
			constructor: Sortable,

			_onTapStart: function (/** Event|TouchEvent */evt) {
				var _this = this,
					el = this.el,
					options = this.options,
					type = evt.type,
					touch = evt.touches && evt.touches[0],
					target = (touch || evt).target,
					originalTarget = target,
					filter = options.filter;


				if (type === 'mousedown' && evt.button !== 0 || options.disabled) {
					return; // only left button or enabled
				}

				target = _closest(target, options.draggable, el);

				if (!target) {
					return;
				}

				// get the index of the dragged element within its parent
				oldIndex = _index(target);

				// Check filter
				if (typeof filter === 'function') {
					if (filter.call(this, evt, target, this)) {
						_dispatchEvent(_this, originalTarget, 'filter', target, el, oldIndex);
						evt.preventDefault();
						return; // cancel dnd
					}
				}
				else if (filter) {
					filter = filter.split(',').some(function (criteria) {
						criteria = _closest(originalTarget, criteria.trim(), el);

						if (criteria) {
							_dispatchEvent(_this, criteria, 'filter', target, el, oldIndex);
							return true;
						}
					});

					if (filter) {
						evt.preventDefault();
						return; // cancel dnd
					}
				}


				if (options.handle && !_closest(originalTarget, options.handle, el)) {
					return;
				}


				// Prepare `dragstart`
				this._prepareDragStart(evt, touch, target);
			},

			_prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target) {
				var _this = this,
					el = _this.el,
					options = _this.options,
					ownerDocument = el.ownerDocument,
					dragStartFn;

				if (target && !dragEl && (target.parentNode === el)) {
					tapEvt = evt;

					rootEl = el;
					dragEl = target;
					parentEl = dragEl.parentNode;
					nextEl = dragEl.nextSibling;
					activeGroup = options.group;

					dragStartFn = function () {
						// Delayed drag has been triggered
						// we can re-enable the events: touchmove/mousemove
						_this._disableDelayedDrag();

						// Make the element draggable
						dragEl.draggable = true;

						// Chosen item
						_toggleClass(dragEl, _this.options.chosenClass, true);

						// Bind the events: dragstart/dragend
						_this._triggerDragStart(touch);
					};

					// Disable "draggable"
					options.ignore.split(',').forEach(function (criteria) {
						_find(dragEl, criteria.trim(), _disableDraggable);
					});

					_on(ownerDocument, 'mouseup', _this._onDrop);
					_on(ownerDocument, 'touchend', _this._onDrop);
					_on(ownerDocument, 'touchcancel', _this._onDrop);

					if (options.delay) {
						// If the user moves the pointer or let go the click or touch
						// before the delay has been reached:
						// disable the delayed drag
						_on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
						_on(ownerDocument, 'touchend', _this._disableDelayedDrag);
						_on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
						_on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
						_on(ownerDocument, 'touchmove', _this._disableDelayedDrag);

						_this._dragStartTimer = setTimeout(dragStartFn, options.delay);
					} else {
						dragStartFn();
					}
				}
			},

			_disableDelayedDrag: function () {
				var ownerDocument = this.el.ownerDocument;

				clearTimeout(this._dragStartTimer);
				_off(ownerDocument, 'mouseup', this._disableDelayedDrag);
				_off(ownerDocument, 'touchend', this._disableDelayedDrag);
				_off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
				_off(ownerDocument, 'mousemove', this._disableDelayedDrag);
				_off(ownerDocument, 'touchmove', this._disableDelayedDrag);
			},

			_triggerDragStart: function (/** Touch */touch) {
				if (touch) {
					// Touch device support
					tapEvt = {
						target: dragEl,
						clientX: touch.clientX,
						clientY: touch.clientY
					};

					this._onDragStart(tapEvt, 'touch');
				}
				else if (!this.nativeDraggable) {
					this._onDragStart(tapEvt, true);
				}
				else {
					_on(dragEl, 'dragend', this);
					_on(rootEl, 'dragstart', this._onDragStart);
				}

				try {
					if (document.selection) {
						document.selection.empty();
					} else {
						window.getSelection().removeAllRanges();
					}
				} catch (err) {
				}
			},

			_dragStarted: function () {
				if (rootEl && dragEl) {
					// Apply effect
					_toggleClass(dragEl, this.options.ghostClass, true);

					Sortable.active = this;

					// Drag start event
					_dispatchEvent(this, rootEl, 'start', dragEl, rootEl, oldIndex);
				}
			},

			_emulateDragOver: function () {
				if (touchEvt) {
					if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
						return;
					}

					this._lastX = touchEvt.clientX;
					this._lastY = touchEvt.clientY;

					if (!supportCssPointerEvents) {
						_css(ghostEl, 'display', 'none');
					}

					var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY),
						parent = target,
						groupName = ' ' + this.options.group.name + '',
						i = touchDragOverListeners.length;

					if (parent) {
						do {
							if (parent[expando] && parent[expando].options.groups.indexOf(groupName) > -1) {
								while (i--) {
									touchDragOverListeners[i]({
										clientX: touchEvt.clientX,
										clientY: touchEvt.clientY,
										target: target,
										rootEl: parent
									});
								}

								break;
							}

							target = parent; // store last element
						}
						/* jshint boss:true */
						while (parent = parent.parentNode);
					}

					if (!supportCssPointerEvents) {
						_css(ghostEl, 'display', '');
					}
				}
			},


			_onTouchMove: function (/**TouchEvent*/evt) {
				if (tapEvt) {
					// only set the status to dragging, when we are actually dragging
					if (!Sortable.active) {
						this._dragStarted();
					}

					// as well as creating the ghost element on the document body
					this._appendGhost();

					var touch = evt.touches ? evt.touches[0] : evt,
						dx = touch.clientX - tapEvt.clientX,
						dy = touch.clientY - tapEvt.clientY,
						translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';

					moved = true;
					touchEvt = touch;

					_css(ghostEl, 'webkitTransform', translate3d);
					_css(ghostEl, 'mozTransform', translate3d);
					_css(ghostEl, 'msTransform', translate3d);
					_css(ghostEl, 'transform', translate3d);

					evt.preventDefault();
				}
			},

			_appendGhost: function () {
				if (!ghostEl) {
					var rect = dragEl.getBoundingClientRect(),
						css = _css(dragEl),
						options = this.options,
						ghostRect;

					ghostEl = dragEl.cloneNode(true);

					_toggleClass(ghostEl, options.ghostClass, false);
					_toggleClass(ghostEl, options.fallbackClass, true);

					_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
					_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
					_css(ghostEl, 'width', rect.width);
					_css(ghostEl, 'height', rect.height);
					_css(ghostEl, 'opacity', '0.8');
					_css(ghostEl, 'position', 'fixed');
					_css(ghostEl, 'zIndex', '100000');
					_css(ghostEl, 'pointerEvents', 'none');

					options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);

					// Fixing dimensions.
					ghostRect = ghostEl.getBoundingClientRect();
					_css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
					_css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
				}
			},

			_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
				var dataTransfer = evt.dataTransfer,
					options = this.options;

				this._offUpEvents();

				if (activeGroup.pull == 'clone') {
					cloneEl = dragEl.cloneNode(true);
					_css(cloneEl, 'display', 'none');
					rootEl.insertBefore(cloneEl, dragEl);
				}

				if (useFallback) {

					if (useFallback === 'touch') {
						// Bind touch events
						_on(document, 'touchmove', this._onTouchMove);
						_on(document, 'touchend', this._onDrop);
						_on(document, 'touchcancel', this._onDrop);
					} else {
						// Old brwoser
						_on(document, 'mousemove', this._onTouchMove);
						_on(document, 'mouseup', this._onDrop);
					}

					this._loopId = setInterval(this._emulateDragOver, 50);
				}
				else {
					if (dataTransfer) {
						dataTransfer.effectAllowed = 'move';
						options.setData && options.setData.call(this, dataTransfer, dragEl);
					}

					_on(document, 'drop', this);
					setTimeout(this._dragStarted, 0);
				}
			},

			_onDragOver: function (/**Event*/evt) {
				var el = this.el,
					target,
					dragRect,
					revert,
					options = this.options,
					group = options.group,
					groupPut = group.put,
					isOwner = (activeGroup === group),
					canSort = options.sort;

				if (evt.preventDefault !== void 0) {
					evt.preventDefault();
					!options.dragoverBubble && evt.stopPropagation();
				}

				moved = true;

				if (activeGroup && !options.disabled &&
					(isOwner
						? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
						: activeGroup.pull && groupPut && (
							(activeGroup.name === group.name) || // by Name
							(groupPut.indexOf && ~groupPut.indexOf(activeGroup.name)) // by Array
						)
					) &&
					(evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
				) {
					// Smart auto-scrolling
					_autoScroll(evt, options, this.el);

					if (_silent) {
						return;
					}

					target = _closest(evt.target, options.draggable, el);
					dragRect = dragEl.getBoundingClientRect();

					if (revert) {
						_cloneHide(true);

						if (cloneEl || nextEl) {
							rootEl.insertBefore(dragEl, cloneEl || nextEl);
						}
						else if (!canSort) {
							rootEl.appendChild(dragEl);
						}

						return;
					}


					if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
						(el === evt.target) && (target = _ghostIsLast(el, evt))
					) {

						if (target) {
							if (target.animated) {
								return;
							}

							targetRect = target.getBoundingClientRect();
						}

						_cloneHide(isOwner);

						if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect) !== false) {
							if (!dragEl.contains(el)) {
								el.appendChild(dragEl);
								parentEl = el; // actualization
							}

							this._animate(dragRect, dragEl);
							target && this._animate(targetRect, target);
						}
					}
					else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
						if (lastEl !== target) {
							lastEl = target;
							lastCSS = _css(target);
							lastParentCSS = _css(target.parentNode);
						}


						var targetRect = target.getBoundingClientRect(),
							width = targetRect.right - targetRect.left,
							height = targetRect.bottom - targetRect.top,
							floating = /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display)
								|| (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),
							isWide = (target.offsetWidth > dragEl.offsetWidth),
							isLong = (target.offsetHeight > dragEl.offsetHeight),
							halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
							nextSibling = target.nextElementSibling,
							moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect),
							after
						;

						if (moveVector !== false) {
							_silent = true;
							setTimeout(_unsilent, 30);

							_cloneHide(isOwner);

							if (moveVector === 1 || moveVector === -1) {
								after = (moveVector === 1);
							}
							else if (floating) {
								var elTop = dragEl.offsetTop,
									tgTop = target.offsetTop;

								if (elTop === tgTop) {
									after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
								} else {
									after = tgTop > elTop;
								}
							} else {
								after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
							}

							if (!dragEl.contains(el)) {
								if (after && !nextSibling) {
									el.appendChild(dragEl);
								} else {
									target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
								}
							}

							parentEl = dragEl.parentNode; // actualization

							this._animate(dragRect, dragEl);
							this._animate(targetRect, target);
						}
					}
				}
			},

			_animate: function (prevRect, target) {
				var ms = this.options.animation;

				if (ms) {
					var currentRect = target.getBoundingClientRect();

					_css(target, 'transition', 'none');
					_css(target, 'transform', 'translate3d('
						+ (prevRect.left - currentRect.left) + 'px,'
						+ (prevRect.top - currentRect.top) + 'px,0)'
					);

					target.offsetWidth; // repaint

					_css(target, 'transition', 'all ' + ms + 'ms');
					_css(target, 'transform', 'translate3d(0,0,0)');

					clearTimeout(target.animated);
					target.animated = setTimeout(function () {
						_css(target, 'transition', '');
						_css(target, 'transform', '');
						target.animated = false;
					}, ms);
				}
			},

			_offUpEvents: function () {
				var ownerDocument = this.el.ownerDocument;

				_off(document, 'touchmove', this._onTouchMove);
				_off(ownerDocument, 'mouseup', this._onDrop);
				_off(ownerDocument, 'touchend', this._onDrop);
				_off(ownerDocument, 'touchcancel', this._onDrop);
			},

			_onDrop: function (/**Event*/evt) {
				var el = this.el,
					options = this.options;

				clearInterval(this._loopId);
				clearInterval(autoScroll.pid);
				clearTimeout(this._dragStartTimer);

				// Unbind events
				_off(document, 'mousemove', this._onTouchMove);

				if (this.nativeDraggable) {
					_off(document, 'drop', this);
					_off(el, 'dragstart', this._onDragStart);
				}

				this._offUpEvents();

				if (evt) {
					if (moved) {
						evt.preventDefault();
						!options.dropBubble && evt.stopPropagation();
					}

					ghostEl && ghostEl.parentNode.removeChild(ghostEl);

					if (dragEl) {
						if (this.nativeDraggable) {
							_off(dragEl, 'dragend', this);
						}

						_disableDraggable(dragEl);

						// Remove class's
						_toggleClass(dragEl, this.options.ghostClass, false);
						_toggleClass(dragEl, this.options.chosenClass, false);

						if (rootEl !== parentEl) {
							newIndex = _index(dragEl);

							if (newIndex >= 0) {
								// drag from one list and drop into another
								_dispatchEvent(null, parentEl, 'sort', dragEl, rootEl, oldIndex, newIndex);
								_dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex);

								// Add event
								_dispatchEvent(null, parentEl, 'add', dragEl, rootEl, oldIndex, newIndex);

								// Remove event
								_dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex);
							}
						}
						else {
							// Remove clone
							cloneEl && cloneEl.parentNode.removeChild(cloneEl);

							if (dragEl.nextSibling !== nextEl) {
								// Get the index of the dragged element within its parent
								newIndex = _index(dragEl);

								if (newIndex >= 0) {
									// drag & drop within the same list
									_dispatchEvent(this, rootEl, 'update', dragEl, rootEl, oldIndex, newIndex);
									_dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex);
								}
							}
						}

						if (Sortable.active) {
							if (newIndex === null || newIndex === -1) {
								newIndex = oldIndex;
							}

							_dispatchEvent(this, rootEl, 'end', dragEl, rootEl, oldIndex, newIndex);

							// Save sorting
							this.save();
						}
					}

					// Nulling
					rootEl =
					dragEl =
					parentEl =
					ghostEl =
					nextEl =
					cloneEl =

					scrollEl =
					scrollParentEl =

					tapEvt =
					touchEvt =

					moved =
					newIndex =

					lastEl =
					lastCSS =

					activeGroup =
					Sortable.active = null;
				}
			},


			handleEvent: function (/**Event*/evt) {
				var type = evt.type;

				if (type === 'dragover' || type === 'dragenter') {
					if (dragEl) {
						this._onDragOver(evt);
						_globalDragOver(evt);
					}
				}
				else if (type === 'drop' || type === 'dragend') {
					this._onDrop(evt);
				}
			},


			/**
			 * Serializes the item into an array of string.
			 * @returns {String[]}
			 */
			toArray: function () {
				var order = [],
					el,
					children = this.el.children,
					i = 0,
					n = children.length,
					options = this.options;

				for (; i < n; i++) {
					el = children[i];
					if (_closest(el, options.draggable, this.el)) {
						order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
					}
				}

				return order;
			},


			/**
			 * Sorts the elements according to the array.
			 * @param  {String[]}  order  order of the items
			 */
			sort: function (order) {
				var items = {}, rootEl = this.el;

				this.toArray().forEach(function (id, i) {
					var el = rootEl.children[i];

					if (_closest(el, this.options.draggable, rootEl)) {
						items[id] = el;
					}
				}, this);

				order.forEach(function (id) {
					if (items[id]) {
						rootEl.removeChild(items[id]);
						rootEl.appendChild(items[id]);
					}
				});
			},


			/**
			 * Save the current sorting
			 */
			save: function () {
				var store = this.options.store;
				store && store.set(this);
			},


			/**
			 * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
			 * @param   {HTMLElement}  el
			 * @param   {String}       [selector]  default: `options.draggable`
			 * @returns {HTMLElement|null}
			 */
			closest: function (el, selector) {
				return _closest(el, selector || this.options.draggable, this.el);
			},


			/**
			 * Set/get option
			 * @param   {string} name
			 * @param   {*}      [value]
			 * @returns {*}
			 */
			option: function (name, value) {
				var options = this.options;

				if (value === void 0) {
					return options[name];
				} else {
					options[name] = value;

					if (name === 'group') {
						_prepareGroup(options);
					}
				}
			},


			/**
			 * Destroy
			 */
			destroy: function () {
				var el = this.el;

				el[expando] = null;

				_off(el, 'mousedown', this._onTapStart);
				_off(el, 'touchstart', this._onTapStart);

				if (this.nativeDraggable) {
					_off(el, 'dragover', this);
					_off(el, 'dragenter', this);
				}

				// Remove draggable attributes
				Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
					el.removeAttribute('draggable');
				});

				touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);

				this._onDrop();

				this.el = el = null;
			}
		};


		function _cloneHide(state) {
			if (cloneEl && (cloneEl.state !== state)) {
				_css(cloneEl, 'display', state ? 'none' : '');
				!state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl);
				cloneEl.state = state;
			}
		}


		function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
			if (el) {
				ctx = ctx || document;
				selector = selector.split('.');

				var tag = selector.shift().toUpperCase(),
					re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');

				do {
					if (
						(tag === '>*' && el.parentNode === ctx) || (
							(tag === '' || el.nodeName.toUpperCase() == tag) &&
							(!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
						)
					) {
						return el;
					}
				}
				while (el !== ctx && (el = el.parentNode));
			}

			return null;
		}


		function _globalDragOver(/**Event*/evt) {
			if (evt.dataTransfer) {
				evt.dataTransfer.dropEffect = 'move';
			}
			evt.preventDefault();
		}


		function _on(el, event, fn) {
			el.addEventListener(event, fn, false);
		}


		function _off(el, event, fn) {
			el.removeEventListener(event, fn, false);
		}


		function _toggleClass(el, name, state) {
			if (el) {
				if (el.classList) {
					el.classList[state ? 'add' : 'remove'](name);
				}
				else {
					var className = (' ' + el.className + ' ').replace(RSPACE, ' ').replace(' ' + name + ' ', ' ');
					el.className = (className + (state ? ' ' + name : '')).replace(RSPACE, ' ');
				}
			}
		}


		function _css(el, prop, val) {
			var style = el && el.style;

			if (style) {
				if (val === void 0) {
					if (document.defaultView && document.defaultView.getComputedStyle) {
						val = document.defaultView.getComputedStyle(el, '');
					}
					else if (el.currentStyle) {
						val = el.currentStyle;
					}

					return prop === void 0 ? val : val[prop];
				}
				else {
					if (!(prop in style)) {
						prop = '-webkit-' + prop;
					}

					style[prop] = val + (typeof val === 'string' ? '' : 'px');
				}
			}
		}


		function _find(ctx, tagName, iterator) {
			if (ctx) {
				var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;

				if (iterator) {
					for (; i < n; i++) {
						iterator(list[i], i);
					}
				}

				return list;
			}

			return [];
		}



		function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) {
			var evt = document.createEvent('Event'),
				options = (sortable || rootEl[expando]).options,
				onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);

			evt.initEvent(name, true, true);

			evt.to = rootEl;
			evt.from = fromEl || rootEl;
			evt.item = targetEl || rootEl;
			evt.clone = cloneEl;

			evt.oldIndex = startIndex;
			evt.newIndex = newIndex;

			rootEl.dispatchEvent(evt);

			if (options[onName]) {
				options[onName].call(sortable, evt);
			}
		}


		function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect) {
			var evt,
				sortable = fromEl[expando],
				onMoveFn = sortable.options.onMove,
				retVal;

			evt = document.createEvent('Event');
			evt.initEvent('move', true, true);

			evt.to = toEl;
			evt.from = fromEl;
			evt.dragged = dragEl;
			evt.draggedRect = dragRect;
			evt.related = targetEl || toEl;
			evt.relatedRect = targetRect || toEl.getBoundingClientRect();

			fromEl.dispatchEvent(evt);

			if (onMoveFn) {
				retVal = onMoveFn.call(sortable, evt);
			}

			return retVal;
		}


		function _disableDraggable(el) {
			el.draggable = false;
		}


		function _unsilent() {
			_silent = false;
		}


		/** @returns {HTMLElement|false} */
		function _ghostIsLast(el, evt) {
			var lastEl = el.lastElementChild,
					rect = lastEl.getBoundingClientRect();

			return ((evt.clientY - (rect.top + rect.height) > 5) || (evt.clientX - (rect.right + rect.width) > 5)) && lastEl; // min delta
		}


		/**
		 * Generate id
		 * @param   {HTMLElement} el
		 * @returns {String}
		 * @private
		 */
		function _generateId(el) {
			var str = el.tagName + el.className + el.src + el.href + el.textContent,
				i = str.length,
				sum = 0;

			while (i--) {
				sum += str.charCodeAt(i);
			}

			return sum.toString(36);
		}

		/**
		 * Returns the index of an element within its parent
		 * @param  {HTMLElement} el
		 * @return {number}
		 */
		function _index(el) {
			var index = 0;

			if (!el || !el.parentNode) {
				return -1;
			}

			while (el && (el = el.previousElementSibling)) {
				if (el.nodeName.toUpperCase() !== 'TEMPLATE') {
					index++;
				}
			}

			return index;
		}

		function _throttle(callback, ms) {
			var args, _this;

			return function () {
				if (args === void 0) {
					args = arguments;
					_this = this;

					setTimeout(function () {
						if (args.length === 1) {
							callback.call(_this, args[0]);
						} else {
							callback.apply(_this, args);
						}

						args = void 0;
					}, ms);
				}
			};
		}

		function _extend(dst, src) {
			if (dst && src) {
				for (var key in src) {
					if (src.hasOwnProperty(key)) {
						dst[key] = src[key];
					}
				}
			}

			return dst;
		}


		// Export utils
		Sortable.utils = {
			on: _on,
			off: _off,
			css: _css,
			find: _find,
			is: function (el, selector) {
				return !!_closest(el, selector, el);
			},
			extend: _extend,
			throttle: _throttle,
			closest: _closest,
			toggleClass: _toggleClass,
			index: _index
		};


		/**
		 * Create sortable instance
		 * @param {HTMLElement}  el
		 * @param {Object}      [options]
		 */
		Sortable.create = function (el, options) {
			return new Sortable(el, options);
		};


		// Export
		Sortable.version = '1.4.2';
		return Sortable;
	});


/***/ },
/* 415 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!function(root, factory) {
		 if (true) {
			 !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__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__));
		 } else if (typeof exports === 'object') {
			 module.exports = factory(require('jquery'));
		 } else {
			 factory(root.jQuery);
		 }
	}(this, function($) {

	/*!
	 @package noty - jQuery Notification Plugin
	 @version version: 2.3.8
	 @contributors https://github.com/needim/noty/graphs/contributors

	 @documentation Examples and Documentation - http://needim.github.com/noty/

	 @license Licensed under the MIT licenses: http://www.opensource.org/licenses/mit-license.php
	 */

	    if(typeof Object.create !== 'function') {
	        Object.create = function(o) {
	            function F() {
	            }

	            F.prototype = o;
	            return new F();
	        };
	    }

	    var NotyObject = {

	        init: function(options) {

	            // Mix in the passed in options with the default options
	            this.options = $.extend({}, $.noty.defaults, options);

	            this.options.layout = (this.options.custom) ? $.noty.layouts['inline'] : $.noty.layouts[this.options.layout];

	            if($.noty.themes[this.options.theme])
	                this.options.theme = $.noty.themes[this.options.theme];
	            else
	                this.options.themeClassName = this.options.theme;

	            this.options = $.extend({}, this.options, this.options.layout.options);
	            this.options.id = 'noty_' + (new Date().getTime() * Math.floor(Math.random() * 1000000));

	            // Build the noty dom initial structure
	            this._build();

	            // return this so we can chain/use the bridge with less code.
	            return this;
	        }, // end init

	        _build: function() {

	            // Generating noty bar
	            var $bar = $('<div class="noty_bar noty_type_' + this.options.type + '"></div>').attr('id', this.options.id);
	            $bar.append(this.options.template).find('.noty_text').html(this.options.text);

	            this.$bar = (this.options.layout.parent.object !== null) ? $(this.options.layout.parent.object).css(this.options.layout.parent.css).append($bar) : $bar;

	            if(this.options.themeClassName)
	                this.$bar.addClass(this.options.themeClassName).addClass('noty_container_type_' + this.options.type);

	            // Set buttons if available
	            if(this.options.buttons) {

	                // If we have button disable closeWith & timeout options
	                this.options.closeWith = [];
	                this.options.timeout = false;

	                var $buttons = $('<div/>').addClass('noty_buttons');

	                (this.options.layout.parent.object !== null) ? this.$bar.find('.noty_bar').append($buttons) : this.$bar.append($buttons);

	                var self = this;

	                $.each(this.options.buttons, function(i, button) {
	                    var $button = $('<button/>').addClass((button.addClass) ? button.addClass : 'gray').html(button.text).attr('id', button.id ? button.id : 'button-' + i)
	                        .attr('title', button.title)
	                        .appendTo(self.$bar.find('.noty_buttons'))
	                        .on('click', function(event) {
	                            if($.isFunction(button.onClick)) {
	                                button.onClick.call($button, self, event);
	                            }
	                        });
	                });
	            }

	            // For easy access
	            this.$message = this.$bar.find('.noty_message');
	            this.$closeButton = this.$bar.find('.noty_close');
	            this.$buttons = this.$bar.find('.noty_buttons');

	            $.noty.store[this.options.id] = this; // store noty for api

	        }, // end _build

	        show: function() {

	            var self = this;

	            (self.options.custom) ? self.options.custom.find(self.options.layout.container.selector).append(self.$bar) : $(self.options.layout.container.selector).append(self.$bar);

	            if(self.options.theme && self.options.theme.style)
	                self.options.theme.style.apply(self);

	            ($.type(self.options.layout.css) === 'function') ? this.options.layout.css.apply(self.$bar) : self.$bar.css(this.options.layout.css || {});

	            self.$bar.addClass(self.options.layout.addClass);

	            self.options.layout.container.style.apply($(self.options.layout.container.selector), [self.options.within]);

	            self.showing = true;

	            if(self.options.theme && self.options.theme.style)
	                self.options.theme.callback.onShow.apply(this);

	            if($.inArray('click', self.options.closeWith) > -1)
	                self.$bar.css('cursor', 'pointer').one('click', function(evt) {
	                    self.stopPropagation(evt);
	                    if(self.options.callback.onCloseClick) {
	                        self.options.callback.onCloseClick.apply(self);
	                    }
	                    self.close();
	                });

	            if($.inArray('hover', self.options.closeWith) > -1)
	                self.$bar.one('mouseenter', function() {
	                    self.close();
	                });

	            if($.inArray('button', self.options.closeWith) > -1)
	                self.$closeButton.one('click', function(evt) {
	                    self.stopPropagation(evt);
	                    self.close();
	                });

	            if($.inArray('button', self.options.closeWith) == -1)
	                self.$closeButton.remove();

	            if(self.options.callback.onShow)
	                self.options.callback.onShow.apply(self);

	            if (typeof self.options.animation.open == 'string') {
	                self.$bar.css('height', self.$bar.innerHeight());
	                self.$bar.on('click',function(e){
	                    self.wasClicked = true;
	                });
	                self.$bar.show().addClass(self.options.animation.open).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
	                    if(self.options.callback.afterShow) self.options.callback.afterShow.apply(self);
	                    self.showing = false;
	                    self.shown = true;
	                    if(self.hasOwnProperty('wasClicked')){
	                        self.$bar.off('click',function(e){
	                            self.wasClicked = true;
	                        });
	                        self.close();
	                    }
	                });

	            } else {
	                self.$bar.animate(
	                    self.options.animation.open,
	                    self.options.animation.speed,
	                    self.options.animation.easing,
	                    function() {
	                        if(self.options.callback.afterShow) self.options.callback.afterShow.apply(self);
	                        self.showing = false;
	                        self.shown = true;
	                    });
	            }

	            // If noty is have a timeout option
	            if(self.options.timeout)
	                self.$bar.delay(self.options.timeout).promise().done(function() {
	                    self.close();
	                });

	            return this;

	        }, // end show

	        close: function() {

	            if(this.closed) return;
	            if(this.$bar && this.$bar.hasClass('i-am-closing-now')) return;

	            var self = this;

	            if(this.showing) {
	                self.$bar.queue(
	                    function() {
	                        self.close.apply(self);
	                    }
	                );
	                return;
	            }

	            if(!this.shown && !this.showing) { // If we are still waiting in the queue just delete from queue
	                var queue = [];
	                $.each($.noty.queue, function(i, n) {
	                    if(n.options.id != self.options.id) {
	                        queue.push(n);
	                    }
	                });
	                $.noty.queue = queue;
	                return;
	            }

	            self.$bar.addClass('i-am-closing-now');

	            if(self.options.callback.onClose) {
	                self.options.callback.onClose.apply(self);
	            }

	            if (typeof self.options.animation.close == 'string') {
	                self.$bar.addClass(self.options.animation.close).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
	                    if(self.options.callback.afterClose) self.options.callback.afterClose.apply(self);
	                    self.closeCleanUp();
	                });
	            } else {
	                self.$bar.clearQueue().stop().animate(
	                    self.options.animation.close,
	                    self.options.animation.speed,
	                    self.options.animation.easing,
	                    function() {
	                        if(self.options.callback.afterClose) self.options.callback.afterClose.apply(self);
	                    })
	                    .promise().done(function() {
	                        self.closeCleanUp();
	                    });
	            }

	        }, // end close

	        closeCleanUp: function() {

	            var self = this;

	            // Modal Cleaning
	            if(self.options.modal) {
	                $.notyRenderer.setModalCount(-1);
	                if($.notyRenderer.getModalCount() == 0) $('.noty_modal').fadeOut(self.options.animation.fadeSpeed, function() {
	                    $(this).remove();
	                });
	            }

	            // Layout Cleaning
	            $.notyRenderer.setLayoutCountFor(self, -1);
	            if($.notyRenderer.getLayoutCountFor(self) == 0) $(self.options.layout.container.selector).remove();

	            // Make sure self.$bar has not been removed before attempting to remove it
	            if(typeof self.$bar !== 'undefined' && self.$bar !== null) {

	                if (typeof self.options.animation.close == 'string') {
	                    self.$bar.css('transition', 'all 100ms ease').css('border', 0).css('margin', 0).height(0);
	                    self.$bar.one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function() {
	                        self.$bar.remove();
	                        self.$bar = null;
	                        self.closed = true;

	                        if(self.options.theme.callback && self.options.theme.callback.onClose) {
	                            self.options.theme.callback.onClose.apply(self);
	                        }
	                    });
	                } else {
	                    self.$bar.remove();
	                    self.$bar = null;
	                    self.closed = true;
	                }
	            }

	            delete $.noty.store[self.options.id]; // deleting noty from store

	            if(self.options.theme.callback && self.options.theme.callback.onClose) {
	                self.options.theme.callback.onClose.apply(self);
	            }

	            if(!self.options.dismissQueue) {
	                // Queue render
	                $.noty.ontap = true;

	                $.notyRenderer.render();
	            }

	            if(self.options.maxVisible > 0 && self.options.dismissQueue) {
	                $.notyRenderer.render();
	            }

	        }, // end close clean up

	        setText: function(text) {
	            if(!this.closed) {
	                this.options.text = text;
	                this.$bar.find('.noty_text').html(text);
	            }
	            return this;
	        },

	        setType: function(type) {
	            if(!this.closed) {
	                this.options.type = type;
	                this.options.theme.style.apply(this);
	                this.options.theme.callback.onShow.apply(this);
	            }
	            return this;
	        },

	        setTimeout: function(time) {
	            if(!this.closed) {
	                var self = this;
	                this.options.timeout = time;
	                self.$bar.delay(self.options.timeout).promise().done(function() {
	                    self.close();
	                });
	            }
	            return this;
	        },

	        stopPropagation: function(evt) {
	            evt = evt || window.event;
	            if(typeof evt.stopPropagation !== "undefined") {
	                evt.stopPropagation();
	            }
	            else {
	                evt.cancelBubble = true;
	            }
	        },

	        closed : false,
	        showing: false,
	        shown  : false

	    }; // end NotyObject

	    $.notyRenderer = {};

	    $.notyRenderer.init = function(options) {

	        // Renderer creates a new noty
	        var notification = Object.create(NotyObject).init(options);

	        if(notification.options.killer)
	            $.noty.closeAll();

	        (notification.options.force) ? $.noty.queue.unshift(notification) : $.noty.queue.push(notification);

	        $.notyRenderer.render();

	        return ($.noty.returns == 'object') ? notification : notification.options.id;
	    };

	    $.notyRenderer.render = function() {

	        var instance = $.noty.queue[0];

	        if($.type(instance) === 'object') {
	            if(instance.options.dismissQueue) {
	                if(instance.options.maxVisible > 0) {
	                    if($(instance.options.layout.container.selector + ' > li').length < instance.options.maxVisible) {
	                        $.notyRenderer.show($.noty.queue.shift());
	                    }
	                    else {

	                    }
	                }
	                else {
	                    $.notyRenderer.show($.noty.queue.shift());
	                }
	            }
	            else {
	                if($.noty.ontap) {
	                    $.notyRenderer.show($.noty.queue.shift());
	                    $.noty.ontap = false;
	                }
	            }
	        }
	        else {
	            $.noty.ontap = true; // Queue is over
	        }

	    };

	    $.notyRenderer.show = function(notification) {

	        if(notification.options.modal) {
	            $.notyRenderer.createModalFor(notification);
	            $.notyRenderer.setModalCount(+1);
	        }

	        // Where is the container?
	        if(notification.options.custom) {
	            if(notification.options.custom.find(notification.options.layout.container.selector).length == 0) {
	                notification.options.custom.append($(notification.options.layout.container.object).addClass('i-am-new'));
	            }
	            else {
	                notification.options.custom.find(notification.options.layout.container.selector).removeClass('i-am-new');
	            }
	        }
	        else {
	            if($(notification.options.layout.container.selector).length == 0) {
	                $('body').append($(notification.options.layout.container.object).addClass('i-am-new'));
	            }
	            else {
	                $(notification.options.layout.container.selector).removeClass('i-am-new');
	            }
	        }

	        $.notyRenderer.setLayoutCountFor(notification, +1);

	        notification.show();
	    };

	    $.notyRenderer.createModalFor = function(notification) {
	        if($('.noty_modal').length == 0) {
	            var modal = $('<div/>').addClass('noty_modal').addClass(notification.options.theme).data('noty_modal_count', 0);

	            if(notification.options.theme.modal && notification.options.theme.modal.css)
	                modal.css(notification.options.theme.modal.css);

	            modal.prependTo($('body')).fadeIn(notification.options.animation.fadeSpeed);

	            if($.inArray('backdrop', notification.options.closeWith) > -1)
	                modal.on('click', function(e) {
	                    $.noty.closeAll();
	                });
	        }
	    };

	    $.notyRenderer.getLayoutCountFor = function(notification) {
	        return $(notification.options.layout.container.selector).data('noty_layout_count') || 0;
	    };

	    $.notyRenderer.setLayoutCountFor = function(notification, arg) {
	        return $(notification.options.layout.container.selector).data('noty_layout_count', $.notyRenderer.getLayoutCountFor(notification) + arg);
	    };

	    $.notyRenderer.getModalCount = function() {
	        return $('.noty_modal').data('noty_modal_count') || 0;
	    };

	    $.notyRenderer.setModalCount = function(arg) {
	        return $('.noty_modal').data('noty_modal_count', $.notyRenderer.getModalCount() + arg);
	    };

	    // This is for custom container
	    $.fn.noty = function(options) {
	        options.custom = $(this);
	        return $.notyRenderer.init(options);
	    };

	    $.noty = {};
	    $.noty.queue = [];
	    $.noty.ontap = true;
	    $.noty.layouts = {};
	    $.noty.themes = {};
	    $.noty.returns = 'object';
	    $.noty.store = {};

	    $.noty.get = function(id) {
	        return $.noty.store.hasOwnProperty(id) ? $.noty.store[id] : false;
	    };

	    $.noty.close = function(id) {
	        return $.noty.get(id) ? $.noty.get(id).close() : false;
	    };

	    $.noty.setText = function(id, text) {
	        return $.noty.get(id) ? $.noty.get(id).setText(text) : false;
	    };

	    $.noty.setType = function(id, type) {
	        return $.noty.get(id) ? $.noty.get(id).setType(type) : false;
	    };

	    $.noty.clearQueue = function() {
	        $.noty.queue = [];
	    };

	    $.noty.closeAll = function() {
	        $.noty.clearQueue();
	        $.each($.noty.store, function(id, noty) {
	            noty.close();
	        });
	    };

	    var windowAlert = window.alert;

	    $.noty.consumeAlert = function(options) {
	        window.alert = function(text) {
	            if(options)
	                options.text = text;
	            else
	                options = {text: text};

	            $.notyRenderer.init(options);
	        };
	    };

	    $.noty.stopConsumeAlert = function() {
	        window.alert = windowAlert;
	    };

	    $.noty.defaults = {
	        layout      : 'top',
	        theme       : 'defaultTheme',
	        type        : 'alert',
	        text        : '',
	        dismissQueue: true,
	        template    : '<div class="noty_message"><span class="noty_text"></span><div class="noty_close"></div></div>',
	        animation   : {
	            open  : {height: 'toggle'},
	            close : {height: 'toggle'},
	            easing: 'swing',
	            speed : 500,
	            fadeSpeed: 'fast',
	        },
	        timeout     : false,
	        force       : false,
	        modal       : false,
	        maxVisible  : 5,
	        killer      : false,
	        closeWith   : ['click'],
	        callback    : {
	            onShow      : function() {
	            },
	            afterShow   : function() {
	            },
	            onClose     : function() {
	            },
	            afterClose  : function() {
	            },
	            onCloseClick: function() {
	            }
	        },
	        buttons     : false
	    };

	    $(window).on('resize', function() {
	        $.each($.noty.layouts, function(index, layout) {
	            layout.container.style.apply($(layout.container.selector));
	        });
	    });

	    // Helpers
	    window.noty = function noty(options) {
	        return $.notyRenderer.init(options);
	    };

	$.noty.layouts.bottom = {
	    name     : 'bottom',
	    options  : {},
	    container: {
	        object  : '<ul id="noty_bottom_layout_container" />',
	        selector: 'ul#noty_bottom_layout_container',
	        style   : function() {
	            $(this).css({
	                bottom       : 0,
	                left         : '5%',
	                position     : 'fixed',
	                width        : '90%',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 9999999
	            });
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none'
	    },
	    addClass : ''
	};

	$.noty.layouts.bottomCenter = {
	    name     : 'bottomCenter',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_bottomCenter_layout_container" />',
	        selector: 'ul#noty_bottomCenter_layout_container',
	        style   : function() {
	            $(this).css({
	                bottom       : 20,
	                left         : 0,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            $(this).css({
	                left: ($(window).width() - $(this).outerWidth(false)) / 2 + 'px'
	            });
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};


	$.noty.layouts.bottomLeft = {
	    name     : 'bottomLeft',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_bottomLeft_layout_container" />',
	        selector: 'ul#noty_bottomLeft_layout_container',
	        style   : function() {
	            $(this).css({
	                bottom       : 20,
	                left         : 20,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            if(window.innerWidth < 600) {
	                $(this).css({
	                    left: 5
	                });
	            }
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};
	$.noty.layouts.bottomRight = {
	    name     : 'bottomRight',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_bottomRight_layout_container" />',
	        selector: 'ul#noty_bottomRight_layout_container',
	        style   : function() {
	            $(this).css({
	                bottom       : 20,
	                right        : 20,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            if(window.innerWidth < 600) {
	                $(this).css({
	                    right: 5
	                });
	            }
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};
	$.noty.layouts.center = {
	    name     : 'center',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_center_layout_container" />',
	        selector: 'ul#noty_center_layout_container',
	        style   : function() {
	            $(this).css({
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            // getting hidden height
	            var dupe = $(this).clone().css({visibility: "hidden", display: "block", position: "absolute", top: 0, left: 0}).attr('id', 'dupe');
	            $("body").append(dupe);
	            dupe.find('.i-am-closing-now').remove();
	            dupe.find('li').css('display', 'block');
	            var actual_height = dupe.height();
	            dupe.remove();

	            if($(this).hasClass('i-am-new')) {
	                $(this).css({
	                    left: ($(window).width() - $(this).outerWidth(false)) / 2 + 'px',
	                    top : ($(window).height() - actual_height) / 2 + 'px'
	                });
	            }
	            else {
	                $(this).animate({
	                    left: ($(window).width() - $(this).outerWidth(false)) / 2 + 'px',
	                    top : ($(window).height() - actual_height) / 2 + 'px'
	                }, 500);
	            }

	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};
	$.noty.layouts.centerLeft = {
	    name     : 'centerLeft',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_centerLeft_layout_container" />',
	        selector: 'ul#noty_centerLeft_layout_container',
	        style   : function() {
	            $(this).css({
	                left         : 20,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            // getting hidden height
	            var dupe = $(this).clone().css({visibility: "hidden", display: "block", position: "absolute", top: 0, left: 0}).attr('id', 'dupe');
	            $("body").append(dupe);
	            dupe.find('.i-am-closing-now').remove();
	            dupe.find('li').css('display', 'block');
	            var actual_height = dupe.height();
	            dupe.remove();

	            if($(this).hasClass('i-am-new')) {
	                $(this).css({
	                    top: ($(window).height() - actual_height) / 2 + 'px'
	                });
	            }
	            else {
	                $(this).animate({
	                    top: ($(window).height() - actual_height) / 2 + 'px'
	                }, 500);
	            }

	            if(window.innerWidth < 600) {
	                $(this).css({
	                    left: 5
	                });
	            }

	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};

	$.noty.layouts.centerRight = {
	    name     : 'centerRight',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_centerRight_layout_container" />',
	        selector: 'ul#noty_centerRight_layout_container',
	        style   : function() {
	            $(this).css({
	                right        : 20,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            // getting hidden height
	            var dupe = $(this).clone().css({visibility: "hidden", display: "block", position: "absolute", top: 0, left: 0}).attr('id', 'dupe');
	            $("body").append(dupe);
	            dupe.find('.i-am-closing-now').remove();
	            dupe.find('li').css('display', 'block');
	            var actual_height = dupe.height();
	            dupe.remove();

	            if($(this).hasClass('i-am-new')) {
	                $(this).css({
	                    top: ($(window).height() - actual_height) / 2 + 'px'
	                });
	            }
	            else {
	                $(this).animate({
	                    top: ($(window).height() - actual_height) / 2 + 'px'
	                }, 500);
	            }

	            if(window.innerWidth < 600) {
	                $(this).css({
	                    right: 5
	                });
	            }

	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};
	$.noty.layouts.inline = {
	    name     : 'inline',
	    options  : {},
	    container: {
	        object  : '<ul class="noty_inline_layout_container" />',
	        selector: 'ul.noty_inline_layout_container',
	        style   : function() {
	            $(this).css({
	                width        : '100%',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 9999999
	            });
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none'
	    },
	    addClass : ''
	};
	$.noty.layouts.top = {
	    name     : 'top',
	    options  : {},
	    container: {
	        object  : '<ul id="noty_top_layout_container" />',
	        selector: 'ul#noty_top_layout_container',
	        style   : function() {
	            $(this).css({
	                top          : 0,
	                left         : '5%',
	                position     : 'fixed',
	                width        : '90%',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 9999999
	            });
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none'
	    },
	    addClass : ''
	};
	$.noty.layouts.topCenter = {
	    name     : 'topCenter',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_topCenter_layout_container" />',
	        selector: 'ul#noty_topCenter_layout_container',
	        style   : function() {
	            $(this).css({
	                top          : 20,
	                left         : 0,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            $(this).css({
	                left: ($(window).width() - $(this).outerWidth(false)) / 2 + 'px'
	            });
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};

	$.noty.layouts.topLeft = {
	    name     : 'topLeft',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_topLeft_layout_container" />',
	        selector: 'ul#noty_topLeft_layout_container',
	        style   : function() {
	            $(this).css({
	                top          : 20,
	                left         : 20,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            if(window.innerWidth < 600) {
	                $(this).css({
	                    left: 5
	                });
	            }
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};
	$.noty.layouts.topRight = {
	    name     : 'topRight',
	    options  : { // overrides options

	    },
	    container: {
	        object  : '<ul id="noty_topRight_layout_container" />',
	        selector: 'ul#noty_topRight_layout_container',
	        style   : function() {
	            $(this).css({
	                top          : 20,
	                right        : 20,
	                position     : 'fixed',
	                width        : '310px',
	                height       : 'auto',
	                margin       : 0,
	                padding      : 0,
	                listStyleType: 'none',
	                zIndex       : 10000000
	            });

	            if(window.innerWidth < 600) {
	                $(this).css({
	                    right: 5
	                });
	            }
	        }
	    },
	    parent   : {
	        object  : '<li />',
	        selector: 'li',
	        css     : {}
	    },
	    css      : {
	        display: 'none',
	        width  : '310px'
	    },
	    addClass : ''
	};
	$.noty.themes.bootstrapTheme = {
	    name: 'bootstrapTheme',
	    modal: {
	        css: {
	            position: 'fixed',
	            width: '100%',
	            height: '100%',
	            backgroundColor: '#000',
	            zIndex: 10000,
	            opacity: 0.6,
	            display: 'none',
	            left: 0,
	            top: 0
	        }
	    },
	    style: function() {

	        var containerSelector = this.options.layout.container.selector;
	        $(containerSelector).addClass('list-group');

	        this.$closeButton.append('<span aria-hidden="true">&times;</span><span class="sr-only">Close</span>');
	        this.$closeButton.addClass('close');

	        this.$bar.addClass( "list-group-item" ).css('padding', '0px');

	        switch (this.options.type) {
	            case 'alert': case 'notification':
	                this.$bar.addClass( "list-group-item-info" );
	                break;
	            case 'warning':
	                this.$bar.addClass( "list-group-item-warning" );
	                break;
	            case 'error':
	                this.$bar.addClass( "list-group-item-danger" );
	                break;
	            case 'information':
	                this.$bar.addClass("list-group-item-info");
	                break;
	            case 'success':
	                this.$bar.addClass( "list-group-item-success" );
	                break;
	        }

	        this.$message.css({
	            fontSize: '13px',
	            lineHeight: '16px',
	            textAlign: 'center',
	            padding: '8px 10px 9px',
	            width: 'auto',
	            position: 'relative'
	        });
	    },
	    callback: {
	        onShow: function() {  },
	        onClose: function() {  }
	    }
	};


	$.noty.themes.defaultTheme = {
	    name    : 'defaultTheme',
	    helpers : {
	        borderFix: function() {
	            if(this.options.dismissQueue) {
	                var selector = this.options.layout.container.selector + ' ' + this.options.layout.parent.selector;
	                switch(this.options.layout.name) {
	                    case 'top':
	                        $(selector).css({borderRadius: '0px 0px 0px 0px'});
	                        $(selector).last().css({borderRadius: '0px 0px 5px 5px'});
	                        break;
	                    case 'topCenter':
	                    case 'topLeft':
	                    case 'topRight':
	                    case 'bottomCenter':
	                    case 'bottomLeft':
	                    case 'bottomRight':
	                    case 'center':
	                    case 'centerLeft':
	                    case 'centerRight':
	                    case 'inline':
	                        $(selector).css({borderRadius: '0px 0px 0px 0px'});
	                        $(selector).first().css({'border-top-left-radius': '5px', 'border-top-right-radius': '5px'});
	                        $(selector).last().css({'border-bottom-left-radius': '5px', 'border-bottom-right-radius': '5px'});
	                        break;
	                    case 'bottom':
	                        $(selector).css({borderRadius: '0px 0px 0px 0px'});
	                        $(selector).first().css({borderRadius: '5px 5px 0px 0px'});
	                        break;
	                    default:
	                        break;
	                }
	            }
	        }
	    },
	    modal   : {
	        css: {
	            position       : 'fixed',
	            width          : '100%',
	            height         : '100%',
	            backgroundColor: '#000',
	            zIndex         : 10000,
	            opacity        : 0.6,
	            display        : 'none',
	            left           : 0,
	            top            : 0
	        }
	    },
	    style   : function() {

	        this.$bar.css({
	            overflow  : 'hidden',
	            background: "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAoCAQAAAClM0ndAAAAhklEQVR4AdXO0QrCMBBE0bttkk38/w8WRERpdyjzVOc+HxhIHqJGMQcFFkpYRQotLLSw0IJ5aBdovruMYDA/kT8plF9ZKLFQcgF18hDj1SbQOMlCA4kao0iiXmah7qBWPdxpohsgVZyj7e5I9KcID+EhiDI5gxBYKLBQYKHAQoGFAoEks/YEGHYKB7hFxf0AAAAASUVORK5CYII=') repeat-x scroll left top #fff"
	        });

	        this.$message.css({
	            fontSize  : '13px',
	            lineHeight: '16px',
	            textAlign : 'center',
	            padding   : '8px 10px 9px',
	            width     : 'auto',
	            position  : 'relative'
	        });

	        this.$closeButton.css({
	            position  : 'absolute',
	            top       : 4, right: 4,
	            width     : 10, height: 10,
	            background: "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAxUlEQVR4AR3MPUoDURSA0e++uSkkOxC3IAOWNtaCIDaChfgXBMEZbQRByxCwk+BasgQRZLSYoLgDQbARxry8nyumPcVRKDfd0Aa8AsgDv1zp6pYd5jWOwhvebRTbzNNEw5BSsIpsj/kurQBnmk7sIFcCF5yyZPDRG6trQhujXYosaFoc+2f1MJ89uc76IND6F9BvlXUdpb6xwD2+4q3me3bysiHvtLYrUJto7PD/ve7LNHxSg/woN2kSz4txasBdhyiz3ugPGetTjm3XRokAAAAASUVORK5CYII=)",
	            display   : 'none',
	            cursor    : 'pointer'
	        });

	        this.$buttons.css({
	            padding        : 5,
	            textAlign      : 'right',
	            borderTop      : '1px solid #ccc',
	            backgroundColor: '#fff'
	        });

	        this.$buttons.find('button').css({
	            marginLeft: 5
	        });

	        this.$buttons.find('button:first').css({
	            marginLeft: 0
	        });

	        this.$bar.on({
	            mouseenter: function() {
	                $(this).find('.noty_close').stop().fadeTo('normal', 1);
	            },
	            mouseleave: function() {
	                $(this).find('.noty_close').stop().fadeTo('normal', 0);
	            }
	        });

	        switch(this.options.layout.name) {
	            case 'top':
	                this.$bar.css({
	                    borderRadius: '0px 0px 5px 5px',
	                    borderBottom: '2px solid #eee',
	                    borderLeft  : '2px solid #eee',
	                    borderRight : '2px solid #eee',
	                    boxShadow   : "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                break;
	            case 'topCenter':
	            case 'center':
	            case 'bottomCenter':
	            case 'inline':
	                this.$bar.css({
	                    borderRadius: '5px',
	                    border      : '1px solid #eee',
	                    boxShadow   : "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                this.$message.css({fontSize: '13px', textAlign: 'center'});
	                break;
	            case 'topLeft':
	            case 'topRight':
	            case 'bottomLeft':
	            case 'bottomRight':
	            case 'centerLeft':
	            case 'centerRight':
	                this.$bar.css({
	                    borderRadius: '5px',
	                    border      : '1px solid #eee',
	                    boxShadow   : "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                this.$message.css({fontSize: '13px', textAlign: 'left'});
	                break;
	            case 'bottom':
	                this.$bar.css({
	                    borderRadius: '5px 5px 0px 0px',
	                    borderTop   : '2px solid #eee',
	                    borderLeft  : '2px solid #eee',
	                    borderRight : '2px solid #eee',
	                    boxShadow   : "0 -2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                break;
	            default:
	                this.$bar.css({
	                    border   : '2px solid #eee',
	                    boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                break;
	        }

	        switch(this.options.type) {
	            case 'alert':
	            case 'notification':
	                this.$bar.css({backgroundColor: '#FFF', borderColor: '#CCC', color: '#444'});
	                break;
	            case 'warning':
	                this.$bar.css({backgroundColor: '#FFEAA8', borderColor: '#FFC237', color: '#826200'});
	                this.$buttons.css({borderTop: '1px solid #FFC237'});
	                break;
	            case 'error':
	                this.$bar.css({backgroundColor: 'red', borderColor: 'darkred', color: '#FFF'});
	                this.$message.css({fontWeight: 'bold'});
	                this.$buttons.css({borderTop: '1px solid darkred'});
	                break;
	            case 'information':
	                this.$bar.css({backgroundColor: '#57B7E2', borderColor: '#0B90C4', color: '#FFF'});
	                this.$buttons.css({borderTop: '1px solid #0B90C4'});
	                break;
	            case 'success':
	                this.$bar.css({backgroundColor: 'lightgreen', borderColor: '#50C24E', color: 'darkgreen'});
	                this.$buttons.css({borderTop: '1px solid #50C24E'});
	                break;
	            default:
	                this.$bar.css({backgroundColor: '#FFF', borderColor: '#CCC', color: '#444'});
	                break;
	        }
	    },
	    callback: {
	        onShow : function() {
	            $.noty.themes.defaultTheme.helpers.borderFix.apply(this);
	        },
	        onClose: function() {
	            $.noty.themes.defaultTheme.helpers.borderFix.apply(this);
	        }
	    }
	};

	$.noty.themes.relax = {
	    name    : 'relax',
	    helpers : {},
	    modal   : {
	        css: {
	            position       : 'fixed',
	            width          : '100%',
	            height         : '100%',
	            backgroundColor: '#000',
	            zIndex         : 10000,
	            opacity        : 0.6,
	            display        : 'none',
	            left           : 0,
	            top            : 0
	        }
	    },
	    style   : function() {

	        this.$bar.css({
	            overflow    : 'hidden',
	            margin      : '4px 0',
	            borderRadius: '2px'
	        });

	        this.$message.css({
	            fontSize  : '14px',
	            lineHeight: '16px',
	            textAlign : 'center',
	            padding   : '10px',
	            width     : 'auto',
	            position  : 'relative'
	        });

	        this.$closeButton.css({
	            position  : 'absolute',
	            top       : 4, right: 4,
	            width     : 10, height: 10,
	            background: "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAxUlEQVR4AR3MPUoDURSA0e++uSkkOxC3IAOWNtaCIDaChfgXBMEZbQRByxCwk+BasgQRZLSYoLgDQbARxry8nyumPcVRKDfd0Aa8AsgDv1zp6pYd5jWOwhvebRTbzNNEw5BSsIpsj/kurQBnmk7sIFcCF5yyZPDRG6trQhujXYosaFoc+2f1MJ89uc76IND6F9BvlXUdpb6xwD2+4q3me3bysiHvtLYrUJto7PD/ve7LNHxSg/woN2kSz4txasBdhyiz3ugPGetTjm3XRokAAAAASUVORK5CYII=)",
	            display   : 'none',
	            cursor    : 'pointer'
	        });

	        this.$buttons.css({
	            padding        : 5,
	            textAlign      : 'right',
	            borderTop      : '1px solid #ccc',
	            backgroundColor: '#fff'
	        });

	        this.$buttons.find('button').css({
	            marginLeft: 5
	        });

	        this.$buttons.find('button:first').css({
	            marginLeft: 0
	        });

	        this.$bar.on({
	            mouseenter: function() {
	                $(this).find('.noty_close').stop().fadeTo('normal', 1);
	            },
	            mouseleave: function() {
	                $(this).find('.noty_close').stop().fadeTo('normal', 0);
	            }
	        });

	        switch(this.options.layout.name) {
	            case 'top':
	                this.$bar.css({
	                    borderBottom: '2px solid #eee',
	                    borderLeft  : '2px solid #eee',
	                    borderRight : '2px solid #eee',
	                    borderTop   : '2px solid #eee',
	                    boxShadow   : "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                break;
	            case 'topCenter':
	            case 'center':
	            case 'bottomCenter':
	            case 'inline':
	                this.$bar.css({
	                    border   : '1px solid #eee',
	                    boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                this.$message.css({fontSize: '13px', textAlign: 'center'});
	                break;
	            case 'topLeft':
	            case 'topRight':
	            case 'bottomLeft':
	            case 'bottomRight':
	            case 'centerLeft':
	            case 'centerRight':
	                this.$bar.css({
	                    border   : '1px solid #eee',
	                    boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                this.$message.css({fontSize: '13px', textAlign: 'left'});
	                break;
	            case 'bottom':
	                this.$bar.css({
	                    borderTop   : '2px solid #eee',
	                    borderLeft  : '2px solid #eee',
	                    borderRight : '2px solid #eee',
	                    borderBottom: '2px solid #eee',
	                    boxShadow   : "0 -2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                break;
	            default:
	                this.$bar.css({
	                    border   : '2px solid #eee',
	                    boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)"
	                });
	                break;
	        }

	        switch(this.options.type) {
	            case 'alert':
	            case 'notification':
	                this.$bar.css({backgroundColor: '#FFF', borderColor: '#dedede', color: '#444'});
	                break;
	            case 'warning':
	                this.$bar.css({backgroundColor: '#FFEAA8', borderColor: '#FFC237', color: '#826200'});
	                this.$buttons.css({borderTop: '1px solid #FFC237'});
	                break;
	            case 'error':
	                this.$bar.css({backgroundColor: '#FF8181', borderColor: '#e25353', color: '#FFF'});
	                this.$message.css({fontWeight: 'bold'});
	                this.$buttons.css({borderTop: '1px solid darkred'});
	                break;
	            case 'information':
	                this.$bar.css({backgroundColor: '#78C5E7', borderColor: '#3badd6', color: '#FFF'});
	                this.$buttons.css({borderTop: '1px solid #0B90C4'});
	                break;
	            case 'success':
	                this.$bar.css({backgroundColor: '#BCF5BC', borderColor: '#7cdd77', color: 'darkgreen'});
	                this.$buttons.css({borderTop: '1px solid #50C24E'});
	                break;
	            default:
	                this.$bar.css({backgroundColor: '#FFF', borderColor: '#CCC', color: '#444'});
	                break;
	        }
	    },
	    callback: {
	        onShow : function() {

	        },
	        onClose: function() {

	        }
	    }
	};


	return window.noty;

	});

/***/ },
/* 416 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Overlay = function Overlay(opts) {
	  var _this = this;

	  _classCallCheck(this, Overlay);

	  var defaults = {
	    selector: "data-overlay",
	    trigger: "data-overlay-trigger",
	    openClass: "open",
	    closeSelector: ".close",
	    widthSelector: "data-overlay-width"
	  };

	  this.opts = _lodash2.default.extend(defaults, opts);

	  (0, _jquery2.default)('[' + this.opts.trigger + ']').click(function (_) {
	    if ((0, _jquery2.default)('[' + _this.opts.widthSelector + ']').length == 0 || (0, _jquery2.default)(window).width() <= parseInt((0, _jquery2.default)('[' + _this.opts.widthSelector + ']').attr(_this.opts.widthSelector))) (0, _jquery2.default)('[' + _this.opts.selector + ']').toggleClass('' + _this.opts.openClass);
	  });

	  (0, _jquery2.default)('[' + this.opts.selector + '] ' + this.opts.closeSelector + ', [' + this.opts.selector + ']').click(function (_) {
	    (0, _jquery2.default)('[' + _this.opts.selector + ']').removeClass('' + _this.opts.openClass);
	  });
	};

	exports.default = Overlay;

/***/ },
/* 417 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _noty = __webpack_require__(415);

	var _noty2 = _interopRequireDefault(_noty);

	var _clipboard = __webpack_require__(418);

	var _clipboard2 = _interopRequireDefault(_clipboard);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 *  Initializes a new clipboard from elements with class copy
	 *  @memberof common
	 *  @example
	 *   %input.form-control{type: "text", value: dash_user.repo_url, readonly: ''}
	 *     %span.copy.input-group-addon{:data => {'clipboard-text' => dash_user.repo_url}}
	 *       %span.icon-paste
	 */
	var Copy = function Copy() {
	  _classCallCheck(this, Copy);

	  var clipboard = new _clipboard2.default('.copy');
	  clipboard.on('success', function (e) {
	    (0, _noty2.default)({
	      layout: 'topRight',
	      type: 'success',
	      text: "Copied",
	      timeout: 3000
	    });
	    e.clearSelection();
	  });
	};

	exports.default = Copy;

/***/ },
/* 418 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {
	    if (true) {
	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [module, __webpack_require__(419), __webpack_require__(421), __webpack_require__(422)], __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 if (typeof exports !== "undefined") {
	        factory(module, require('./clipboard-action'), require('tiny-emitter'), require('good-listener'));
	    } else {
	        var mod = {
	            exports: {}
	        };
	        factory(mod, global.clipboardAction, global.tinyEmitter, global.goodListener);
	        global.clipboard = mod.exports;
	    }
	})(this, function (module, _clipboardAction, _tinyEmitter, _goodListener) {
	    'use strict';

	    var _clipboardAction2 = _interopRequireDefault(_clipboardAction);

	    var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);

	    var _goodListener2 = _interopRequireDefault(_goodListener);

	    function _interopRequireDefault(obj) {
	        return obj && obj.__esModule ? obj : {
	            default: obj
	        };
	    }

	    function _classCallCheck(instance, Constructor) {
	        if (!(instance instanceof Constructor)) {
	            throw new TypeError("Cannot call a class as a function");
	        }
	    }

	    var _createClass = 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);
	            }
	        }

	        return function (Constructor, protoProps, staticProps) {
	            if (protoProps) defineProperties(Constructor.prototype, protoProps);
	            if (staticProps) defineProperties(Constructor, staticProps);
	            return Constructor;
	        };
	    }();

	    function _possibleConstructorReturn(self, call) {
	        if (!self) {
	            throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
	        }

	        return call && (typeof call === "object" || typeof call === "function") ? call : self;
	    }

	    function _inherits(subClass, superClass) {
	        if (typeof superClass !== "function" && superClass !== null) {
	            throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
	        }

	        subClass.prototype = Object.create(superClass && superClass.prototype, {
	            constructor: {
	                value: subClass,
	                enumerable: false,
	                writable: true,
	                configurable: true
	            }
	        });
	        if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
	    }

	    var Clipboard = function (_Emitter) {
	        _inherits(Clipboard, _Emitter);

	        /**
	         * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
	         * @param {Object} options
	         */
	        function Clipboard(trigger, options) {
	            _classCallCheck(this, Clipboard);

	            var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));

	            _this.resolveOptions(options);
	            _this.listenClick(trigger);
	            return _this;
	        }

	        /**
	         * Defines if attributes would be resolved using internal setter functions
	         * or custom functions that were passed in the constructor.
	         * @param {Object} options
	         */


	        _createClass(Clipboard, [{
	            key: 'resolveOptions',
	            value: function resolveOptions() {
	                var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

	                this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
	                this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
	                this.text = typeof options.text === 'function' ? options.text : this.defaultText;
	            }
	        }, {
	            key: 'listenClick',
	            value: function listenClick(trigger) {
	                var _this2 = this;

	                this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {
	                    return _this2.onClick(e);
	                });
	            }
	        }, {
	            key: 'onClick',
	            value: function onClick(e) {
	                var trigger = e.delegateTarget || e.currentTarget;

	                if (this.clipboardAction) {
	                    this.clipboardAction = null;
	                }

	                this.clipboardAction = new _clipboardAction2.default({
	                    action: this.action(trigger),
	                    target: this.target(trigger),
	                    text: this.text(trigger),
	                    trigger: trigger,
	                    emitter: this
	                });
	            }
	        }, {
	            key: 'defaultAction',
	            value: function defaultAction(trigger) {
	                return getAttributeValue('action', trigger);
	            }
	        }, {
	            key: 'defaultTarget',
	            value: function defaultTarget(trigger) {
	                var selector = getAttributeValue('target', trigger);

	                if (selector) {
	                    return document.querySelector(selector);
	                }
	            }
	        }, {
	            key: 'defaultText',
	            value: function defaultText(trigger) {
	                return getAttributeValue('text', trigger);
	            }
	        }, {
	            key: 'destroy',
	            value: function destroy() {
	                this.listener.destroy();

	                if (this.clipboardAction) {
	                    this.clipboardAction.destroy();
	                    this.clipboardAction = null;
	                }
	            }
	        }]);

	        return Clipboard;
	    }(_tinyEmitter2.default);

	    /**
	     * Helper function to retrieve attribute value.
	     * @param {String} suffix
	     * @param {Element} element
	     */
	    function getAttributeValue(suffix, element) {
	        var attribute = 'data-clipboard-' + suffix;

	        if (!element.hasAttribute(attribute)) {
	            return;
	        }

	        return element.getAttribute(attribute);
	    }

	    module.exports = Clipboard;
	});

/***/ },
/* 419 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {
	    if (true) {
	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [module, __webpack_require__(420)], __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 if (typeof exports !== "undefined") {
	        factory(module, require('select'));
	    } else {
	        var mod = {
	            exports: {}
	        };
	        factory(mod, global.select);
	        global.clipboardAction = mod.exports;
	    }
	})(this, function (module, _select) {
	    'use strict';

	    var _select2 = _interopRequireDefault(_select);

	    function _interopRequireDefault(obj) {
	        return obj && obj.__esModule ? obj : {
	            default: obj
	        };
	    }

	    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
	        return typeof obj;
	    } : function (obj) {
	        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
	    };

	    function _classCallCheck(instance, Constructor) {
	        if (!(instance instanceof Constructor)) {
	            throw new TypeError("Cannot call a class as a function");
	        }
	    }

	    var _createClass = 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);
	            }
	        }

	        return function (Constructor, protoProps, staticProps) {
	            if (protoProps) defineProperties(Constructor.prototype, protoProps);
	            if (staticProps) defineProperties(Constructor, staticProps);
	            return Constructor;
	        };
	    }();

	    var ClipboardAction = function () {
	        /**
	         * @param {Object} options
	         */
	        function ClipboardAction(options) {
	            _classCallCheck(this, ClipboardAction);

	            this.resolveOptions(options);
	            this.initSelection();
	        }

	        /**
	         * Defines base properties passed from constructor.
	         * @param {Object} options
	         */


	        _createClass(ClipboardAction, [{
	            key: 'resolveOptions',
	            value: function resolveOptions() {
	                var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

	                this.action = options.action;
	                this.emitter = options.emitter;
	                this.target = options.target;
	                this.text = options.text;
	                this.trigger = options.trigger;

	                this.selectedText = '';
	            }
	        }, {
	            key: 'initSelection',
	            value: function initSelection() {
	                if (this.text) {
	                    this.selectFake();
	                } else if (this.target) {
	                    this.selectTarget();
	                }
	            }
	        }, {
	            key: 'selectFake',
	            value: function selectFake() {
	                var _this = this;

	                var isRTL = document.documentElement.getAttribute('dir') == 'rtl';

	                this.removeFake();

	                this.fakeHandlerCallback = function () {
	                    return _this.removeFake();
	                };
	                this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true;

	                this.fakeElem = document.createElement('textarea');
	                // Prevent zooming on iOS
	                this.fakeElem.style.fontSize = '12pt';
	                // Reset box model
	                this.fakeElem.style.border = '0';
	                this.fakeElem.style.padding = '0';
	                this.fakeElem.style.margin = '0';
	                // Move element out of screen horizontally
	                this.fakeElem.style.position = 'absolute';
	                this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
	                // Move element to the same position vertically
	                var yPosition = window.pageYOffset || document.documentElement.scrollTop;
	                this.fakeElem.addEventListener('focus', window.scrollTo(0, yPosition));
	                this.fakeElem.style.top = yPosition + 'px';

	                this.fakeElem.setAttribute('readonly', '');
	                this.fakeElem.value = this.text;

	                document.body.appendChild(this.fakeElem);

	                this.selectedText = (0, _select2.default)(this.fakeElem);
	                this.copyText();
	            }
	        }, {
	            key: 'removeFake',
	            value: function removeFake() {
	                if (this.fakeHandler) {
	                    document.body.removeEventListener('click', this.fakeHandlerCallback);
	                    this.fakeHandler = null;
	                    this.fakeHandlerCallback = null;
	                }

	                if (this.fakeElem) {
	                    document.body.removeChild(this.fakeElem);
	                    this.fakeElem = null;
	                }
	            }
	        }, {
	            key: 'selectTarget',
	            value: function selectTarget() {
	                this.selectedText = (0, _select2.default)(this.target);
	                this.copyText();
	            }
	        }, {
	            key: 'copyText',
	            value: function copyText() {
	                var succeeded = void 0;

	                try {
	                    succeeded = document.execCommand(this.action);
	                } catch (err) {
	                    succeeded = false;
	                }

	                this.handleResult(succeeded);
	            }
	        }, {
	            key: 'handleResult',
	            value: function handleResult(succeeded) {
	                this.emitter.emit(succeeded ? 'success' : 'error', {
	                    action: this.action,
	                    text: this.selectedText,
	                    trigger: this.trigger,
	                    clearSelection: this.clearSelection.bind(this)
	                });
	            }
	        }, {
	            key: 'clearSelection',
	            value: function clearSelection() {
	                if (this.target) {
	                    this.target.blur();
	                }

	                window.getSelection().removeAllRanges();
	            }
	        }, {
	            key: 'destroy',
	            value: function destroy() {
	                this.removeFake();
	            }
	        }, {
	            key: 'action',
	            set: function set() {
	                var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';

	                this._action = action;

	                if (this._action !== 'copy' && this._action !== 'cut') {
	                    throw new Error('Invalid "action" value, use either "copy" or "cut"');
	                }
	            },
	            get: function get() {
	                return this._action;
	            }
	        }, {
	            key: 'target',
	            set: function set(target) {
	                if (target !== undefined) {
	                    if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {
	                        if (this.action === 'copy' && target.hasAttribute('disabled')) {
	                            throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
	                        }

	                        if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
	                            throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
	                        }

	                        this._target = target;
	                    } else {
	                        throw new Error('Invalid "target" value, use a valid Element');
	                    }
	                }
	            },
	            get: function get() {
	                return this._target;
	            }
	        }]);

	        return ClipboardAction;
	    }();

	    module.exports = ClipboardAction;
	});

/***/ },
/* 420 */
/***/ function(module, exports) {

	function select(element) {
	    var selectedText;

	    if (element.nodeName === 'SELECT') {
	        element.focus();

	        selectedText = element.value;
	    }
	    else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
	        var isReadOnly = element.hasAttribute('readonly');

	        if (!isReadOnly) {
	            element.setAttribute('readonly', '');
	        }

	        element.select();
	        element.setSelectionRange(0, element.value.length);

	        if (!isReadOnly) {
	            element.removeAttribute('readonly');
	        }

	        selectedText = element.value;
	    }
	    else {
	        if (element.hasAttribute('contenteditable')) {
	            element.focus();
	        }

	        var selection = window.getSelection();
	        var range = document.createRange();

	        range.selectNodeContents(element);
	        selection.removeAllRanges();
	        selection.addRange(range);

	        selectedText = selection.toString();
	    }

	    return selectedText;
	}

	module.exports = select;


/***/ },
/* 421 */
/***/ function(module, exports) {

	function E () {
	  // Keep this empty so it's easier to inherit from
	  // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
	}

	E.prototype = {
	  on: function (name, callback, ctx) {
	    var e = this.e || (this.e = {});

	    (e[name] || (e[name] = [])).push({
	      fn: callback,
	      ctx: ctx
	    });

	    return this;
	  },

	  once: function (name, callback, ctx) {
	    var self = this;
	    function listener () {
	      self.off(name, listener);
	      callback.apply(ctx, arguments);
	    };

	    listener._ = callback
	    return this.on(name, listener, ctx);
	  },

	  emit: function (name) {
	    var data = [].slice.call(arguments, 1);
	    var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
	    var i = 0;
	    var len = evtArr.length;

	    for (i; i < len; i++) {
	      evtArr[i].fn.apply(evtArr[i].ctx, data);
	    }

	    return this;
	  },

	  off: function (name, callback) {
	    var e = this.e || (this.e = {});
	    var evts = e[name];
	    var liveEvents = [];

	    if (evts && callback) {
	      for (var i = 0, len = evts.length; i < len; i++) {
	        if (evts[i].fn !== callback && evts[i].fn._ !== callback)
	          liveEvents.push(evts[i]);
	      }
	    }

	    // Remove event from queue to prevent memory leak
	    // Suggested by https://github.com/lazd
	    // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910

	    (liveEvents.length)
	      ? e[name] = liveEvents
	      : delete e[name];

	    return this;
	  }
	};

	module.exports = E;


/***/ },
/* 422 */
/***/ function(module, exports, __webpack_require__) {

	var is = __webpack_require__(423);
	var delegate = __webpack_require__(424);

	/**
	 * Validates all params and calls the right
	 * listener function based on its target type.
	 *
	 * @param {String|HTMLElement|HTMLCollection|NodeList} target
	 * @param {String} type
	 * @param {Function} callback
	 * @return {Object}
	 */
	function listen(target, type, callback) {
	    if (!target && !type && !callback) {
	        throw new Error('Missing required arguments');
	    }

	    if (!is.string(type)) {
	        throw new TypeError('Second argument must be a String');
	    }

	    if (!is.fn(callback)) {
	        throw new TypeError('Third argument must be a Function');
	    }

	    if (is.node(target)) {
	        return listenNode(target, type, callback);
	    }
	    else if (is.nodeList(target)) {
	        return listenNodeList(target, type, callback);
	    }
	    else if (is.string(target)) {
	        return listenSelector(target, type, callback);
	    }
	    else {
	        throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
	    }
	}

	/**
	 * Adds an event listener to a HTML element
	 * and returns a remove listener function.
	 *
	 * @param {HTMLElement} node
	 * @param {String} type
	 * @param {Function} callback
	 * @return {Object}
	 */
	function listenNode(node, type, callback) {
	    node.addEventListener(type, callback);

	    return {
	        destroy: function() {
	            node.removeEventListener(type, callback);
	        }
	    }
	}

	/**
	 * Add an event listener to a list of HTML elements
	 * and returns a remove listener function.
	 *
	 * @param {NodeList|HTMLCollection} nodeList
	 * @param {String} type
	 * @param {Function} callback
	 * @return {Object}
	 */
	function listenNodeList(nodeList, type, callback) {
	    Array.prototype.forEach.call(nodeList, function(node) {
	        node.addEventListener(type, callback);
	    });

	    return {
	        destroy: function() {
	            Array.prototype.forEach.call(nodeList, function(node) {
	                node.removeEventListener(type, callback);
	            });
	        }
	    }
	}

	/**
	 * Add an event listener to a selector
	 * and returns a remove listener function.
	 *
	 * @param {String} selector
	 * @param {String} type
	 * @param {Function} callback
	 * @return {Object}
	 */
	function listenSelector(selector, type, callback) {
	    return delegate(document.body, selector, type, callback);
	}

	module.exports = listen;


/***/ },
/* 423 */
/***/ function(module, exports) {

	/**
	 * Check if argument is a HTML element.
	 *
	 * @param {Object} value
	 * @return {Boolean}
	 */
	exports.node = function(value) {
	    return value !== undefined
	        && value instanceof HTMLElement
	        && value.nodeType === 1;
	};

	/**
	 * Check if argument is a list of HTML elements.
	 *
	 * @param {Object} value
	 * @return {Boolean}
	 */
	exports.nodeList = function(value) {
	    var type = Object.prototype.toString.call(value);

	    return value !== undefined
	        && (type === '[object NodeList]' || type === '[object HTMLCollection]')
	        && ('length' in value)
	        && (value.length === 0 || exports.node(value[0]));
	};

	/**
	 * Check if argument is a string.
	 *
	 * @param {Object} value
	 * @return {Boolean}
	 */
	exports.string = function(value) {
	    return typeof value === 'string'
	        || value instanceof String;
	};

	/**
	 * Check if argument is a function.
	 *
	 * @param {Object} value
	 * @return {Boolean}
	 */
	exports.fn = function(value) {
	    var type = Object.prototype.toString.call(value);

	    return type === '[object Function]';
	};


/***/ },
/* 424 */
/***/ function(module, exports, __webpack_require__) {

	var closest = __webpack_require__(425);

	/**
	 * Delegates event to a selector.
	 *
	 * @param {Element} element
	 * @param {String} selector
	 * @param {String} type
	 * @param {Function} callback
	 * @param {Boolean} useCapture
	 * @return {Object}
	 */
	function _delegate(element, selector, type, callback, useCapture) {
	    var listenerFn = listener.apply(this, arguments);

	    element.addEventListener(type, listenerFn, useCapture);

	    return {
	        destroy: function() {
	            element.removeEventListener(type, listenerFn, useCapture);
	        }
	    }
	}

	/**
	 * Delegates event to a selector.
	 *
	 * @param {Element|String|Array} [elements]
	 * @param {String} selector
	 * @param {String} type
	 * @param {Function} callback
	 * @param {Boolean} useCapture
	 * @return {Object}
	 */
	function delegate(elements, selector, type, callback, useCapture) {
	    // Handle the regular Element usage
	    if (typeof elements.addEventListener === 'function') {
	        return _delegate.apply(null, arguments);
	    }

	    // Handle Element-less usage, it defaults to global delegation
	    if (typeof type === 'function') {
	        // Use `document` as the first parameter, then apply arguments
	        // This is a short way to .unshift `arguments` without running into deoptimizations
	        return _delegate.bind(null, document).apply(null, arguments);
	    }

	    // Handle Selector-based usage
	    if (typeof elements === 'string') {
	        elements = document.querySelectorAll(elements);
	    }

	    // Handle Array-like based usage
	    return Array.prototype.map.call(elements, function (element) {
	        return _delegate(element, selector, type, callback, useCapture);
	    });
	}

	/**
	 * Finds closest match and invokes callback.
	 *
	 * @param {Element} element
	 * @param {String} selector
	 * @param {String} type
	 * @param {Function} callback
	 * @return {Function}
	 */
	function listener(element, selector, type, callback) {
	    return function(e) {
	        e.delegateTarget = closest(e.target, selector);

	        if (e.delegateTarget) {
	            callback.call(element, e);
	        }
	    }
	}

	module.exports = delegate;


/***/ },
/* 425 */
/***/ function(module, exports) {

	var DOCUMENT_NODE_TYPE = 9;

	/**
	 * A polyfill for Element.matches()
	 */
	if (typeof Element !== 'undefined' && !Element.prototype.matches) {
	    var proto = Element.prototype;

	    proto.matches = proto.matchesSelector ||
	                    proto.mozMatchesSelector ||
	                    proto.msMatchesSelector ||
	                    proto.oMatchesSelector ||
	                    proto.webkitMatchesSelector;
	}

	/**
	 * Finds the closest parent that matches a selector.
	 *
	 * @param {Element} element
	 * @param {String} selector
	 * @return {Function}
	 */
	function closest (element, selector) {
	    while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {
	        if (typeof element.matches === 'function' &&
	            element.matches(selector)) {
	          return element;
	        }
	        element = element.parentNode;
	    }
	}

	module.exports = closest;


/***/ },
/* 426 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 * A check all checkbox helper, for a checkbox having 'data-check-all'='toto'
	 * toggles all checkboxes having name=toto when it is clicked
	 * @memberof common
	 * @example
	 *  %input{type: 'checkbox', data: {check_all: "cursus_subscription[cursus_subscriptions_users][]"}}
	 */
	var CheckAll = function CheckAll() {
	  _classCallCheck(this, CheckAll);

	  $('[data-check-all]').each(function () {
	    $(this).click(function () {
	      var name = $(this).data('checkAll');
	      var checkboxes = document.getElementsByName(name);
	      for (var i = 0, n = checkboxes.length; i < n; i++) {
	        checkboxes[i].checked = this.checked;
	      }
	    });
	  });
	};

	exports.default = CheckAll;

/***/ },
/* 427 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 * Replaces the text of button when the parent form successfully performs an ajax request
	 * @memberof common
	 * @example
	 * = f.submit, 'save', data: {'disable-with': 'saving...', 'replace-with': 'saved'}
	 */
	var ReplaceWith = function ReplaceWith() {
	  _classCallCheck(this, ReplaceWith);

	  $('[data-replace-with]').each(function () {
	    $(this).parents('form').bind('ajax:complete', function (e, r, s) {
	      if (r.status == 200) {
	        $(this).find('[data-replace-with]').each(function () {
	          var btn = $(this);
	          var replacementText = $(this).data('replaceWith');
	          setTimeout(function () {
	            if (btn.val && btn.val !== "") {
	              btn.val(replacementText);
	            }
	            if (btn.html && btn.html !== "") {
	              btn.html(replacementText);
	            }
	          }, 15);
	        });
	      }
	    });
	  });
	};

	exports.default = ReplaceWith;

/***/ },
/* 428 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _emojify = __webpack_require__(429);

	var _emojify2 = _interopRequireDefault(_emojify);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Emojis = function Emojis() {
	  _classCallCheck(this, Emojis);

	  _emojify2.default.setConfig({
	    emojify_tag_type: 'span',
	    only_crawl_id: null,
	    img_dir: '/images/emoji',
	    ignored_tags: {
	      'H1': 1,
	      'SCRIPT': 1,
	      'TEXTAREA': 1,
	      'A': 1,
	      'PRE': 1,
	      'CODE': 1
	    }
	  });
	  Emojis.refresh();
	};

	Emojis.refresh = function () {
	  var _arr = ["messages", "changelogs"];

	  for (var _i = 0; _i < _arr.length; _i++) {
	    var tag = _arr[_i];
	    var elt = document.getElementsByClassName(tag + '-list')[0];
	    if (_emojify2.default && elt) _emojify2.default.run(elt);
	  }
	};

	exports.default = Emojis;

/***/ },
/* 429 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (root, factory) {
	    'use strict';

	    if (true) {
	        // AMD. Register as an anonymous module.
	        !(__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 if (typeof exports === 'object') {
	        // Node. Does not work with strict CommonJS, but
	        // only CommonJS-like environments that support module.exports,
	        // like Node.
	        module.exports = factory();
	    } else {
	        // Browser globals (root is window)
	        root.emojify = factory();
	    }
	}(this, function () {
	        'use strict';

	        var emojify = (function () {
	            /**
	             * NB!
	             * The namedEmojiString variable is updated automatically by the
	             * "update" gulp task. Do not remove the comment as this will
	             * cause the gulp task to stop working.
	             */
	            var namedEmojiString =
	            /*##EMOJILIST*/"+1,-1,100,1234,8ball,a,ab,abc,abcd,accept,aerial_tramway,airplane,alarm_clock,alien,ambulance,anchor,angel,anger,angry,anguished,ant,apple,aquarius,aries,arrow_backward,arrow_double_down,arrow_double_up,arrow_down,arrow_down_small,arrow_forward,arrow_heading_down,arrow_heading_up,arrow_left,arrow_lower_left,arrow_lower_right,arrow_right,arrow_right_hook,arrow_up,arrow_up_down,arrow_up_small,arrow_upper_left,arrow_upper_right,arrows_clockwise,arrows_counterclockwise,art,articulated_lorry,astonished,atm,b,baby,baby_bottle,baby_chick,baby_symbol,back,baggage_claim,balloon,ballot_box_with_check,bamboo,banana,bangbang,bank,bar_chart,barber,baseball,basketball,bath,bathtub,battery,bear,bee,beer,beers,beetle,beginner,bell,bento,bicyclist,bike,bikini,bird,birthday,black_circle,black_joker,black_medium_small_square,black_medium_square,black_nib,black_small_square,black_square,black_square_button,blossom,blowfish,blue_book,blue_car,blue_heart,blush,boar,boat,bomb,book,bookmark,bookmark_tabs,books,boom,boot,bouquet,bow,bowling,bowtie,boy,bread,bride_with_veil,bridge_at_night,briefcase,broken_heart,bug,bulb,bullettrain_front,bullettrain_side,bus,busstop,bust_in_silhouette,busts_in_silhouette,cactus,cake,calendar,calling,camel,camera,cancer,candy,capital_abcd,capricorn,car,card_index,carousel_horse,cat,cat2,cd,chart,chart_with_downwards_trend,chart_with_upwards_trend,checkered_flag,cherries,cherry_blossom,chestnut,chicken,children_crossing,chocolate_bar,christmas_tree,church,cinema,circus_tent,city_sunrise,city_sunset,cl,clap,clapper,clipboard,clock1,clock10,clock1030,clock11,clock1130,clock12,clock1230,clock130,clock2,clock230,clock3,clock330,clock4,clock430,clock5,clock530,clock6,clock630,clock7,clock730,clock8,clock830,clock9,clock930,closed_book,closed_lock_with_key,closed_umbrella,cloud,clubs,cn,cocktail,coffee,cold_sweat,collision,computer,confetti_ball,confounded,confused,congratulations,construction,construction_worker,convenience_store,cookie,cool,cop,copyright,corn,couple,couple_with_heart,couplekiss,cow,cow2,credit_card,crescent_moon,crocodile,crossed_flags,crown,cry,crying_cat_face,crystal_ball,cupid,curly_loop,currency_exchange,curry,custard,customs,cyclone,dancer,dancers,dango,dart,dash,date,de,deciduous_tree,department_store,diamond_shape_with_a_dot_inside,diamonds,disappointed,disappointed_relieved,dizzy,dizzy_face,do_not_litter,dog,dog2,dollar,dolls,dolphin,donut,door,doughnut,dragon,dragon_face,dress,dromedary_camel,droplet,dvd,e-mail,ear,ear_of_rice,earth_africa,earth_americas,earth_asia,egg,eggplant,eight,eight_pointed_black_star,eight_spoked_asterisk,electric_plug,elephant,email,end,envelope,es,euro,european_castle,european_post_office,evergreen_tree,exclamation,expressionless,eyeglasses,eyes,facepunch,factory,fallen_leaf,family,fast_forward,fax,fearful,feelsgood,feet,ferris_wheel,file_folder,finnadie,fire,fire_engine,fireworks,first_quarter_moon,first_quarter_moon_with_face,fish,fish_cake,fishing_pole_and_fish,fist,five,flags,flashlight,floppy_disk,flower_playing_cards,flushed,foggy,football,fork_and_knife,fountain,four,four_leaf_clover,fr,free,fried_shrimp,fries,frog,frowning,fu,fuelpump,full_moon,full_moon_with_face,game_die,gb,gem,gemini,ghost,gift,gift_heart,girl,globe_with_meridians,goat,goberserk,godmode,golf,grapes,green_apple,green_book,green_heart,grey_exclamation,grey_question,grimacing,grin,grinning,guardsman,guitar,gun,haircut,hamburger,hammer,hamster,hand,handbag,hankey,hash,hatched_chick,hatching_chick,headphones,hear_no_evil,heart,heart_decoration,heart_eyes,heart_eyes_cat,heartbeat,heartpulse,hearts,heavy_check_mark,heavy_division_sign,heavy_dollar_sign,heavy_exclamation_mark,heavy_minus_sign,heavy_multiplication_x,heavy_plus_sign,helicopter,herb,hibiscus,high_brightness,high_heel,hocho,honey_pot,honeybee,horse,horse_racing,hospital,hotel,hotsprings,hourglass,hourglass_flowing_sand,house,house_with_garden,hurtrealbad,hushed,ice_cream,icecream,id,ideograph_advantage,imp,inbox_tray,incoming_envelope,information_desk_person,information_source,innocent,interrobang,iphone,it,izakaya_lantern,jack_o_lantern,japan,japanese_castle,japanese_goblin,japanese_ogre,jeans,joy,joy_cat,jp,key,keycap_ten,kimono,kiss,kissing,kissing_cat,kissing_closed_eyes,kissing_face,kissing_heart,kissing_smiling_eyes,koala,koko,kr,large_blue_circle,large_blue_diamond,large_orange_diamond,last_quarter_moon,last_quarter_moon_with_face,laughing,leaves,ledger,left_luggage,left_right_arrow,leftwards_arrow_with_hook,lemon,leo,leopard,libra,light_rail,link,lips,lipstick,lock,lock_with_ink_pen,lollipop,loop,loudspeaker,love_hotel,love_letter,low_brightness,m,mag,mag_right,mahjong,mailbox,mailbox_closed,mailbox_with_mail,mailbox_with_no_mail,man,man_with_gua_pi_mao,man_with_turban,mans_shoe,maple_leaf,mask,massage,meat_on_bone,mega,melon,memo,mens,metal,metro,microphone,microscope,milky_way,minibus,minidisc,mobile_phone_off,money_with_wings,moneybag,monkey,monkey_face,monorail,mortar_board,mount_fuji,mountain_bicyclist,mountain_cableway,mountain_railway,mouse,mouse2,movie_camera,moyai,muscle,mushroom,musical_keyboard,musical_note,musical_score,mute,nail_care,name_badge,neckbeard,necktie,negative_squared_cross_mark,neutral_face,new,new_moon,new_moon_with_face,newspaper,ng,nine,no_bell,no_bicycles,no_entry,no_entry_sign,no_good,no_mobile_phones,no_mouth,no_pedestrians,no_smoking,non-potable_water,nose,notebook,notebook_with_decorative_cover,notes,nut_and_bolt,o,o2,ocean,octocat,octopus,oden,office,ok,ok_hand,ok_woman,older_man,older_woman,on,oncoming_automobile,oncoming_bus,oncoming_police_car,oncoming_taxi,one,open_file_folder,open_hands,open_mouth,ophiuchus,orange_book,outbox_tray,ox,package,page_facing_up,page_with_curl,pager,palm_tree,panda_face,paperclip,parking,part_alternation_mark,partly_sunny,passport_control,paw_prints,peach,pear,pencil,pencil2,penguin,pensive,performing_arts,persevere,person_frowning,person_with_blond_hair,person_with_pouting_face,phone,pig,pig2,pig_nose,pill,pineapple,pisces,pizza,plus1,point_down,point_left,point_right,point_up,point_up_2,police_car,poodle,poop,post_office,postal_horn,postbox,potable_water,pouch,poultry_leg,pound,pouting_cat,pray,princess,punch,purple_heart,purse,pushpin,put_litter_in_its_place,question,rabbit,rabbit2,racehorse,radio,radio_button,rage,rage1,rage2,rage3,rage4,railway_car,rainbow,raised_hand,raised_hands,raising_hand,ram,ramen,rat,recycle,red_car,red_circle,registered,relaxed,relieved,repeat,repeat_one,restroom,revolving_hearts,rewind,ribbon,rice,rice_ball,rice_cracker,rice_scene,ring,rocket,roller_coaster,rooster,rose,rotating_light,round_pushpin,rowboat,ru,rugby_football,runner,running,running_shirt_with_sash,sa,sagittarius,sailboat,sake,sandal,santa,satellite,satisfied,saxophone,school,school_satchel,scissors,scorpius,scream,scream_cat,scroll,seat,secret,see_no_evil,seedling,seven,shaved_ice,sheep,shell,ship,shipit,shirt,shit,shoe,shower,signal_strength,six,six_pointed_star,ski,skull,sleeping,sleepy,slot_machine,small_blue_diamond,small_orange_diamond,small_red_triangle,small_red_triangle_down,smile,smile_cat,smiley,smiley_cat,smiling_imp,smirk,smirk_cat,smoking,snail,snake,snowboarder,snowflake,snowman,sob,soccer,soon,sos,sound,space_invader,spades,spaghetti,sparkle,sparkler,sparkles,sparkling_heart,speak_no_evil,speaker,speech_balloon,speedboat,squirrel,star,star2,stars,station,statue_of_liberty,steam_locomotive,stew,straight_ruler,strawberry,stuck_out_tongue,stuck_out_tongue_closed_eyes,stuck_out_tongue_winking_eye,sun_with_face,sunflower,sunglasses,sunny,sunrise,sunrise_over_mountains,surfer,sushi,suspect,suspension_railway,sweat,sweat_drops,sweat_smile,sweet_potato,swimmer,symbols,syringe,tada,tanabata_tree,tangerine,taurus,taxi,tea,telephone,telephone_receiver,telescope,tennis,tent,thought_balloon,three,thumbsdown,thumbsup,ticket,tiger,tiger2,tired_face,tm,toilet,tokyo_tower,tomato,tongue,top,tophat,tractor,traffic_light,train,train2,tram,triangular_flag_on_post,triangular_ruler,trident,triumph,trolleybus,trollface,trophy,tropical_drink,tropical_fish,truck,trumpet,tshirt,tulip,turtle,tv,twisted_rightwards_arrows,two,two_hearts,two_men_holding_hands,two_women_holding_hands,u5272,u5408,u55b6,u6307,u6708,u6709,u6e80,u7121,u7533,u7981,u7a7a,uk,umbrella,unamused,underage,unlock,up,us,v,vertical_traffic_light,vhs,vibration_mode,video_camera,video_game,violin,virgo,volcano,vs,walking,waning_crescent_moon,waning_gibbous_moon,warning,watch,water_buffalo,watermelon,wave,wavy_dash,waxing_crescent_moon,waxing_gibbous_moon,wc,weary,wedding,whale,whale2,wheelchair,white_check_mark,white_circle,white_flower,white_large_square,white_medium_small_square,white_medium_square,white_small_square,white_square_button,wind_chime,wine_glass,wink,wolf,woman,womans_clothes,womans_hat,womens,worried,wrench,x,yellow_heart,yen,yum,zap,zero,zzz";

	            var namedEmoji = namedEmojiString.split(/,/);

	            /* A hash with the named emoji as keys */
	            var namedMatchHash = namedEmoji.reduce(function(memo, v) {
	                memo[v] = true;
	                return memo;
	            }, {});

	            var emoticonsProcessed;
	            var emojiMegaRe;

	            function initEmoticonsProcessed() {
	                /* List of emoticons used in the regular expression */
	                var emoticons = {
	         /* :..: */ named: /:([a-z0-9A-Z_-]+):/,
	         /* :-)  */ smile: /:-?\)/g,
	         /* :o   */ open_mouth: /:o/gi,
	         /* :-o  */ scream: /:-o/gi,
	         /* :-]  */ smirk: /[:;]-?]/g,
	         /* :-D  */ grinning: /[:;]-?d/gi,
	         /* X-D  */ stuck_out_tongue_closed_eyes: /x-d/gi,
	         /* ;-p  */ stuck_out_tongue_winking_eye: /[:;]-?p/gi,
	   /* :-[ / :-@  */ rage: /:-?[\[@]/g,
	         /* :-(  */ frowning: /:-?\(/g,
	         /* :'-( */ sob: /:['’]-?\(|:&#x27;\(/g,
	         /* :-*  */ kissing_heart: /:-?\*/g,
	         /* ;-)  */ wink: /;-?\)/g,
	         /* :-/  */ pensive: /:-?\//g,
	         /* :-s  */ confounded: /:-?s/gi,
	         /* :-|  */ flushed: /:-?\|/g,
	         /* :-$  */ relaxed: /:-?\$/g,
	         /* :-x  */ mask: /:-x/gi,
	         /* <3   */ heart: /<3|&lt;3/g,
	         /* </3  */ broken_heart: /<\/3|&lt;&#x2F;3/g,
	         /* :+1: */ thumbsup: /:\+1:/g,
	         /* :-1: */ thumbsdown: /:\-1:/g
	                };

	                if (defaultConfig.ignore_emoticons) {
	                    emoticons = {
	             /* :..: */ named: /:([a-z0-9A-Z_-]+):/,
	             /* :+1: */ thumbsup: /:\+1:/g,
	             /* :-1: */ thumbsdown: /:\-1:/g
	                    };
	                }

	                return Object.keys(emoticons).map(function(key) {
	                    return [emoticons[key], key];
	                });
	            }

	            function initMegaRe() {
	                /* The source for our mega-regex */
	                var mega = emoticonsProcessed
	                        .map(function(v) {
	                            var re = v[0];
	                            var val = re.source || re;
	                            val = val.replace(/(^|[^\[])\^/g, '$1');
	                            return "(" + val + ")";
	                        })
	                        .join('|');

	                /* The regex used to find emoji */
	                return new RegExp(mega, "gi");
	            }

	            var defaultConfig = {
	                blacklist: {
	                    'ids': [],
	                    'classes': ['no-emojify'],
	                    'elements': ['script', 'textarea', 'a', 'pre', 'code']
	                },
	                tag_type: null,
	                only_crawl_id: null,
	                img_dir: 'images/emoji',
	                ignore_emoticons: false,
	                mode: 'img'
	            };

	            /* Returns true if the given char is whitespace */
	            function isWhitespace(s) {
	                return s === ' ' || s === '\t' || s === '\r' || s === '\n' || s === '' || s === String.fromCharCode(160);
	            }

	            var modeToElementTagType = {
	                'img': 'img',
	                'sprite': 'span',
	                'data-uri': 'span'
	            };

	            /* Given a match in a node, replace the text with an image */
	            function insertEmojicon(args) {
	                var emojiElement = null;


	                if(args.replacer){
	                    emojiElement = args.replacer.apply({
	                            config: defaultConfig
	                        },
	                        [':' + args.emojiName + ':', args.emojiName]
	                    );
	                }
	                else {
	                    var elementType = defaultConfig.tag_type || modeToElementTagType[defaultConfig.mode];
	                    emojiElement = args.win.document.createElement(elementType);

	                    if (elementType !== 'img') {
	                        emojiElement.setAttribute('class', 'emoji emoji-' + args.emojiName);
	                    } else {
	                        emojiElement.setAttribute('align', 'absmiddle');
	                        emojiElement.setAttribute('alt', ':' + args.emojiName + ':');
	                        emojiElement.setAttribute('class', 'emoji');
	                        emojiElement.setAttribute('src', defaultConfig.img_dir + '/' + args.emojiName + '.png');
	                    }

	                    emojiElement.setAttribute('title', ':' + args.emojiName + ':');
	                }

	                args.node.splitText(args.match.index);
	                args.node.nextSibling.nodeValue = args.node.nextSibling.nodeValue.substr(
	                    args.match[0].length,
	                    args.node.nextSibling.nodeValue.length
	                );
	                emojiElement.appendChild(args.node.splitText(args.match.index));
	                args.node.parentNode.insertBefore(emojiElement, args.node.nextSibling);
	            }

	            /* Given an regex match, return the name of the matching emoji */
	            function getEmojiNameForMatch(match) {
	                /* Special case for named emoji */
	                if(match[1] && match[2]) {
	                    var named = match[2];
	                    if(namedMatchHash[named]) { return named; }
	                    return;
	                }
	                for(var i = 3; i < match.length - 1; i++) {
	                    if(match[i]) {
	                        return emoticonsProcessed[i - 2][1];
	                    }
	                }
	            }

	            function defaultReplacer(emoji, name) {
	                /*jshint validthis: true */
	                var elementType = this.config.tag_type || modeToElementTagType[this.config.mode];
	                if (elementType !== 'img') {
	                    return "<" +  elementType +" class='emoji emoji-" + name + "' title=':" + name + ":'></" + elementType+ ">";
	                } else {
	                    return "<img align='absmiddle' alt=':" + name + ":' class='emoji' src='" + this.config.img_dir + '/' + name + ".png' title=':" + name + ":' />";
	                }
	            }

	            function Validator() {
	                this.lastEmojiTerminatedAt = -1;
	            }

	            Validator.prototype = {
	                validate: function(match, index, input) {
	                    var self = this;

	                    /* Validator */
	                    var emojiName = getEmojiNameForMatch(match);
	                    if(!emojiName) { return; }

	                    var m = match[0];
	                    var length = m.length;
	                    // var index = match.index;
	                    // var input = match.input;

	                    function success() {
	                        self.lastEmojiTerminatedAt = length + index;
	                        return emojiName;
	                    }

	                    /* At the beginning? */
	                    if(index === 0) { return success(); }

	                    /* At the end? */
	                    if(input.length === m.length + index) { return success(); }

	                    var hasEmojiBefore = this.lastEmojiTerminatedAt === index;
	                    if (hasEmojiBefore) { return success();}

	                    /* Has a whitespace before? */
	                    if(isWhitespace(input.charAt(index - 1))) { return success(); }

	                    var hasWhitespaceAfter = isWhitespace(input.charAt(m.length + index));
	                    /* Has a whitespace after? */
	                    if(hasWhitespaceAfter && hasEmojiBefore) { return success(); }

	                    return;
	                }
	            };

	            function emojifyString (htmlString, replacer) {
	                if(!htmlString) { return htmlString; }
	                if(!replacer) { replacer = defaultReplacer; }

	                emoticonsProcessed = initEmoticonsProcessed();
	                emojiMegaRe = initMegaRe();

	                var validator = new Validator();

	                return htmlString.replace(emojiMegaRe, function() {
	                    var matches = Array.prototype.slice.call(arguments, 0, -2);
	                    var index = arguments[arguments.length - 2];
	                    var input = arguments[arguments.length - 1];
	                    var emojiName = validator.validate(matches, index, input);
	                    if(emojiName) {
	                        return replacer.apply({
	                                config: defaultConfig
	                            },
	                            [arguments[0], emojiName]
	                        );
	                    }
	                    /* Did not validate, return the original value */
	                    return arguments[0];
	                });

	            }
	            function run(el, replacer) {

	                // Check if an element was not passed.
	                // This will only work in the browser
	                if(typeof el === 'undefined'){
	                    // Check if an element was configured. If not, default to the body.
	                    if (defaultConfig.only_crawl_id) {
	                        el = document.getElementById(defaultConfig.only_crawl_id);
	                    } else {
	                        el = document.body;
	                    }
	                }

	                // Get the window object from the passed element.
	                var doc = el.ownerDocument,
	                    win = doc.defaultView || doc.parentWindow;

	                var treeTraverse = function (parent, cb){
	                    var child;

	                    if (parent.hasChildNodes()) {
	                        child = parent.firstChild;
	                        while(child){
	                            if(cb(child)) {
	                                treeTraverse(child, cb);
	                            }
	                            child = child.nextSibling;
	                        }
	                    }
	                };

	                var matchAndInsertEmoji = function(node) {
	                    var match;
	                    var matches = [];
	                    var validator = new Validator();

	                    while ((match = emojiMegaRe.exec(node.data)) !== null) {
	                        if(validator.validate(match, match.index, match.input)) {
	                            matches.push(match);
	                        }
	                    }

	                    for (var i = matches.length; i-- > 0;) {
	                        /* Replace the text with the emoji */
	                        var emojiName = getEmojiNameForMatch(matches[i]);
	                        insertEmojicon({
	                            node: node,
	                            match: matches[i],
	                            emojiName: emojiName,
	                            replacer: replacer,
	                            win: win
	                        });
	                    }
	                };

	                emoticonsProcessed = initEmoticonsProcessed();
	                emojiMegaRe = initMegaRe();

	                var nodes = [];

	                var elementsBlacklist = new RegExp(defaultConfig.blacklist.elements.join('|'), 'i'),
	                    classesBlacklist = new RegExp(defaultConfig.blacklist.classes.join('|'), 'i');

	                if(typeof win.document.createTreeWalker !== 'undefined') {
	                    var nodeIterator = win.document.createTreeWalker(
	                        el,
	                        win.NodeFilter.SHOW_TEXT | win.NodeFilter.SHOW_ELEMENT,
	                        function(node) {
	                            if(node.nodeType !== 1) {
	                                /* Text Node? Good! */
	                                return win.NodeFilter.FILTER_ACCEPT;
	                            }

	                            if(node.tagName.match(elementsBlacklist) || node.tagName === "svg" || node.className.match(classesBlacklist)) {
	                                return win.NodeFilter.FILTER_REJECT;
	                            }

	                            return win.NodeFilter.FILTER_SKIP;
	                        },
	                        false
	                    );

	                    var node;

	                    while((node = nodeIterator.nextNode()) !== null) {
	                        nodes.push(node);
	                    }
	                }
	                else {
	                    treeTraverse(el, function(node){
	                        if(
	                            (typeof node.tagName !== 'undefined' && node.tagName.match(elementsBlacklist)) ||
	                            (typeof node.className !== 'undefined' && node.className.match(classesBlacklist))
	                        ){
	                            return false;
	                        }
	                        if (node.nodeType === 1) {
	                            return true;
	                        }

	                        nodes.push(node);
	                        return true;
	                    });
	                }

	                nodes.forEach(matchAndInsertEmoji);
	            }

	            return {
	                // Sane defaults
	                defaultConfig: defaultConfig,
	                emojiNames: namedEmoji,
	                setConfig: function (newConfig) {
	                    Object.keys(defaultConfig).forEach(function(f) {
	                        if(f in newConfig) {
	                            defaultConfig[f] = newConfig[f];
	                        }
	                    });
	                },

	                replace: emojifyString,

	                // Main method
	                run: run
	            };
	        })();

	        return emojify;
	    }
	));


/***/ },
/* 430 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _slicedToArray = function () { function sliceIterator(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"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	__webpack_require__(318);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var LocationGraph = function () {
	  function LocationGraph() {
	    var _this = this;

	    _classCallCheck(this, LocationGraph);

	    if ((0, _jquery2.default)("#user-locations").length === 0) return;

	    // The size of a square, in px
	    this.SQUARE_SIZE = 18;

	    // The numbers of days per-row.
	    // 7 is good for a week :)
	    this.COL_SIZE = 7;

	    this.MONTH_OFFSET = this.SQUARE_SIZE * this.COL_SIZE + this.SQUARE_SIZE;

	    // The legend (month names) size.
	    this.LEGEND_HEIGHT = 40;

	    // The empty cell background-color (when the user didn't came)
	    this.BG_COLOR = "#fafafa";

	    // Get the 'month ceiled' number of days to generate from now.
	    var duration = moment.duration(moment().diff(moment().subtract(3, 'month')));
	    var offset_day = new Date(Date.now()).getDate();
	    this.days_history = parseInt(duration.asDays(), 10) + (offset_day < 31 ? offset_day : 0);
	    this.min_month = moment().subtract(this.days_history, 'days').month();
	    this.min_year = moment().subtract(this.days_history, 'days').year();
	    this.max = 24 * 60 * 60;

	    this.getGoodKey = function (__, e) {
	      var m = moment(e, "YYYY-MM-DD HH:mm:ss Z");
	      return m.month() + '#' + m.date();
	    };

	    this.firstDraw();
	    setTimeout(function () {
	      _this._fetchDataAndDraw();
	    }, 100);
	  }

	  _createClass(LocationGraph, [{
	    key: 'month_offset',
	    value: function month_offset(month, year) {
	      return (month - this.min_month) * this.MONTH_OFFSET + this.MONTH_OFFSET * 12 * (year - this.min_year);
	    }

	    // =========================== The main draw function =======================

	  }, {
	    key: 'draw',
	    value: function draw() {
	      var _this2 = this;

	      var c = 0;
	      var _old_month = -1; //AHAHAHAHAHAHAHA (c'est pour dessiner le premier mois)

	      this.svg.setAttribute('viewBox', '150 0 600 200');
	      this.svg.setAttribute('preserveAspectRatio', 'xMinYMin meet');
	      _.forEachRight(this.histo, function (v, k) {

	        // Unparse month & day from key
	        var _k$split = k.split("#"),
	            _k$split2 = _slicedToArray(_k$split, 3),
	            year = _k$split2[0],
	            month = _k$split2[1],
	            day = _k$split2[2];
	        // Counter reset

	        // console.log(year, month, day)


	        if (month != _old_month) {
	          _this2._draw_legend(month, year);
	          c = moment({ month: month, year: year }).startOf('day').day();
	        } else c += 1;

	        // Generate the rendered color
	        var x = _this2.SQUARE_SIZE + parseInt(c % _this2.COL_SIZE) * _this2.SQUARE_SIZE + _this2.month_offset(month, year);
	        var y = parseInt(c / _this2.COL_SIZE) * _this2.SQUARE_SIZE;

	        if (v != 0 && parseInt(v.split(':')[0]) >= 24) {
	          v = '24:00:00';
	          _this2._drawDay(x, y, 'rgba(0, 186, 188, 100)', day, _this2.max * 100, moment(v, 'HH:mm:ss'));

	          _old_month = month;
	        } else {
	          v = moment(v, "HH:mm:ss");
	          var nbr_seconds = v.hour() * 3600 + v.minutes() * 60 + v.seconds();
	          var cr = parseInt(nbr_seconds * 100 / _this2.max) || 0;
	          var color = cr == 0 ? _this2.BG_COLOR : 'rgba(0, 186, 188, ' + cr / 100 + ')';

	          // Draaaaw me tendeeeer !
	          _this2._drawDay(x, y, color, day, nbr_seconds, v);

	          _old_month = month;
	        }
	      });
	    }

	    // ============================== Draw utilities ============================

	  }, {
	    key: '_fetchDataAndDraw',
	    value: function _fetchDataAndDraw() {
	      var _this3 = this;

	      var url = this.svg.getAttribute('data-url');

	      _jquery2.default.ajax({
	        url: url + '.json',
	        xhrFields: { withCredentials: true },
	        async: true,
	        timeout: 30000,
	        success: function success(json) {
	          var _buffer = _.mapKeys(json, _this3.getGoodKey);
	          _this3.histo = _this3._getDatesArray(_buffer);
	          _this3.draw();
	          (0, _jquery2.default)("g[data-toggle='tooltip']").tooltip({ 'container': 'body' });
	          (0, _jquery2.default)("#user-locations-loading-overlay").remove();
	        },
	        error: function error(_error) {
	          console.error('ajax error');
	          console.log(_error);
	          var h1 = (0, _jquery2.default)("#user-locations-loading-overlay h1");
	          h1.text("An error has occured while loading locations. Please try again later.");
	          h1.removeClass("text-primary").addClass("text-danger");
	          return null;
	        }
	      });
	    }
	  }, {
	    key: 'firstDraw',
	    value: function firstDraw() {
	      this.svg = document.getElementById("user-locations");
	      this.ns = "http://www.w3.org/2000/svg";

	      // Simulate fake data so we dont have to wait for the ajax call
	      this.histo = this._getDatesArray(_.mapKeys({}, this.getGoodKey));
	      this.draw();
	      (0, _jquery2.default)("g[data-toggle='tooltip']").tooltip({ 'container': 'body' });
	    }

	    // Generate last days arrays

	  }, {
	    key: '_getDatesArray',
	    value: function _getDatesArray(histo) {
	      this.histo = histo;
	      var now = moment();
	      histo = {};

	      var num = 0;
	      while (num < this.days_history) {
	        histo[now.year() + '#' + now.month() + '#' + now.date()] = this.histo[now.month() + '#' + now.date()] || 0;
	        now = now.subtract(1, 'days');
	        num += 1;
	      }
	      // console.log("Histo: ", histo)
	      return histo;
	    }

	    // The month names

	  }, {
	    key: '_draw_legend',
	    value: function _draw_legend(month, year) {
	      var text = moment({ month: month }).format("MMM");
	      var index = this.SQUARE_SIZE + this.month_offset(month, year) + this.COL_SIZE * this.SQUARE_SIZE / 2;

	      text = document.createElementNS(this.ns, 'text');
	      text.innerHTML = moment({ month: month }).format("MMM");
	      text.setAttributeNS(null, 'x', index);
	      text.setAttributeNS(null, 'y', this.LEGEND_HEIGHT / 2);
	      text.setAttributeNS(null, 'fill', "#999");
	      text.setAttributeNS(null, 'width', this.COL_SIZE * this.SQUARE_SIZE);
	      text.setAttributeNS(null, 'height', this.COL_SIZE * this.SQUARE_SIZE);
	      text.setAttributeNS(null, 'font-family', "sans-serif");
	      text.setAttributeNS(null, 'font-size', '' + this.LEGEND_HEIGHT / 4);
	      this.svg.appendChild(text);
	    }

	    // Draw a square day

	  }, {
	    key: '_drawDay',
	    value: function _drawDay(x, y, color, day, nbr_seconds, v) {
	      var g = document.createElementNS(this.ns, 'g');
	      var rect = document.createElementNS(this.ns, 'rect');
	      var logtime = nbr_seconds >= this.max ? '24h00' : v.hour() + 'h' + (v.minutes() < 10 ? '0' : '') + v.minutes();
	      rect.setAttributeNS(null, 'x', x);
	      rect.setAttributeNS(null, 'y', y + this.LEGEND_HEIGHT);
	      rect.setAttributeNS(null, 'width', this.SQUARE_SIZE);
	      rect.setAttributeNS(null, 'height', this.SQUARE_SIZE);
	      rect.setAttributeNS(null, 'stroke', "#fff");
	      rect.setAttributeNS(null, 'stroke-width', "2");
	      rect.setAttributeNS(null, 'fill', color);
	      g.setAttributeNS(null, 'data-toggle', 'tooltip');
	      g.setAttributeNS(null, 'data-original-title', logtime);
	      g.appendChild(rect);

	      // Rajouter un hover pour display le nbr_seconds (formatter en heure evidement :D), amuse toi bien! :D
	      // Voir aussi si le @max est bien choisi ou si les couleurs sont parlantes, parce que 12h c'est déjà beaucoup mais ça fait que 50% de max
	      // :rocket: :moon:

	      var text = document.createElementNS(this.ns, 'text');
	      text.innerHTML = '' + day;
	      text.setAttributeNS(null, 'x', x + this.SQUARE_SIZE / 4);
	      text.setAttributeNS(null, 'y', y + this.LEGEND_HEIGHT + this.SQUARE_SIZE / 2 + 2);
	      text.setAttributeNS(null, 'fill', color == this.BG_COLOR ? "#ccc" : "#007B7C");
	      text.setAttributeNS(null, 'width', this.SQUARE_SIZE);
	      text.setAttributeNS(null, 'height', this.SQUARE_SIZE);
	      text.setAttributeNS(null, 'font-family', "sans-serif");
	      text.setAttributeNS(null, 'font-size', '' + this.SQUARE_SIZE / 2);
	      g.appendChild(text);

	      this.svg.appendChild(g);
	    }
	  }]);

	  return LocationGraph;
	}();

	exports.default = LocationGraph;

/***/ },
/* 431 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var LogtimesChart = function () {
	  function LogtimesChart() {
	    var _this = this;

	    _classCallCheck(this, LogtimesChart);

	    if ((0, _jquery2.default)("#chart-logtimes-day").length == 0) return;

	    (0, _jquery2.default)("a[data-toggle=tab][href^='#logtimes-']").click(function () {
	      if ((0, _jquery2.default)("#chart-logtimes-day").children().length == 0) {
	        _this.drawChart("#chart-logtimes-day", ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]);
	        _this.drawChart("#chart-logtimes-hour", [].concat(_toConsumableArray(Array(24).keys())));
	        _this.fetchDataSet();
	      }
	      var dayChart = (0, _jquery2.default)("#chart-logtimes-day").highcharts();
	      var hourChart = (0, _jquery2.default)("#chart-logtimes-hour").highcharts();
	      dayChart.reflow();
	      hourChart.reflow();
	    });
	  }

	  _createClass(LogtimesChart, [{
	    key: "fetchDataSet",
	    value: function fetchDataSet() {
	      var _this2 = this;

	      var url = window.location.pathname + '/logtimes';

	      _jquery2.default.getJSON(url, function (json) {
	        var dayChart = (0, _jquery2.default)("#chart-logtimes-day").highcharts();
	        var hourChart = (0, _jquery2.default)("#chart-logtimes-hour").highcharts();

	        _this2.addPoints(dayChart, json.by_day);
	        _this2.addPoints(hourChart, json.by_hour);
	        hourChart.xAxis[0].addPlotBand({ from: -1, to: 7, color: '#f3f3f3' });
	        dayChart.xAxis[0].addPlotBand({ from: 5, to: 7, color: '#f3f3f3' });
	      });
	    }
	  }, {
	    key: "addPoints",
	    value: function addPoints(chart, dataSet) {
	      var _iteratorNormalCompletion = true;
	      var _didIteratorError = false;
	      var _iteratorError = undefined;

	      try {
	        var _loop = function _loop() {
	          var elem = _step.value;

	          var data = dataSet.find(function (a) {
	            return a[0] == elem;
	          });
	          if (data) chart.series[0].addPoint([-parseFloat(data[1]), parseFloat(data[1])]);else chart.series[0].addPoint([0, 0]);
	        };

	        for (var _iterator = chart.xAxis[0].categories[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	          _loop();
	        }
	      } catch (err) {
	        _didIteratorError = true;
	        _iteratorError = err;
	      } finally {
	        try {
	          if (!_iteratorNormalCompletion && _iterator.return) {
	            _iterator.return();
	          }
	        } finally {
	          if (_didIteratorError) {
	            throw _iteratorError;
	          }
	        }
	      }
	    }
	  }, {
	    key: "drawChart",
	    value: function drawChart(selector, categories) {
	      (0, _jquery2.default)(selector).highcharts({
	        chart: {
	          type: 'columnrange',
	          plotBorderColor: "#fff",
	          animation: false,
	          style: {
	            fontFamily: ['Noto sans', 'sans-serif'],
	            width: '100%',
	            height: '100%'
	          }
	        },
	        title: { text: null },
	        credits: {
	          enabled: false
	        },
	        xAxis: {
	          categories: []
	        },
	        tooltip: {
	          formatter: function formatter() {
	            return '<b>' + this.x + '</b> : <b>' + Math.abs(this.y) + '%</b>';
	          }
	        },
	        yAxis: {
	          labels: { enabled: false },
	          title: null,
	          allowDecimals: true
	        },
	        plotOptions: {
	          series: {
	            pointPadding: 0,
	            groupPadding: 0,
	            borderWidth: 0
	          },
	          column: {
	            color: "#00BABC",
	            marker: { enabled: true }
	          }
	        },
	        series: [{ showInLegend: false, color: "#a9d9da", data: [] }]
	      });
	      var chart = (0, _jquery2.default)(selector).highcharts();
	      chart.xAxis[0].setCategories(categories);
	    }
	  }]);

	  return LogtimesChart;
	}();

	exports.default = LogtimesChart;

/***/ },
/* 432 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var BootstrapFlashHelper = function () {
	  function BootstrapFlashHelper() {
	    var _this = this;

	    _classCallCheck(this, BootstrapFlashHelper);

	    var flash = document.querySelector('.alert.fade');
	    if (flash) {
	      flash.addEventListener('click', function () {
	        _this._fadeOut(flash, 200);
	      });
	      setTimeout(function () {
	        _this._fadeOut(flash, 200);
	      }, 3000);
	    }
	  }

	  _createClass(BootstrapFlashHelper, [{
	    key: '_fadeOut',
	    value: function _fadeOut(el, speed) {
	      var seconds = speed / 1000;
	      el.style.transition = 'opacity ' + seconds + 's ease';
	      el.style.opacity = 0;
	      setTimeout(function () {
	        el.remove(el);
	      }, speed);
	    }
	  }]);

	  return BootstrapFlashHelper;
	}();

	exports.default = BootstrapFlashHelper;

/***/ },
/* 433 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function find(val, idx) {
	  var sel = document.getElementById('select_1');
	  alert(val + ' : ' + sel.options[idx].parentNode.label);
	}

	function init_selector(element) {
	  var force_string = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

	  var type = force_string ? (0, _jquery2.default)(element).parents('.webhook_registery_resource_event, .doorkeeper_application_webhook_registeries_resource_event').siblings('.webhook_registery_resource_type, .doorkeeper_application_webhook_registeries_resource_type').find('select').val() : (0, _jquery2.default)(element)[0].selectedOptions[0].parentElement.label;

	  (0, _jquery2.default)(element).siblings('.chosen-container').find('a.chosen-single > span').text(type + ' - ' + (0, _jquery2.default)(element).val());
	  (0, _jquery2.default)(element).parents('.webhook_registery_resource_event, .doorkeeper_application_webhook_registeries_resource_event').siblings('.webhook_registery_resource_type, .doorkeeper_application_webhook_registeries_resource_type').find('select').val(type);
	}

	function webhook_selector() {
	  var selector = (0, _jquery2.default)('.webhook-registery-item select.chosen-select');

	  selector.each(function () {
	    init_selector((0, _jquery2.default)(this), true);
	    (0, _jquery2.default)(this).on('change', function () {
	      init_selector((0, _jquery2.default)(this));
	    });

	    (0, _jquery2.default)(this).parents('[data-association="webhook_registeries"]').bind('cocoon:after-insert', function (e, _t) {
	      _t.find('.webhook_registery_resource_type select, .doorkeeper_application_webhook_registeries_resource_event select').on('change', function () {
	        init_selector((0, _jquery2.default)(this));
	      });
	    });
	  });
	}

	exports.default = webhook_selector;

/***/ },
/* 434 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _noty = __webpack_require__(415);

	var _noty2 = _interopRequireDefault(_noty);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var ScaleTeamUsers = function () {
	  function ScaleTeamUsers(opts) {
	    _classCallCheck(this, ScaleTeamUsers);

	    if ((0, _jquery2.default)("[data-scale-team]").length === 0) return;

	    var defaults = {
	      selector: "data-scale-team",
	      userId: (0, _jquery2.default)("body").attr("data-id"),
	      publicChannelName: "global",
	      queryEvent: "scale_team_user.checkin"
	    };

	    this.opts = _lodash2.default.extend(defaults, opts);
	    this.ws = false;
	    if (window.dispatcher != undefined) {
	      this.ws = dispatcher;
	      this._bindWsHandler();
	    } else {
	      console.warn("No websocket handler found :/");
	      this._bindAjaxHandler();
	    }
	  }

	  _createClass(ScaleTeamUsers, [{
	    key: '_bindWsHandler',
	    value: function _bindWsHandler() {
	      var _this = this;

	      public_channel = this.ws.subscribe(this.opts.publicChannelName);
	      public_channel.bind(this.opts.queryEvent, function (e) {
	        console.log("Checking event !", e);
	        _this._checkinFor(e.user_id, e.scale_team_id, e.login);
	      });
	    }
	  }, {
	    key: '_bindAjaxHandler',
	    value: function _bindAjaxHandler() {
	      console.log("Ajax fallback :'(");
	    }
	  }, {
	    key: '_checkinFor',
	    value: function _checkinFor(user_id, scale_team_id, login) {
	      elt = (0, _jquery2.default)('[data-checkin-id=\'' + scale_team_id + '-' + user_id + '\']');
	      elt.attr("data-checkin-present", "true");
	      (0, _noty2.default)({
	        layout: 'topRight',
	        type: 'success',
	        text: login + ' just checked in',
	        timeout: 4000
	      });
	    }
	  }]);

	  return ScaleTeamUsers;
	}();

	exports.default = ScaleTeamUsers;

/***/ },
/* 435 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _actioncable = __webpack_require__(436);

	var _actioncable2 = _interopRequireDefault(_actioncable);

	var _location = __webpack_require__(437);

	var _location2 = _interopRequireDefault(_location);

	var _notification = __webpack_require__(438);

	var _notification2 = _interopRequireDefault(_notification);

	var _repo_git = __webpack_require__(439);

	var _repo_git2 = _interopRequireDefault(_repo_git);

	var _flash_channel = __webpack_require__(440);

	var _flash_channel2 = _interopRequireDefault(_flash_channel);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	(function () {
	  this.App || (this.App = { last_ids: [] });
	  // 
	  App.cable = _actioncable2.default.createConsumer(window._consumer_address);
	  App.location = (0, _location2.default)();
	  App.notification = (0, _notification2.default)();
	  App.repo_git = (0, _repo_git2.default)();
	  App.flash_channel = (0, _flash_channel2.default)();
	}).call(window);

/***/ },
/* 436 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(module) {(function() {
	  var slice = [].slice;

	  this.ActionCable = {
	    INTERNAL: {
	      "message_types": {
	        "welcome": "welcome",
	        "ping": "ping",
	        "confirmation": "confirm_subscription",
	        "rejection": "reject_subscription"
	      },
	      "default_mount_path": "/cable",
	      "protocols": ["actioncable-v1-json", "actioncable-unsupported"]
	    },
	    createConsumer: function(url) {
	      var ref;
	      if (url == null) {
	        url = (ref = this.getConfig("url")) != null ? ref : this.INTERNAL.default_mount_path;
	      }
	      return new ActionCable.Consumer(this.createWebSocketURL(url));
	    },
	    getConfig: function(name) {
	      var element;
	      element = document.head.querySelector("meta[name='action-cable-" + name + "']");
	      return element != null ? element.getAttribute("content") : void 0;
	    },
	    createWebSocketURL: function(url) {
	      var a;
	      if (url && !/^wss?:/i.test(url)) {
	        a = document.createElement("a");
	        a.href = url;
	        a.href = a.href;
	        a.protocol = a.protocol.replace("http", "ws");
	        return a.href;
	      } else {
	        return url;
	      }
	    },
	    startDebugging: function() {
	      return this.debugging = true;
	    },
	    stopDebugging: function() {
	      return this.debugging = null;
	    },
	    log: function() {
	      var messages;
	      messages = 1 <= arguments.length ? slice.call(arguments, 0) : [];
	      if (this.debugging) {
	        messages.push(Date.now());
	        return console.log.apply(console, ["[ActionCable]"].concat(slice.call(messages)));
	      }
	    }
	  };

	  if (typeof window !== "undefined" && window !== null) {
	    window.ActionCable = this.ActionCable;
	  }

	  if (typeof module !== "undefined" && module !== null) {
	    module.exports = this.ActionCable;
	  }

	}).call(this);
	(function() {
	  var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

	  ActionCable.ConnectionMonitor = (function() {
	    var clamp, now, secondsSince;

	    ConnectionMonitor.pollInterval = {
	      min: 3,
	      max: 30
	    };

	    ConnectionMonitor.staleThreshold = 6;

	    function ConnectionMonitor(connection) {
	      this.connection = connection;
	      this.visibilityDidChange = bind(this.visibilityDidChange, this);
	      this.reconnectAttempts = 0;
	    }

	    ConnectionMonitor.prototype.start = function() {
	      if (!this.isRunning()) {
	        this.startedAt = now();
	        delete this.stoppedAt;
	        this.startPolling();
	        document.addEventListener("visibilitychange", this.visibilityDidChange);
	        return ActionCable.log("ConnectionMonitor started. pollInterval = " + (this.getPollInterval()) + " ms");
	      }
	    };

	    ConnectionMonitor.prototype.stop = function() {
	      if (this.isRunning()) {
	        this.stoppedAt = now();
	        this.stopPolling();
	        document.removeEventListener("visibilitychange", this.visibilityDidChange);
	        return ActionCable.log("ConnectionMonitor stopped");
	      }
	    };

	    ConnectionMonitor.prototype.isRunning = function() {
	      return (this.startedAt != null) && (this.stoppedAt == null);
	    };

	    ConnectionMonitor.prototype.recordPing = function() {
	      return this.pingedAt = now();
	    };

	    ConnectionMonitor.prototype.recordConnect = function() {
	      this.reconnectAttempts = 0;
	      this.recordPing();
	      delete this.disconnectedAt;
	      return ActionCable.log("ConnectionMonitor recorded connect");
	    };

	    ConnectionMonitor.prototype.recordDisconnect = function() {
	      this.disconnectedAt = now();
	      return ActionCable.log("ConnectionMonitor recorded disconnect");
	    };

	    ConnectionMonitor.prototype.startPolling = function() {
	      this.stopPolling();
	      return this.poll();
	    };

	    ConnectionMonitor.prototype.stopPolling = function() {
	      return clearTimeout(this.pollTimeout);
	    };

	    ConnectionMonitor.prototype.poll = function() {
	      return this.pollTimeout = setTimeout((function(_this) {
	        return function() {
	          _this.reconnectIfStale();
	          return _this.poll();
	        };
	      })(this), this.getPollInterval());
	    };

	    ConnectionMonitor.prototype.getPollInterval = function() {
	      var interval, max, min, ref;
	      ref = this.constructor.pollInterval, min = ref.min, max = ref.max;
	      interval = 5 * Math.log(this.reconnectAttempts + 1);
	      return Math.round(clamp(interval, min, max) * 1000);
	    };

	    ConnectionMonitor.prototype.reconnectIfStale = function() {
	      if (this.connectionIsStale()) {
	        ActionCable.log("ConnectionMonitor detected stale connection. reconnectAttempts = " + this.reconnectAttempts + ", pollInterval = " + (this.getPollInterval()) + " ms, time disconnected = " + (secondsSince(this.disconnectedAt)) + " s, stale threshold = " + this.constructor.staleThreshold + " s");
	        this.reconnectAttempts++;
	        if (this.disconnectedRecently()) {
	          return ActionCable.log("ConnectionMonitor skipping reopening recent disconnect");
	        } else {
	          ActionCable.log("ConnectionMonitor reopening");
	          return this.connection.reopen();
	        }
	      }
	    };

	    ConnectionMonitor.prototype.connectionIsStale = function() {
	      var ref;
	      return secondsSince((ref = this.pingedAt) != null ? ref : this.startedAt) > this.constructor.staleThreshold;
	    };

	    ConnectionMonitor.prototype.disconnectedRecently = function() {
	      return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold;
	    };

	    ConnectionMonitor.prototype.visibilityDidChange = function() {
	      if (document.visibilityState === "visible") {
	        return setTimeout((function(_this) {
	          return function() {
	            if (_this.connectionIsStale() || !_this.connection.isOpen()) {
	              ActionCable.log("ConnectionMonitor reopening stale connection on visibilitychange. visbilityState = " + document.visibilityState);
	              return _this.connection.reopen();
	            }
	          };
	        })(this), 200);
	      }
	    };

	    now = function() {
	      return new Date().getTime();
	    };

	    secondsSince = function(time) {
	      return (now() - time) / 1000;
	    };

	    clamp = function(number, min, max) {
	      return Math.max(min, Math.min(max, number));
	    };

	    return ConnectionMonitor;

	  })();

	}).call(this);
	(function() {
	  var i, message_types, protocols, ref, supportedProtocols, unsupportedProtocol,
	    slice = [].slice,
	    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
	    indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

	  ref = ActionCable.INTERNAL, message_types = ref.message_types, protocols = ref.protocols;

	  supportedProtocols = 2 <= protocols.length ? slice.call(protocols, 0, i = protocols.length - 1) : (i = 0, []), unsupportedProtocol = protocols[i++];

	  ActionCable.Connection = (function() {
	    Connection.reopenDelay = 500;

	    function Connection(consumer) {
	      this.consumer = consumer;
	      this.open = bind(this.open, this);
	      this.subscriptions = this.consumer.subscriptions;
	      this.monitor = new ActionCable.ConnectionMonitor(this);
	      this.disconnected = true;
	    }

	    Connection.prototype.send = function(data) {
	      if (this.isOpen()) {
	        this.webSocket.send(JSON.stringify(data));
	        return true;
	      } else {
	        return false;
	      }
	    };

	    Connection.prototype.open = function() {
	      if (this.isActive()) {
	        ActionCable.log("Attempted to open WebSocket, but existing socket is " + (this.getState()));
	        throw new Error("Existing connection must be closed before opening");
	      } else {
	        ActionCable.log("Opening WebSocket, current state is " + (this.getState()) + ", subprotocols: " + protocols);
	        if (this.webSocket != null) {
	          this.uninstallEventHandlers();
	        }
	        this.webSocket = new WebSocket(this.consumer.url, protocols);
	        this.installEventHandlers();
	        this.monitor.start();
	        return true;
	      }
	    };

	    Connection.prototype.close = function(arg) {
	      var allowReconnect, ref1;
	      allowReconnect = (arg != null ? arg : {
	        allowReconnect: true
	      }).allowReconnect;
	      if (!allowReconnect) {
	        this.monitor.stop();
	      }
	      if (this.isActive()) {
	        return (ref1 = this.webSocket) != null ? ref1.close() : void 0;
	      }
	    };

	    Connection.prototype.reopen = function() {
	      var error, error1;
	      ActionCable.log("Reopening WebSocket, current state is " + (this.getState()));
	      if (this.isActive()) {
	        try {
	          return this.close();
	        } catch (error1) {
	          error = error1;
	          return ActionCable.log("Failed to reopen WebSocket", error);
	        } finally {
	          ActionCable.log("Reopening WebSocket in " + this.constructor.reopenDelay + "ms");
	          setTimeout(this.open, this.constructor.reopenDelay);
	        }
	      } else {
	        return this.open();
	      }
	    };

	    Connection.prototype.getProtocol = function() {
	      var ref1;
	      return (ref1 = this.webSocket) != null ? ref1.protocol : void 0;
	    };

	    Connection.prototype.isOpen = function() {
	      return this.isState("open");
	    };

	    Connection.prototype.isActive = function() {
	      return this.isState("open", "connecting");
	    };

	    Connection.prototype.isProtocolSupported = function() {
	      var ref1;
	      return ref1 = this.getProtocol(), indexOf.call(supportedProtocols, ref1) >= 0;
	    };

	    Connection.prototype.isState = function() {
	      var ref1, states;
	      states = 1 <= arguments.length ? slice.call(arguments, 0) : [];
	      return ref1 = this.getState(), indexOf.call(states, ref1) >= 0;
	    };

	    Connection.prototype.getState = function() {
	      var ref1, state, value;
	      for (state in WebSocket) {
	        value = WebSocket[state];
	        if (value === ((ref1 = this.webSocket) != null ? ref1.readyState : void 0)) {
	          return state.toLowerCase();
	        }
	      }
	      return null;
	    };

	    Connection.prototype.installEventHandlers = function() {
	      var eventName, handler;
	      for (eventName in this.events) {
	        handler = this.events[eventName].bind(this);
	        this.webSocket["on" + eventName] = handler;
	      }
	    };

	    Connection.prototype.uninstallEventHandlers = function() {
	      var eventName;
	      for (eventName in this.events) {
	        this.webSocket["on" + eventName] = function() {};
	      }
	    };

	    Connection.prototype.events = {
	      message: function(event) {
	        var identifier, message, ref1, type;
	        if (!this.isProtocolSupported()) {
	          return;
	        }
	        ref1 = JSON.parse(event.data), identifier = ref1.identifier, message = ref1.message, type = ref1.type;
	        switch (type) {
	          case message_types.welcome:
	            this.monitor.recordConnect();
	            return this.subscriptions.reload();
	          case message_types.ping:
	            return this.monitor.recordPing();
	          case message_types.confirmation:
	            return this.subscriptions.notify(identifier, "connected");
	          case message_types.rejection:
	            return this.subscriptions.reject(identifier);
	          default:
	            return this.subscriptions.notify(identifier, "received", message);
	        }
	      },
	      open: function() {
	        ActionCable.log("WebSocket onopen event, using '" + (this.getProtocol()) + "' subprotocol");
	        this.disconnected = false;
	        if (!this.isProtocolSupported()) {
	          ActionCable.log("Protocol is unsupported. Stopping monitor and disconnecting.");
	          return this.close({
	            allowReconnect: false
	          });
	        }
	      },
	      close: function(event) {
	        ActionCable.log("WebSocket onclose event");
	        if (this.disconnected) {
	          return;
	        }
	        this.disconnected = true;
	        this.monitor.recordDisconnect();
	        return this.subscriptions.notifyAll("disconnected", {
	          willAttemptReconnect: this.monitor.isRunning()
	        });
	      },
	      error: function() {
	        return ActionCable.log("WebSocket onerror event");
	      }
	    };

	    return Connection;

	  })();

	}).call(this);
	(function() {
	  var slice = [].slice;

	  ActionCable.Subscriptions = (function() {
	    function Subscriptions(consumer) {
	      this.consumer = consumer;
	      this.subscriptions = [];
	    }

	    Subscriptions.prototype.create = function(channelName, mixin) {
	      var channel, params, subscription;
	      channel = channelName;
	      params = typeof channel === "object" ? channel : {
	        channel: channel
	      };
	      subscription = new ActionCable.Subscription(this.consumer, params, mixin);
	      return this.add(subscription);
	    };

	    Subscriptions.prototype.add = function(subscription) {
	      this.subscriptions.push(subscription);
	      this.consumer.ensureActiveConnection();
	      this.notify(subscription, "initialized");
	      this.sendCommand(subscription, "subscribe");
	      return subscription;
	    };

	    Subscriptions.prototype.remove = function(subscription) {
	      this.forget(subscription);
	      if (!this.findAll(subscription.identifier).length) {
	        this.sendCommand(subscription, "unsubscribe");
	      }
	      return subscription;
	    };

	    Subscriptions.prototype.reject = function(identifier) {
	      var i, len, ref, results, subscription;
	      ref = this.findAll(identifier);
	      results = [];
	      for (i = 0, len = ref.length; i < len; i++) {
	        subscription = ref[i];
	        this.forget(subscription);
	        this.notify(subscription, "rejected");
	        results.push(subscription);
	      }
	      return results;
	    };

	    Subscriptions.prototype.forget = function(subscription) {
	      var s;
	      this.subscriptions = (function() {
	        var i, len, ref, results;
	        ref = this.subscriptions;
	        results = [];
	        for (i = 0, len = ref.length; i < len; i++) {
	          s = ref[i];
	          if (s !== subscription) {
	            results.push(s);
	          }
	        }
	        return results;
	      }).call(this);
	      return subscription;
	    };

	    Subscriptions.prototype.findAll = function(identifier) {
	      var i, len, ref, results, s;
	      ref = this.subscriptions;
	      results = [];
	      for (i = 0, len = ref.length; i < len; i++) {
	        s = ref[i];
	        if (s.identifier === identifier) {
	          results.push(s);
	        }
	      }
	      return results;
	    };

	    Subscriptions.prototype.reload = function() {
	      var i, len, ref, results, subscription;
	      ref = this.subscriptions;
	      results = [];
	      for (i = 0, len = ref.length; i < len; i++) {
	        subscription = ref[i];
	        results.push(this.sendCommand(subscription, "subscribe"));
	      }
	      return results;
	    };

	    Subscriptions.prototype.notifyAll = function() {
	      var args, callbackName, i, len, ref, results, subscription;
	      callbackName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
	      ref = this.subscriptions;
	      results = [];
	      for (i = 0, len = ref.length; i < len; i++) {
	        subscription = ref[i];
	        results.push(this.notify.apply(this, [subscription, callbackName].concat(slice.call(args))));
	      }
	      return results;
	    };

	    Subscriptions.prototype.notify = function() {
	      var args, callbackName, i, len, results, subscription, subscriptions;
	      subscription = arguments[0], callbackName = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
	      if (typeof subscription === "string") {
	        subscriptions = this.findAll(subscription);
	      } else {
	        subscriptions = [subscription];
	      }
	      results = [];
	      for (i = 0, len = subscriptions.length; i < len; i++) {
	        subscription = subscriptions[i];
	        results.push(typeof subscription[callbackName] === "function" ? subscription[callbackName].apply(subscription, args) : void 0);
	      }
	      return results;
	    };

	    Subscriptions.prototype.sendCommand = function(subscription, command) {
	      var identifier;
	      identifier = subscription.identifier;
	      return this.consumer.send({
	        command: command,
	        identifier: identifier
	      });
	    };

	    return Subscriptions;

	  })();

	}).call(this);
	(function() {
	  ActionCable.Subscription = (function() {
	    var extend;

	    function Subscription(consumer, params, mixin) {
	      this.consumer = consumer;
	      if (params == null) {
	        params = {};
	      }
	      this.identifier = JSON.stringify(params);
	      extend(this, mixin);
	    }

	    Subscription.prototype.perform = function(action, data) {
	      if (data == null) {
	        data = {};
	      }
	      data.action = action;
	      return this.send(data);
	    };

	    Subscription.prototype.send = function(data) {
	      return this.consumer.send({
	        command: "message",
	        identifier: this.identifier,
	        data: JSON.stringify(data)
	      });
	    };

	    Subscription.prototype.unsubscribe = function() {
	      return this.consumer.subscriptions.remove(this);
	    };

	    extend = function(object, properties) {
	      var key, value;
	      if (properties != null) {
	        for (key in properties) {
	          value = properties[key];
	          object[key] = value;
	        }
	      }
	      return object;
	    };

	    return Subscription;

	  })();

	}).call(this);
	(function() {
	  ActionCable.Consumer = (function() {
	    function Consumer(url) {
	      this.url = url;
	      this.subscriptions = new ActionCable.Subscriptions(this);
	      this.connection = new ActionCable.Connection(this);
	    }

	    Consumer.prototype.send = function(data) {
	      return this.connection.send(data);
	    };

	    Consumer.prototype.connect = function() {
	      return this.connection.open();
	    };

	    Consumer.prototype.disconnect = function() {
	      return this.connection.close({
	        allowReconnect: false
	      });
	    };

	    Consumer.prototype.ensureActiveConnection = function() {
	      if (!this.connection.isActive()) {
	        return this.connection.open();
	      }
	    };

	    return Consumer;

	  })();

	}).call(this);

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8)(module)))

/***/ },
/* 437 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	exports.default = function () {
	  if (window.location.pathname == '/clusters' || window.location.pathname.split('/')[3] == 'clusters') {
	    return App.cable.subscriptions.create({ channel: "LocationChannel", user_id: window._user['id'] }, {
	      connected: function connected() {
	        this.last_id = null;

	        console.log("je connect location");
	        window.clusterMap.load();
	      },

	      disconnected: function disconnected() {
	        console.log("je deconnect");
	      },

	      received: function received(data) {
	        if (this.last_id != null && this.last_id != data['id'] - 1) console.log("il manque des datas!");else {
	          window.clusterMap.onDataRecieved(data.location);
	        }
	        this.last_id = data['id'];
	      }
	    });
	  }
	};

/***/ },
/* 438 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});

	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

	exports.default = function () {
	    if (!window._user) {
	        return;
	    }
	    return App.cable.subscriptions.create({ channel: "NotificationChannel", user_id: window._user['id'] }, {
	        connected: function connected() {
	            App.last_ids['notifications'] || (App.last_ids['notifications'] = null);

	            if (App.last_ids['notifications'] != null) {
	                // Je me reco
	                this.perform("last_id", { user_id: window._user['id'] });
	            }
	        },

	        disconnected: function disconnected() {},

	        received: function received(data) {
	            console.log("data!", data, App.last_ids['notifications']);
	            if (typeof window.ft_notification === "undefined") return false;

	            if (data["notification"] == null && App.last_ids['notifications'] != null) // last id
	                {
	                    if (App.last_ids['notifications'] < data['id']) {
	                        window.ft_notification.fetchNotifications();
	                        App.last_ids['notifications'] = data['id'];
	                    }
	                } else {
	                if (App.last_ids['notifications'] != null && App.last_ids['notifications'] != data['id'] - 1) {
	                    window.ft_notification.fetchNotifications();
	                } else {
	                    if (_typeof(data.notification) == "object") window.ft_notification._onNew(data.notification);else window.ft_notification._onNew(JSON.parse(data.notification));
	                }
	                App.last_ids['notifications'] = data['id'];
	            }
	        }
	    });
	};

/***/ },
/* 439 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});

	exports.default = function () {
	    if (document.querySelector('[data-git-waiting]')) {
	        return App.cable.subscriptions.create({
	            channel: "RepoGitChannel",
	            user_id: window._user['id'],
	            team_id: document.querySelector('[data-git-waiting]').getAttribute('data-git-waiting')
	        }, {
	            connected: function connected() {},

	            disconnected: function disconnected() {},

	            received: function received(data) {
	                document.querySelector('[data-git-waiting]').innerHTML = data['team']['html'];
	                window.copy._initCopy(document.querySelector('[data-git-waiting]').querySelector("[data-copy]"));
	            }
	        });
	    }
	};

/***/ },
/* 440 */
/***/ function(module, exports) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	exports.default = function () {
	  if (!window._user) {
	    return;
	  }

	  var bindMarkAsSeen = function bindMarkAsSeen(modal, flash) {
	    $.signedAjax({ url: flash.read_url, method: "POST" }).success(function (d) {
	      console.log("👀 Read Flash !", d);
	    }).error(function (d) {
	      console.warn("Error in flash", d);
	    });
	  };

	  var createModal = function createModal(flash) {
	    var modalId = Math.random().toString(36).substr(2);
	    var template = ("\n      <div aria-hidden=\"true\" aria-labelledby=\"flashModalLabel\" class=\"modal websocket-modal fade\" id=\"" + modalId + "\" role=\"dialog\" tabindex=\"-1\">\n        <div class=\"modal-dialog modal-lg\">\n          <div class=\"modal-content\">\n            <div class=\"modal-header\">\n              <button aria-hidden=\"true\" class=\"close\" data-dismiss=\"modal\" type=\"button\">\n                x\n              </button>\n              <h3 id=\"flashModalLabel\">" + flash.title + "</h3>\n            </div>\n            <div class=\"modal-body\">\n              " + _.unescape(flash.content) + "\n            </div>\n            <div class=\"modal-footer\">\n              <button aria-hidden=\"true\" class=\"btn btn-block btn-default\" data-dismiss=\"modal\">Close</button>\n            </div>\n          </div>\n        </div>\n      </div>\n    ").trim();
	    $('#flashModal').after(template);
	    var modal = $("#" + modalId);
	    modal.modal('show');
	    bindMarkAsSeen(modal, flash);
	  };

	  return App.cable.subscriptions.create({
	    channel: "FlashChannel",
	    user_id: window._user['id']
	  }, {
	    connected: function connected() {
	      console.log("je connect les flash bngo");
	    },

	    disconnected: function disconnected() {
	      console.log("je deconnect les flash bngo");
	    },

	    received: function received(flash) {
	      createModal(flash);
	    }
	  });
	};

/***/ },
/* 441 */
/***/ function(module, exports) {

	// import 'expose?Toto!./toto';
	"use strict";

/***/ },
/* 442 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var require;var require;'use strict';

	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

	/*!
	 * Select2 4.0.3
	 * https://select2.github.io
	 *
	 * Released under the MIT license
	 * https://github.com/select2/select2/blob/master/LICENSE.md
	 */
	(function (factory) {
	  if (true) {
	    // AMD. Register as an anonymous module.
	    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__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__));
	  } else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
	    // Node/CommonJS
	    factory(require('jquery'));
	  } else {
	    // Browser globals
	    factory(jQuery);
	  }
	})(function (jQuery) {
	  // This is needed so we can catch the AMD loader configuration and use it
	  // The inner file should be wrapped (by `banner.start.js`) in a function that
	  // returns the AMD loader references.
	  var S2 = function () {
	    // Restore the Select2 AMD loader so it can be used
	    // Needed mostly in the language files, where the loader is not inserted
	    if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
	      var S2 = jQuery.fn.select2.amd;
	    }
	    var S2;(function () {
	      if (!S2 || !S2.requirejs) {
	        if (!S2) {
	          S2 = {};
	        } else {
	          require = S2;
	        }
	        /**
	         * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
	         * Available via the MIT or new BSD license.
	         * see: http://github.com/jrburke/almond for details
	         */
	        //Going sloppy to avoid 'use strict' string cost, but strict practices should
	        //be followed.
	        /*jslint sloppy: true */
	        /*global setTimeout: false */

	        var requirejs, require, define;
	        (function (undef) {
	          var main,
	              _req,
	              makeMap,
	              handlers,
	              defined = {},
	              waiting = {},
	              config = {},
	              defining = {},
	              hasOwn = Object.prototype.hasOwnProperty,
	              aps = [].slice,
	              jsSuffixRegExp = /\.js$/;

	          function hasProp(obj, prop) {
	            return hasOwn.call(obj, prop);
	          }

	          /**
	           * Given a relative module name, like ./something, normalize it to
	           * a real name that can be mapped to a path.
	           * @param {String} name the relative name
	           * @param {String} baseName a real name that the name arg is relative
	           * to.
	           * @returns {String} normalized name
	           */
	          function normalize(name, baseName) {
	            var nameParts,
	                nameSegment,
	                mapValue,
	                foundMap,
	                lastIndex,
	                foundI,
	                foundStarMap,
	                starI,
	                i,
	                j,
	                part,
	                baseParts = baseName && baseName.split("/"),
	                map = config.map,
	                starMap = map && map['*'] || {};

	            //Adjust any relative paths.
	            if (name && name.charAt(0) === ".") {
	              //If have a base name, try to normalize against it,
	              //otherwise, assume it is a top-level require that will
	              //be relative to baseUrl in the end.
	              if (baseName) {
	                name = name.split('/');
	                lastIndex = name.length - 1;

	                // Node .js allowance:
	                if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
	                  name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
	                }

	                //Lop off the last part of baseParts, so that . matches the
	                //"directory" and not name of the baseName's module. For instance,
	                //baseName of "one/two/three", maps to "one/two/three.js", but we
	                //want the directory, "one/two" for this normalization.
	                name = baseParts.slice(0, baseParts.length - 1).concat(name);

	                //start trimDots
	                for (i = 0; i < name.length; i += 1) {
	                  part = name[i];
	                  if (part === ".") {
	                    name.splice(i, 1);
	                    i -= 1;
	                  } else if (part === "..") {
	                    if (i === 1 && (name[2] === '..' || name[0] === '..')) {
	                      //End of the line. Keep at least one non-dot
	                      //path segment at the front so it can be mapped
	                      //correctly to disk. Otherwise, there is likely
	                      //no path mapping for a path starting with '..'.
	                      //This can still fail, but catches the most reasonable
	                      //uses of ..
	                      break;
	                    } else if (i > 0) {
	                      name.splice(i - 1, 2);
	                      i -= 2;
	                    }
	                  }
	                }
	                //end trimDots

	                name = name.join("/");
	              } else if (name.indexOf('./') === 0) {
	                // No baseName, so this is ID is resolved relative
	                // to baseUrl, pull off the leading dot.
	                name = name.substring(2);
	              }
	            }

	            //Apply map config if available.
	            if ((baseParts || starMap) && map) {
	              nameParts = name.split('/');

	              for (i = nameParts.length; i > 0; i -= 1) {
	                nameSegment = nameParts.slice(0, i).join("/");

	                if (baseParts) {
	                  //Find the longest baseName segment match in the config.
	                  //So, do joins on the biggest to smallest lengths of baseParts.
	                  for (j = baseParts.length; j > 0; j -= 1) {
	                    mapValue = map[baseParts.slice(0, j).join('/')];

	                    //baseName segment has  config, find if it has one for
	                    //this name.
	                    if (mapValue) {
	                      mapValue = mapValue[nameSegment];
	                      if (mapValue) {
	                        //Match, update name to the new value.
	                        foundMap = mapValue;
	                        foundI = i;
	                        break;
	                      }
	                    }
	                  }
	                }

	                if (foundMap) {
	                  break;
	                }

	                //Check for a star map match, but just hold on to it,
	                //if there is a shorter segment match later in a matching
	                //config, then favor over this star map.
	                if (!foundStarMap && starMap && starMap[nameSegment]) {
	                  foundStarMap = starMap[nameSegment];
	                  starI = i;
	                }
	              }

	              if (!foundMap && foundStarMap) {
	                foundMap = foundStarMap;
	                foundI = starI;
	              }

	              if (foundMap) {
	                nameParts.splice(0, foundI, foundMap);
	                name = nameParts.join('/');
	              }
	            }

	            return name;
	          }

	          function makeRequire(relName, forceSync) {
	            return function () {
	              //A version of a require function that passes a moduleName
	              //value for items that may need to
	              //look up paths relative to the moduleName
	              var args = aps.call(arguments, 0);

	              //If first arg is not require('string'), and there is only
	              //one arg, it is the array form without a callback. Insert
	              //a null so that the following concat is correct.
	              if (typeof args[0] !== 'string' && args.length === 1) {
	                args.push(null);
	              }
	              return _req.apply(undef, args.concat([relName, forceSync]));
	            };
	          }

	          function makeNormalize(relName) {
	            return function (name) {
	              return normalize(name, relName);
	            };
	          }

	          function makeLoad(depName) {
	            return function (value) {
	              defined[depName] = value;
	            };
	          }

	          function callDep(name) {
	            if (hasProp(waiting, name)) {
	              var args = waiting[name];
	              delete waiting[name];
	              defining[name] = true;
	              main.apply(undef, args);
	            }

	            if (!hasProp(defined, name) && !hasProp(defining, name)) {
	              throw new Error('No ' + name);
	            }
	            return defined[name];
	          }

	          //Turns a plugin!resource to [plugin, resource]
	          //with the plugin being undefined if the name
	          //did not have a plugin prefix.
	          function splitPrefix(name) {
	            var prefix,
	                index = name ? name.indexOf('!') : -1;
	            if (index > -1) {
	              prefix = name.substring(0, index);
	              name = name.substring(index + 1, name.length);
	            }
	            return [prefix, name];
	          }

	          /**
	           * Makes a name map, normalizing the name, and using a plugin
	           * for normalization if necessary. Grabs a ref to plugin
	           * too, as an optimization.
	           */
	          makeMap = function makeMap(name, relName) {
	            var plugin,
	                parts = splitPrefix(name),
	                prefix = parts[0];

	            name = parts[1];

	            if (prefix) {
	              prefix = normalize(prefix, relName);
	              plugin = callDep(prefix);
	            }

	            //Normalize according
	            if (prefix) {
	              if (plugin && plugin.normalize) {
	                name = plugin.normalize(name, makeNormalize(relName));
	              } else {
	                name = normalize(name, relName);
	              }
	            } else {
	              name = normalize(name, relName);
	              parts = splitPrefix(name);
	              prefix = parts[0];
	              name = parts[1];
	              if (prefix) {
	                plugin = callDep(prefix);
	              }
	            }

	            //Using ridiculous property names for space reasons
	            return {
	              f: prefix ? prefix + '!' + name : name, //fullName
	              n: name,
	              pr: prefix,
	              p: plugin
	            };
	          };

	          function makeConfig(name) {
	            return function () {
	              return config && config.config && config.config[name] || {};
	            };
	          }

	          handlers = {
	            require: function require(name) {
	              return makeRequire(name);
	            },
	            exports: function exports(name) {
	              var e = defined[name];
	              if (typeof e !== 'undefined') {
	                return e;
	              } else {
	                return defined[name] = {};
	              }
	            },
	            module: function module(name) {
	              return {
	                id: name,
	                uri: '',
	                exports: defined[name],
	                config: makeConfig(name)
	              };
	            }
	          };

	          main = function main(name, deps, callback, relName) {
	            var cjsModule,
	                depName,
	                ret,
	                map,
	                i,
	                args = [],
	                callbackType = typeof callback === 'undefined' ? 'undefined' : _typeof(callback),
	                usingExports;

	            //Use name if no relName
	            relName = relName || name;

	            //Call the callback to define the module, if necessary.
	            if (callbackType === 'undefined' || callbackType === 'function') {
	              //Pull out the defined dependencies and pass the ordered
	              //values to the callback.
	              //Default to [require, exports, module] if no deps
	              deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
	              for (i = 0; i < deps.length; i += 1) {
	                map = makeMap(deps[i], relName);
	                depName = map.f;

	                //Fast path CommonJS standard dependencies.
	                if (depName === "require") {
	                  args[i] = handlers.require(name);
	                } else if (depName === "exports") {
	                  //CommonJS module spec 1.1
	                  args[i] = handlers.exports(name);
	                  usingExports = true;
	                } else if (depName === "module") {
	                  //CommonJS module spec 1.1
	                  cjsModule = args[i] = handlers.module(name);
	                } else if (hasProp(defined, depName) || hasProp(waiting, depName) || hasProp(defining, depName)) {
	                  args[i] = callDep(depName);
	                } else if (map.p) {
	                  map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
	                  args[i] = defined[depName];
	                } else {
	                  throw new Error(name + ' missing ' + depName);
	                }
	              }

	              ret = callback ? callback.apply(defined[name], args) : undefined;

	              if (name) {
	                //If setting exports via "module" is in play,
	                //favor that over return value and exports. After that,
	                //favor a non-undefined return value over exports use.
	                if (cjsModule && cjsModule.exports !== undef && cjsModule.exports !== defined[name]) {
	                  defined[name] = cjsModule.exports;
	                } else if (ret !== undef || !usingExports) {
	                  //Use the return value from the function.
	                  defined[name] = ret;
	                }
	              }
	            } else if (name) {
	              //May just be an object definition for the module. Only
	              //worry about defining if have a module name.
	              defined[name] = callback;
	            }
	          };

	          requirejs = require = _req = function req(deps, callback, relName, forceSync, alt) {
	            if (typeof deps === "string") {
	              if (handlers[deps]) {
	                //callback in this case is really relName
	                return handlers[deps](callback);
	              }
	              //Just return the module wanted. In this scenario, the
	              //deps arg is the module name, and second arg (if passed)
	              //is just the relName.
	              //Normalize module name, if it contains . or ..
	              return callDep(makeMap(deps, callback).f);
	            } else if (!deps.splice) {
	              //deps is a config object, not an array.
	              config = deps;
	              if (config.deps) {
	                _req(config.deps, config.callback);
	              }
	              if (!callback) {
	                return;
	              }

	              if (callback.splice) {
	                //callback is an array, which means it is a dependency list.
	                //Adjust args if there are dependencies
	                deps = callback;
	                callback = relName;
	                relName = null;
	              } else {
	                deps = undef;
	              }
	            }

	            //Support require(['a'])
	            callback = callback || function () {};

	            //If relName is a function, it is an errback handler,
	            //so remove it.
	            if (typeof relName === 'function') {
	              relName = forceSync;
	              forceSync = alt;
	            }

	            //Simulate async callback;
	            if (forceSync) {
	              main(undef, deps, callback, relName);
	            } else {
	              //Using a non-zero value because of concern for what old browsers
	              //do, and latest browsers "upgrade" to 4 if lower value is used:
	              //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
	              //If want a value immediately, use require('id') instead -- something
	              //that works in almond on the global level, but not guaranteed and
	              //unlikely to work in other AMD implementations.
	              setTimeout(function () {
	                main(undef, deps, callback, relName);
	              }, 4);
	            }

	            return _req;
	          };

	          /**
	           * Just drops the config on the floor, but returns req in case
	           * the config return value is used.
	           */
	          _req.config = function (cfg) {
	            return _req(cfg);
	          };

	          /**
	           * Expose module registry for debugging and tooling
	           */
	          requirejs._defined = defined;

	          define = function define(name, deps, callback) {
	            if (typeof name !== 'string') {
	              throw new Error('See almond README: incorrect module build, no module name');
	            }

	            //This module may not have dependencies
	            if (!deps.splice) {
	              //deps is not an array, so probably means
	              //an object literal or factory function for
	              //the value. Adjust args.
	              callback = deps;
	              deps = [];
	            }

	            if (!hasProp(defined, name) && !hasProp(waiting, name)) {
	              waiting[name] = [name, deps, callback];
	            }
	          };

	          define.amd = {
	            jQuery: true
	          };
	        })();

	        S2.requirejs = requirejs;S2.require = require;S2.define = define;
	      }
	    })();
	    S2.define("almond", function () {});

	    /* global jQuery:false, $:false */
	    S2.define('jquery', [], function () {
	      var _$ = jQuery || $;

	      if (_$ == null && console && console.error) {
	        console.error('Select2: An instance of jQuery or a jQuery-compatible library was not ' + 'found. Make sure that you are including jQuery before Select2 on your ' + 'web page.');
	      }

	      return _$;
	    });

	    S2.define('select2/utils', ['jquery'], function ($) {
	      var Utils = {};

	      Utils.Extend = function (ChildClass, SuperClass) {
	        var __hasProp = {}.hasOwnProperty;

	        function BaseConstructor() {
	          this.constructor = ChildClass;
	        }

	        for (var key in SuperClass) {
	          if (__hasProp.call(SuperClass, key)) {
	            ChildClass[key] = SuperClass[key];
	          }
	        }

	        BaseConstructor.prototype = SuperClass.prototype;
	        ChildClass.prototype = new BaseConstructor();
	        ChildClass.__super__ = SuperClass.prototype;

	        return ChildClass;
	      };

	      function getMethods(theClass) {
	        var proto = theClass.prototype;

	        var methods = [];

	        for (var methodName in proto) {
	          var m = proto[methodName];

	          if (typeof m !== 'function') {
	            continue;
	          }

	          if (methodName === 'constructor') {
	            continue;
	          }

	          methods.push(methodName);
	        }

	        return methods;
	      }

	      Utils.Decorate = function (SuperClass, DecoratorClass) {
	        var decoratedMethods = getMethods(DecoratorClass);
	        var superMethods = getMethods(SuperClass);

	        function DecoratedClass() {
	          var unshift = Array.prototype.unshift;

	          var argCount = DecoratorClass.prototype.constructor.length;

	          var calledConstructor = SuperClass.prototype.constructor;

	          if (argCount > 0) {
	            unshift.call(arguments, SuperClass.prototype.constructor);

	            calledConstructor = DecoratorClass.prototype.constructor;
	          }

	          calledConstructor.apply(this, arguments);
	        }

	        DecoratorClass.displayName = SuperClass.displayName;

	        function ctr() {
	          this.constructor = DecoratedClass;
	        }

	        DecoratedClass.prototype = new ctr();

	        for (var m = 0; m < superMethods.length; m++) {
	          var superMethod = superMethods[m];

	          DecoratedClass.prototype[superMethod] = SuperClass.prototype[superMethod];
	        }

	        var calledMethod = function calledMethod(methodName) {
	          // Stub out the original method if it's not decorating an actual method
	          var originalMethod = function originalMethod() {};

	          if (methodName in DecoratedClass.prototype) {
	            originalMethod = DecoratedClass.prototype[methodName];
	          }

	          var decoratedMethod = DecoratorClass.prototype[methodName];

	          return function () {
	            var unshift = Array.prototype.unshift;

	            unshift.call(arguments, originalMethod);

	            return decoratedMethod.apply(this, arguments);
	          };
	        };

	        for (var d = 0; d < decoratedMethods.length; d++) {
	          var decoratedMethod = decoratedMethods[d];

	          DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
	        }

	        return DecoratedClass;
	      };

	      var Observable = function Observable() {
	        this.listeners = {};
	      };

	      Observable.prototype.on = function (event, callback) {
	        this.listeners = this.listeners || {};

	        if (event in this.listeners) {
	          this.listeners[event].push(callback);
	        } else {
	          this.listeners[event] = [callback];
	        }
	      };

	      Observable.prototype.trigger = function (event) {
	        var slice = Array.prototype.slice;
	        var params = slice.call(arguments, 1);

	        this.listeners = this.listeners || {};

	        // Params should always come in as an array
	        if (params == null) {
	          params = [];
	        }

	        // If there are no arguments to the event, use a temporary object
	        if (params.length === 0) {
	          params.push({});
	        }

	        // Set the `_type` of the first object to the event
	        params[0]._type = event;

	        if (event in this.listeners) {
	          this.invoke(this.listeners[event], slice.call(arguments, 1));
	        }

	        if ('*' in this.listeners) {
	          this.invoke(this.listeners['*'], arguments);
	        }
	      };

	      Observable.prototype.invoke = function (listeners, params) {
	        for (var i = 0, len = listeners.length; i < len; i++) {
	          listeners[i].apply(this, params);
	        }
	      };

	      Utils.Observable = Observable;

	      Utils.generateChars = function (length) {
	        var chars = '';

	        for (var i = 0; i < length; i++) {
	          var randomChar = Math.floor(Math.random() * 36);
	          chars += randomChar.toString(36);
	        }

	        return chars;
	      };

	      Utils.bind = function (func, context) {
	        return function () {
	          func.apply(context, arguments);
	        };
	      };

	      Utils._convertData = function (data) {
	        for (var originalKey in data) {
	          var keys = originalKey.split('-');

	          var dataLevel = data;

	          if (keys.length === 1) {
	            continue;
	          }

	          for (var k = 0; k < keys.length; k++) {
	            var key = keys[k];

	            // Lowercase the first letter
	            // By default, dash-separated becomes camelCase
	            key = key.substring(0, 1).toLowerCase() + key.substring(1);

	            if (!(key in dataLevel)) {
	              dataLevel[key] = {};
	            }

	            if (k == keys.length - 1) {
	              dataLevel[key] = data[originalKey];
	            }

	            dataLevel = dataLevel[key];
	          }

	          delete data[originalKey];
	        }

	        return data;
	      };

	      Utils.hasScroll = function (index, el) {
	        // Adapted from the function created by @ShadowScripter
	        // and adapted by @BillBarry on the Stack Exchange Code Review website.
	        // The original code can be found at
	        // http://codereview.stackexchange.com/q/13338
	        // and was designed to be used with the Sizzle selector engine.

	        var $el = $(el);
	        var overflowX = el.style.overflowX;
	        var overflowY = el.style.overflowY;

	        //Check both x and y declarations
	        if (overflowX === overflowY && (overflowY === 'hidden' || overflowY === 'visible')) {
	          return false;
	        }

	        if (overflowX === 'scroll' || overflowY === 'scroll') {
	          return true;
	        }

	        return $el.innerHeight() < el.scrollHeight || $el.innerWidth() < el.scrollWidth;
	      };

	      Utils.escapeMarkup = function (markup) {
	        var replaceMap = {
	          '\\': '&#92;',
	          '&': '&amp;',
	          '<': '&lt;',
	          '>': '&gt;',
	          '"': '&quot;',
	          '\'': '&#39;',
	          '/': '&#47;'
	        };

	        // Do not try to escape the markup if it's not a string
	        if (typeof markup !== 'string') {
	          return markup;
	        }

	        return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
	          return replaceMap[match];
	        });
	      };

	      // Append an array of jQuery nodes to a given element.
	      Utils.appendMany = function ($element, $nodes) {
	        // jQuery 1.7.x does not support $.fn.append() with an array
	        // Fall back to a jQuery object collection using $.fn.add()
	        if ($.fn.jquery.substr(0, 3) === '1.7') {
	          var $jqNodes = $();

	          $.map($nodes, function (node) {
	            $jqNodes = $jqNodes.add(node);
	          });

	          $nodes = $jqNodes;
	        }

	        $element.append($nodes);
	      };

	      return Utils;
	    });

	    S2.define('select2/results', ['jquery', './utils'], function ($, Utils) {
	      function Results($element, options, dataAdapter) {
	        this.$element = $element;
	        this.data = dataAdapter;
	        this.options = options;

	        Results.__super__.constructor.call(this);
	      }

	      Utils.Extend(Results, Utils.Observable);

	      Results.prototype.render = function () {
	        var $results = $('<ul class="select2-results__options" role="tree"></ul>');

	        if (this.options.get('multiple')) {
	          $results.attr('aria-multiselectable', 'true');
	        }

	        this.$results = $results;

	        return $results;
	      };

	      Results.prototype.clear = function () {
	        this.$results.empty();
	      };

	      Results.prototype.displayMessage = function (params) {
	        var escapeMarkup = this.options.get('escapeMarkup');

	        this.clear();
	        this.hideLoading();

	        var $message = $('<li role="treeitem" aria-live="assertive"' + ' class="select2-results__option"></li>');

	        var message = this.options.get('translations').get(params.message);

	        $message.append(escapeMarkup(message(params.args)));

	        $message[0].className += ' select2-results__message';

	        this.$results.append($message);
	      };

	      Results.prototype.hideMessages = function () {
	        this.$results.find('.select2-results__message').remove();
	      };

	      Results.prototype.append = function (data) {
	        this.hideLoading();

	        var $options = [];

	        if (data.results == null || data.results.length === 0) {
	          if (this.$results.children().length === 0) {
	            this.trigger('results:message', {
	              message: 'noResults'
	            });
	          }

	          return;
	        }

	        data.results = this.sort(data.results);

	        for (var d = 0; d < data.results.length; d++) {
	          var item = data.results[d];

	          var $option = this.option(item);

	          $options.push($option);
	        }

	        this.$results.append($options);
	      };

	      Results.prototype.position = function ($results, $dropdown) {
	        var $resultsContainer = $dropdown.find('.select2-results');
	        $resultsContainer.append($results);
	      };

	      Results.prototype.sort = function (data) {
	        var sorter = this.options.get('sorter');

	        return sorter(data);
	      };

	      Results.prototype.highlightFirstItem = function () {
	        var $options = this.$results.find('.select2-results__option[aria-selected]');

	        var $selected = $options.filter('[aria-selected=true]');

	        // Check if there are any selected options
	        if ($selected.length > 0) {
	          // If there are selected options, highlight the first
	          $selected.first().trigger('mouseenter');
	        } else {
	          // If there are no selected options, highlight the first option
	          // in the dropdown
	          $options.first().trigger('mouseenter');
	        }

	        this.ensureHighlightVisible();
	      };

	      Results.prototype.setClasses = function () {
	        var self = this;

	        this.data.current(function (selected) {
	          var selectedIds = $.map(selected, function (s) {
	            return s.id.toString();
	          });

	          var $options = self.$results.find('.select2-results__option[aria-selected]');

	          $options.each(function () {
	            var $option = $(this);

	            var item = $.data(this, 'data');

	            // id needs to be converted to a string when comparing
	            var id = '' + item.id;

	            if (item.element != null && item.element.selected || item.element == null && $.inArray(id, selectedIds) > -1) {
	              $option.attr('aria-selected', 'true');
	            } else {
	              $option.attr('aria-selected', 'false');
	            }
	          });
	        });
	      };

	      Results.prototype.showLoading = function (params) {
	        this.hideLoading();

	        var loadingMore = this.options.get('translations').get('searching');

	        var loading = {
	          disabled: true,
	          loading: true,
	          text: loadingMore(params)
	        };
	        var $loading = this.option(loading);
	        $loading.className += ' loading-results';

	        this.$results.prepend($loading);
	      };

	      Results.prototype.hideLoading = function () {
	        this.$results.find('.loading-results').remove();
	      };

	      Results.prototype.option = function (data) {
	        var option = document.createElement('li');
	        option.className = 'select2-results__option';

	        var attrs = {
	          'role': 'treeitem',
	          'aria-selected': 'false'
	        };

	        if (data.disabled) {
	          delete attrs['aria-selected'];
	          attrs['aria-disabled'] = 'true';
	        }

	        if (data.id == null) {
	          delete attrs['aria-selected'];
	        }

	        if (data._resultId != null) {
	          option.id = data._resultId;
	        }

	        if (data.title) {
	          option.title = data.title;
	        }

	        if (data.children) {
	          attrs.role = 'group';
	          attrs['aria-label'] = data.text;
	          delete attrs['aria-selected'];
	        }

	        for (var attr in attrs) {
	          var val = attrs[attr];

	          option.setAttribute(attr, val);
	        }

	        if (data.children) {
	          var $option = $(option);

	          var label = document.createElement('strong');
	          label.className = 'select2-results__group';

	          var $label = $(label);
	          this.template(data, label);

	          var $children = [];

	          for (var c = 0; c < data.children.length; c++) {
	            var child = data.children[c];

	            var $child = this.option(child);

	            $children.push($child);
	          }

	          var $childrenContainer = $('<ul></ul>', {
	            'class': 'select2-results__options select2-results__options--nested'
	          });

	          $childrenContainer.append($children);

	          $option.append(label);
	          $option.append($childrenContainer);
	        } else {
	          this.template(data, option);
	        }

	        $.data(option, 'data', data);

	        return option;
	      };

	      Results.prototype.bind = function (container, $container) {
	        var self = this;

	        var id = container.id + '-results';

	        this.$results.attr('id', id);

	        container.on('results:all', function (params) {
	          self.clear();
	          self.append(params.data);

	          if (container.isOpen()) {
	            self.setClasses();
	            self.highlightFirstItem();
	          }
	        });

	        container.on('results:append', function (params) {
	          self.append(params.data);

	          if (container.isOpen()) {
	            self.setClasses();
	          }
	        });

	        container.on('query', function (params) {
	          self.hideMessages();
	          self.showLoading(params);
	        });

	        container.on('select', function () {
	          if (!container.isOpen()) {
	            return;
	          }

	          self.setClasses();
	          self.highlightFirstItem();
	        });

	        container.on('unselect', function () {
	          if (!container.isOpen()) {
	            return;
	          }

	          self.setClasses();
	          self.highlightFirstItem();
	        });

	        container.on('open', function () {
	          // When the dropdown is open, aria-expended="true"
	          self.$results.attr('aria-expanded', 'true');
	          self.$results.attr('aria-hidden', 'false');

	          self.setClasses();
	          self.ensureHighlightVisible();
	        });

	        container.on('close', function () {
	          // When the dropdown is closed, aria-expended="false"
	          self.$results.attr('aria-expanded', 'false');
	          self.$results.attr('aria-hidden', 'true');
	          self.$results.removeAttr('aria-activedescendant');
	        });

	        container.on('results:toggle', function () {
	          var $highlighted = self.getHighlightedResults();

	          if ($highlighted.length === 0) {
	            return;
	          }

	          $highlighted.trigger('mouseup');
	        });

	        container.on('results:select', function () {
	          var $highlighted = self.getHighlightedResults();

	          if ($highlighted.length === 0) {
	            return;
	          }

	          var data = $highlighted.data('data');

	          if ($highlighted.attr('aria-selected') == 'true') {
	            self.trigger('close', {});
	          } else {
	            self.trigger('select', {
	              data: data
	            });
	          }
	        });

	        container.on('results:previous', function () {
	          var $highlighted = self.getHighlightedResults();

	          var $options = self.$results.find('[aria-selected]');

	          var currentIndex = $options.index($highlighted);

	          // If we are already at te top, don't move further
	          if (currentIndex === 0) {
	            return;
	          }

	          var nextIndex = currentIndex - 1;

	          // If none are highlighted, highlight the first
	          if ($highlighted.length === 0) {
	            nextIndex = 0;
	          }

	          var $next = $options.eq(nextIndex);

	          $next.trigger('mouseenter');

	          var currentOffset = self.$results.offset().top;
	          var nextTop = $next.offset().top;
	          var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);

	          if (nextIndex === 0) {
	            self.$results.scrollTop(0);
	          } else if (nextTop - currentOffset < 0) {
	            self.$results.scrollTop(nextOffset);
	          }
	        });

	        container.on('results:next', function () {
	          var $highlighted = self.getHighlightedResults();

	          var $options = self.$results.find('[aria-selected]');

	          var currentIndex = $options.index($highlighted);

	          var nextIndex = currentIndex + 1;

	          // If we are at the last option, stay there
	          if (nextIndex >= $options.length) {
	            return;
	          }

	          var $next = $options.eq(nextIndex);

	          $next.trigger('mouseenter');

	          var currentOffset = self.$results.offset().top + self.$results.outerHeight(false);
	          var nextBottom = $next.offset().top + $next.outerHeight(false);
	          var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;

	          if (nextIndex === 0) {
	            self.$results.scrollTop(0);
	          } else if (nextBottom > currentOffset) {
	            self.$results.scrollTop(nextOffset);
	          }
	        });

	        container.on('results:focus', function (params) {
	          params.element.addClass('select2-results__option--highlighted');
	        });

	        container.on('results:message', function (params) {
	          self.displayMessage(params);
	        });

	        if ($.fn.mousewheel) {
	          this.$results.on('mousewheel', function (e) {
	            var top = self.$results.scrollTop();

	            var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;

	            var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
	            var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();

	            if (isAtTop) {
	              self.$results.scrollTop(0);

	              e.preventDefault();
	              e.stopPropagation();
	            } else if (isAtBottom) {
	              self.$results.scrollTop(self.$results.get(0).scrollHeight - self.$results.height());

	              e.preventDefault();
	              e.stopPropagation();
	            }
	          });
	        }

	        this.$results.on('mouseup', '.select2-results__option[aria-selected]', function (evt) {
	          var $this = $(this);

	          var data = $this.data('data');

	          if ($this.attr('aria-selected') === 'true') {
	            if (self.options.get('multiple')) {
	              self.trigger('unselect', {
	                originalEvent: evt,
	                data: data
	              });
	            } else {
	              self.trigger('close', {});
	            }

	            return;
	          }

	          self.trigger('select', {
	            originalEvent: evt,
	            data: data
	          });
	        });

	        this.$results.on('mouseenter', '.select2-results__option[aria-selected]', function (evt) {
	          var data = $(this).data('data');

	          self.getHighlightedResults().removeClass('select2-results__option--highlighted');

	          self.trigger('results:focus', {
	            data: data,
	            element: $(this)
	          });
	        });
	      };

	      Results.prototype.getHighlightedResults = function () {
	        var $highlighted = this.$results.find('.select2-results__option--highlighted');

	        return $highlighted;
	      };

	      Results.prototype.destroy = function () {
	        this.$results.remove();
	      };

	      Results.prototype.ensureHighlightVisible = function () {
	        var $highlighted = this.getHighlightedResults();

	        if ($highlighted.length === 0) {
	          return;
	        }

	        var $options = this.$results.find('[aria-selected]');

	        var currentIndex = $options.index($highlighted);

	        var currentOffset = this.$results.offset().top;
	        var nextTop = $highlighted.offset().top;
	        var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);

	        var offsetDelta = nextTop - currentOffset;
	        nextOffset -= $highlighted.outerHeight(false) * 2;

	        if (currentIndex <= 2) {
	          this.$results.scrollTop(0);
	        } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
	          this.$results.scrollTop(nextOffset);
	        }
	      };

	      Results.prototype.template = function (result, container) {
	        var template = this.options.get('templateResult');
	        var escapeMarkup = this.options.get('escapeMarkup');

	        var content = template(result, container);

	        if (content == null) {
	          container.style.display = 'none';
	        } else if (typeof content === 'string') {
	          container.innerHTML = escapeMarkup(content);
	        } else {
	          $(container).append(content);
	        }
	      };

	      return Results;
	    });

	    S2.define('select2/keys', [], function () {
	      var KEYS = {
	        BACKSPACE: 8,
	        TAB: 9,
	        ENTER: 13,
	        SHIFT: 16,
	        CTRL: 17,
	        ALT: 18,
	        ESC: 27,
	        SPACE: 32,
	        PAGE_UP: 33,
	        PAGE_DOWN: 34,
	        END: 35,
	        HOME: 36,
	        LEFT: 37,
	        UP: 38,
	        RIGHT: 39,
	        DOWN: 40,
	        DELETE: 46
	      };

	      return KEYS;
	    });

	    S2.define('select2/selection/base', ['jquery', '../utils', '../keys'], function ($, Utils, KEYS) {
	      function BaseSelection($element, options) {
	        this.$element = $element;
	        this.options = options;

	        BaseSelection.__super__.constructor.call(this);
	      }

	      Utils.Extend(BaseSelection, Utils.Observable);

	      BaseSelection.prototype.render = function () {
	        var $selection = $('<span class="select2-selection" role="combobox" ' + ' aria-haspopup="true" aria-expanded="false">' + '</span>');

	        this._tabindex = 0;

	        if (this.$element.data('old-tabindex') != null) {
	          this._tabindex = this.$element.data('old-tabindex');
	        } else if (this.$element.attr('tabindex') != null) {
	          this._tabindex = this.$element.attr('tabindex');
	        }

	        $selection.attr('title', this.$element.attr('title'));
	        $selection.attr('tabindex', this._tabindex);

	        this.$selection = $selection;

	        return $selection;
	      };

	      BaseSelection.prototype.bind = function (container, $container) {
	        var self = this;

	        var id = container.id + '-container';
	        var resultsId = container.id + '-results';

	        this.container = container;

	        this.$selection.on('focus', function (evt) {
	          self.trigger('focus', evt);
	        });

	        this.$selection.on('blur', function (evt) {
	          self._handleBlur(evt);
	        });

	        this.$selection.on('keydown', function (evt) {
	          self.trigger('keypress', evt);

	          if (evt.which === KEYS.SPACE) {
	            evt.preventDefault();
	          }
	        });

	        container.on('results:focus', function (params) {
	          self.$selection.attr('aria-activedescendant', params.data._resultId);
	        });

	        container.on('selection:update', function (params) {
	          self.update(params.data);
	        });

	        container.on('open', function () {
	          // When the dropdown is open, aria-expanded="true"
	          self.$selection.attr('aria-expanded', 'true');
	          self.$selection.attr('aria-owns', resultsId);

	          self._attachCloseHandler(container);
	        });

	        container.on('close', function () {
	          // When the dropdown is closed, aria-expanded="false"
	          self.$selection.attr('aria-expanded', 'false');
	          self.$selection.removeAttr('aria-activedescendant');
	          self.$selection.removeAttr('aria-owns');

	          self.$selection.focus();

	          self._detachCloseHandler(container);
	        });

	        container.on('enable', function () {
	          self.$selection.attr('tabindex', self._tabindex);
	        });

	        container.on('disable', function () {
	          self.$selection.attr('tabindex', '-1');
	        });
	      };

	      BaseSelection.prototype._handleBlur = function (evt) {
	        var self = this;

	        // This needs to be delayed as the active element is the body when the tab
	        // key is pressed, possibly along with others.
	        window.setTimeout(function () {
	          // Don't trigger `blur` if the focus is still in the selection
	          if (document.activeElement == self.$selection[0] || $.contains(self.$selection[0], document.activeElement)) {
	            return;
	          }

	          self.trigger('blur', evt);
	        }, 1);
	      };

	      BaseSelection.prototype._attachCloseHandler = function (container) {
	        var self = this;

	        $(document.body).on('mousedown.select2.' + container.id, function (e) {
	          var $target = $(e.target);

	          var $select = $target.closest('.select2');

	          var $all = $('.select2.select2-container--open');

	          $all.each(function () {
	            var $this = $(this);

	            if (this == $select[0]) {
	              return;
	            }

	            var $element = $this.data('element');

	            $element.select2('close');
	          });
	        });
	      };

	      BaseSelection.prototype._detachCloseHandler = function (container) {
	        $(document.body).off('mousedown.select2.' + container.id);
	      };

	      BaseSelection.prototype.position = function ($selection, $container) {
	        var $selectionContainer = $container.find('.selection');
	        $selectionContainer.append($selection);
	      };

	      BaseSelection.prototype.destroy = function () {
	        this._detachCloseHandler(this.container);
	      };

	      BaseSelection.prototype.update = function (data) {
	        throw new Error('The `update` method must be defined in child classes.');
	      };

	      return BaseSelection;
	    });

	    S2.define('select2/selection/single', ['jquery', './base', '../utils', '../keys'], function ($, BaseSelection, Utils, KEYS) {
	      function SingleSelection() {
	        SingleSelection.__super__.constructor.apply(this, arguments);
	      }

	      Utils.Extend(SingleSelection, BaseSelection);

	      SingleSelection.prototype.render = function () {
	        var $selection = SingleSelection.__super__.render.call(this);

	        $selection.addClass('select2-selection--single');

	        $selection.html('<span class="select2-selection__rendered"></span>' + '<span class="select2-selection__arrow" role="presentation">' + '<b role="presentation"></b>' + '</span>');

	        return $selection;
	      };

	      SingleSelection.prototype.bind = function (container, $container) {
	        var self = this;

	        SingleSelection.__super__.bind.apply(this, arguments);

	        var id = container.id + '-container';

	        this.$selection.find('.select2-selection__rendered').attr('id', id);
	        this.$selection.attr('aria-labelledby', id);

	        this.$selection.on('mousedown', function (evt) {
	          // Only respond to left clicks
	          if (evt.which !== 1) {
	            return;
	          }

	          self.trigger('toggle', {
	            originalEvent: evt
	          });
	        });

	        this.$selection.on('focus', function (evt) {
	          // User focuses on the container
	        });

	        this.$selection.on('blur', function (evt) {
	          // User exits the container
	        });

	        container.on('focus', function (evt) {
	          if (!container.isOpen()) {
	            self.$selection.focus();
	          }
	        });

	        container.on('selection:update', function (params) {
	          self.update(params.data);
	        });
	      };

	      SingleSelection.prototype.clear = function () {
	        this.$selection.find('.select2-selection__rendered').empty();
	      };

	      SingleSelection.prototype.display = function (data, container) {
	        var template = this.options.get('templateSelection');
	        var escapeMarkup = this.options.get('escapeMarkup');

	        return escapeMarkup(template(data, container));
	      };

	      SingleSelection.prototype.selectionContainer = function () {
	        return $('<span></span>');
	      };

	      SingleSelection.prototype.update = function (data) {
	        if (data.length === 0) {
	          this.clear();
	          return;
	        }

	        var selection = data[0];

	        var $rendered = this.$selection.find('.select2-selection__rendered');
	        var formatted = this.display(selection, $rendered);

	        $rendered.empty().append(formatted);
	        $rendered.prop('title', selection.title || selection.text);
	      };

	      return SingleSelection;
	    });

	    S2.define('select2/selection/multiple', ['jquery', './base', '../utils'], function ($, BaseSelection, Utils) {
	      function MultipleSelection($element, options) {
	        MultipleSelection.__super__.constructor.apply(this, arguments);
	      }

	      Utils.Extend(MultipleSelection, BaseSelection);

	      MultipleSelection.prototype.render = function () {
	        var $selection = MultipleSelection.__super__.render.call(this);

	        $selection.addClass('select2-selection--multiple');

	        $selection.html('<ul class="select2-selection__rendered"></ul>');

	        return $selection;
	      };

	      MultipleSelection.prototype.bind = function (container, $container) {
	        var self = this;

	        MultipleSelection.__super__.bind.apply(this, arguments);

	        this.$selection.on('click', function (evt) {
	          self.trigger('toggle', {
	            originalEvent: evt
	          });
	        });

	        this.$selection.on('click', '.select2-selection__choice__remove', function (evt) {
	          // Ignore the event if it is disabled
	          if (self.options.get('disabled')) {
	            return;
	          }

	          var $remove = $(this);
	          var $selection = $remove.parent();

	          var data = $selection.data('data');

	          self.trigger('unselect', {
	            originalEvent: evt,
	            data: data
	          });
	        });
	      };

	      MultipleSelection.prototype.clear = function () {
	        this.$selection.find('.select2-selection__rendered').empty();
	      };

	      MultipleSelection.prototype.display = function (data, container) {
	        var template = this.options.get('templateSelection');
	        var escapeMarkup = this.options.get('escapeMarkup');

	        return escapeMarkup(template(data, container));
	      };

	      MultipleSelection.prototype.selectionContainer = function () {
	        var $container = $('<li class="select2-selection__choice">' + '<span class="select2-selection__choice__remove" role="presentation">' + '&times;' + '</span>' + '</li>');

	        return $container;
	      };

	      MultipleSelection.prototype.update = function (data) {
	        this.clear();

	        if (data.length === 0) {
	          return;
	        }

	        var $selections = [];

	        for (var d = 0; d < data.length; d++) {
	          var selection = data[d];

	          var $selection = this.selectionContainer();
	          var formatted = this.display(selection, $selection);

	          $selection.append(formatted);
	          $selection.prop('title', selection.title || selection.text);

	          $selection.data('data', selection);

	          $selections.push($selection);
	        }

	        var $rendered = this.$selection.find('.select2-selection__rendered');

	        Utils.appendMany($rendered, $selections);
	      };

	      return MultipleSelection;
	    });

	    S2.define('select2/selection/placeholder', ['../utils'], function (Utils) {
	      function Placeholder(decorated, $element, options) {
	        this.placeholder = this.normalizePlaceholder(options.get('placeholder'));

	        decorated.call(this, $element, options);
	      }

	      Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
	        if (typeof placeholder === 'string') {
	          placeholder = {
	            id: '',
	            text: placeholder
	          };
	        }

	        return placeholder;
	      };

	      Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
	        var $placeholder = this.selectionContainer();

	        $placeholder.html(this.display(placeholder));
	        $placeholder.addClass('select2-selection__placeholder').removeClass('select2-selection__choice');

	        return $placeholder;
	      };

	      Placeholder.prototype.update = function (decorated, data) {
	        var singlePlaceholder = data.length == 1 && data[0].id != this.placeholder.id;
	        var multipleSelections = data.length > 1;

	        if (multipleSelections || singlePlaceholder) {
	          return decorated.call(this, data);
	        }

	        this.clear();

	        var $placeholder = this.createPlaceholder(this.placeholder);

	        this.$selection.find('.select2-selection__rendered').append($placeholder);
	      };

	      return Placeholder;
	    });

	    S2.define('select2/selection/allowClear', ['jquery', '../keys'], function ($, KEYS) {
	      function AllowClear() {}

	      AllowClear.prototype.bind = function (decorated, container, $container) {
	        var self = this;

	        decorated.call(this, container, $container);

	        if (this.placeholder == null) {
	          if (this.options.get('debug') && window.console && console.error) {
	            console.error('Select2: The `allowClear` option should be used in combination ' + 'with the `placeholder` option.');
	          }
	        }

	        this.$selection.on('mousedown', '.select2-selection__clear', function (evt) {
	          self._handleClear(evt);
	        });

	        container.on('keypress', function (evt) {
	          self._handleKeyboardClear(evt, container);
	        });
	      };

	      AllowClear.prototype._handleClear = function (_, evt) {
	        // Ignore the event if it is disabled
	        if (this.options.get('disabled')) {
	          return;
	        }

	        var $clear = this.$selection.find('.select2-selection__clear');

	        // Ignore the event if nothing has been selected
	        if ($clear.length === 0) {
	          return;
	        }

	        evt.stopPropagation();

	        var data = $clear.data('data');

	        for (var d = 0; d < data.length; d++) {
	          var unselectData = {
	            data: data[d]
	          };

	          // Trigger the `unselect` event, so people can prevent it from being
	          // cleared.
	          this.trigger('unselect', unselectData);

	          // If the event was prevented, don't clear it out.
	          if (unselectData.prevented) {
	            return;
	          }
	        }

	        this.$element.val(this.placeholder.id).trigger('change');

	        this.trigger('toggle', {});
	      };

	      AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
	        if (container.isOpen()) {
	          return;
	        }

	        if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
	          this._handleClear(evt);
	        }
	      };

	      AllowClear.prototype.update = function (decorated, data) {
	        decorated.call(this, data);

	        if (this.$selection.find('.select2-selection__placeholder').length > 0 || data.length === 0) {
	          return;
	        }

	        var $remove = $('<span class="select2-selection__clear">' + '&times;' + '</span>');
	        $remove.data('data', data);

	        this.$selection.find('.select2-selection__rendered').prepend($remove);
	      };

	      return AllowClear;
	    });

	    S2.define('select2/selection/search', ['jquery', '../utils', '../keys'], function ($, Utils, KEYS) {
	      function Search(decorated, $element, options) {
	        decorated.call(this, $element, options);
	      }

	      Search.prototype.render = function (decorated) {
	        var $search = $('<li class="select2-search select2-search--inline">' + '<input class="select2-search__field" type="search" tabindex="-1"' + ' autocomplete="off" autocorrect="off" autocapitalize="off"' + ' spellcheck="false" role="textbox" aria-autocomplete="list" />' + '</li>');

	        this.$searchContainer = $search;
	        this.$search = $search.find('input');

	        var $rendered = decorated.call(this);

	        this._transferTabIndex();

	        return $rendered;
	      };

	      Search.prototype.bind = function (decorated, container, $container) {
	        var self = this;

	        decorated.call(this, container, $container);

	        container.on('open', function () {
	          self.$search.trigger('focus');
	        });

	        container.on('close', function () {
	          self.$search.val('');
	          self.$search.removeAttr('aria-activedescendant');
	          self.$search.trigger('focus');
	        });

	        container.on('enable', function () {
	          self.$search.prop('disabled', false);

	          self._transferTabIndex();
	        });

	        container.on('disable', function () {
	          self.$search.prop('disabled', true);
	        });

	        container.on('focus', function (evt) {
	          self.$search.trigger('focus');
	        });

	        container.on('results:focus', function (params) {
	          self.$search.attr('aria-activedescendant', params.id);
	        });

	        this.$selection.on('focusin', '.select2-search--inline', function (evt) {
	          self.trigger('focus', evt);
	        });

	        this.$selection.on('focusout', '.select2-search--inline', function (evt) {
	          self._handleBlur(evt);
	        });

	        this.$selection.on('keydown', '.select2-search--inline', function (evt) {
	          evt.stopPropagation();

	          self.trigger('keypress', evt);

	          self._keyUpPrevented = evt.isDefaultPrevented();

	          var key = evt.which;

	          if (key === KEYS.BACKSPACE && self.$search.val() === '') {
	            var $previousChoice = self.$searchContainer.prev('.select2-selection__choice');

	            if ($previousChoice.length > 0) {
	              var item = $previousChoice.data('data');

	              self.searchRemoveChoice(item);

	              evt.preventDefault();
	            }
	          }
	        });

	        // Try to detect the IE version should the `documentMode` property that
	        // is stored on the document. This is only implemented in IE and is
	        // slightly cleaner than doing a user agent check.
	        // This property is not available in Edge, but Edge also doesn't have
	        // this bug.
	        var msie = document.documentMode;
	        var disableInputEvents = msie && msie <= 11;

	        // Workaround for browsers which do not support the `input` event
	        // This will prevent double-triggering of events for browsers which support
	        // both the `keyup` and `input` events.
	        this.$selection.on('input.searchcheck', '.select2-search--inline', function (evt) {
	          // IE will trigger the `input` event when a placeholder is used on a
	          // search box. To get around this issue, we are forced to ignore all
	          // `input` events in IE and keep using `keyup`.
	          if (disableInputEvents) {
	            self.$selection.off('input.search input.searchcheck');
	            return;
	          }

	          // Unbind the duplicated `keyup` event
	          self.$selection.off('keyup.search');
	        });

	        this.$selection.on('keyup.search input.search', '.select2-search--inline', function (evt) {
	          // IE will trigger the `input` event when a placeholder is used on a
	          // search box. To get around this issue, we are forced to ignore all
	          // `input` events in IE and keep using `keyup`.
	          if (disableInputEvents && evt.type === 'input') {
	            self.$selection.off('input.search input.searchcheck');
	            return;
	          }

	          var key = evt.which;

	          // We can freely ignore events from modifier keys
	          if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
	            return;
	          }

	          // Tabbing will be handled during the `keydown` phase
	          if (key == KEYS.TAB) {
	            return;
	          }

	          self.handleSearch(evt);
	        });
	      };

	      /**
	       * This method will transfer the tabindex attribute from the rendered
	       * selection to the search box. This allows for the search box to be used as
	       * the primary focus instead of the selection container.
	       *
	       * @private
	       */
	      Search.prototype._transferTabIndex = function (decorated) {
	        this.$search.attr('tabindex', this.$selection.attr('tabindex'));
	        this.$selection.attr('tabindex', '-1');
	      };

	      Search.prototype.createPlaceholder = function (decorated, placeholder) {
	        this.$search.attr('placeholder', placeholder.text);
	      };

	      Search.prototype.update = function (decorated, data) {
	        var searchHadFocus = this.$search[0] == document.activeElement;

	        this.$search.attr('placeholder', '');

	        decorated.call(this, data);

	        this.$selection.find('.select2-selection__rendered').append(this.$searchContainer);

	        this.resizeSearch();
	        if (searchHadFocus) {
	          this.$search.focus();
	        }
	      };

	      Search.prototype.handleSearch = function () {
	        this.resizeSearch();

	        if (!this._keyUpPrevented) {
	          var input = this.$search.val();

	          this.trigger('query', {
	            term: input
	          });
	        }

	        this._keyUpPrevented = false;
	      };

	      Search.prototype.searchRemoveChoice = function (decorated, item) {
	        this.trigger('unselect', {
	          data: item
	        });

	        this.$search.val(item.text);
	        this.handleSearch();
	      };

	      Search.prototype.resizeSearch = function () {
	        this.$search.css('width', '25px');

	        var width = '';

	        if (this.$search.attr('placeholder') !== '') {
	          width = this.$selection.find('.select2-selection__rendered').innerWidth();
	        } else {
	          var minimumWidth = this.$search.val().length + 1;

	          width = minimumWidth * 0.75 + 'em';
	        }

	        this.$search.css('width', width);
	      };

	      return Search;
	    });

	    S2.define('select2/selection/eventRelay', ['jquery'], function ($) {
	      function EventRelay() {}

	      EventRelay.prototype.bind = function (decorated, container, $container) {
	        var self = this;
	        var relayEvents = ['open', 'opening', 'close', 'closing', 'select', 'selecting', 'unselect', 'unselecting'];

	        var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];

	        decorated.call(this, container, $container);

	        container.on('*', function (name, params) {
	          // Ignore events that should not be relayed
	          if ($.inArray(name, relayEvents) === -1) {
	            return;
	          }

	          // The parameters should always be an object
	          params = params || {};

	          // Generate the jQuery event for the Select2 event
	          var evt = $.Event('select2:' + name, {
	            params: params
	          });

	          self.$element.trigger(evt);

	          // Only handle preventable events if it was one
	          if ($.inArray(name, preventableEvents) === -1) {
	            return;
	          }

	          params.prevented = evt.isDefaultPrevented();
	        });
	      };

	      return EventRelay;
	    });

	    S2.define('select2/translation', ['jquery', 'require'], function ($, require) {
	      function Translation(dict) {
	        this.dict = dict || {};
	      }

	      Translation.prototype.all = function () {
	        return this.dict;
	      };

	      Translation.prototype.get = function (key) {
	        return this.dict[key];
	      };

	      Translation.prototype.extend = function (translation) {
	        this.dict = $.extend({}, translation.all(), this.dict);
	      };

	      // Static functions

	      Translation._cache = {};

	      Translation.loadPath = function (path) {
	        if (!(path in Translation._cache)) {
	          var translations = require(path);

	          Translation._cache[path] = translations;
	        }

	        return new Translation(Translation._cache[path]);
	      };

	      return Translation;
	    });

	    S2.define('select2/diacritics', [], function () {
	      var diacritics = {
	        '\u24B6': 'A',
	        '\uFF21': 'A',
	        '\xC0': 'A',
	        '\xC1': 'A',
	        '\xC2': 'A',
	        '\u1EA6': 'A',
	        '\u1EA4': 'A',
	        '\u1EAA': 'A',
	        '\u1EA8': 'A',
	        '\xC3': 'A',
	        '\u0100': 'A',
	        '\u0102': 'A',
	        '\u1EB0': 'A',
	        '\u1EAE': 'A',
	        '\u1EB4': 'A',
	        '\u1EB2': 'A',
	        '\u0226': 'A',
	        '\u01E0': 'A',
	        '\xC4': 'A',
	        '\u01DE': 'A',
	        '\u1EA2': 'A',
	        '\xC5': 'A',
	        '\u01FA': 'A',
	        '\u01CD': 'A',
	        '\u0200': 'A',
	        '\u0202': 'A',
	        '\u1EA0': 'A',
	        '\u1EAC': 'A',
	        '\u1EB6': 'A',
	        '\u1E00': 'A',
	        '\u0104': 'A',
	        '\u023A': 'A',
	        '\u2C6F': 'A',
	        '\uA732': 'AA',
	        '\xC6': 'AE',
	        '\u01FC': 'AE',
	        '\u01E2': 'AE',
	        '\uA734': 'AO',
	        '\uA736': 'AU',
	        '\uA738': 'AV',
	        '\uA73A': 'AV',
	        '\uA73C': 'AY',
	        '\u24B7': 'B',
	        '\uFF22': 'B',
	        '\u1E02': 'B',
	        '\u1E04': 'B',
	        '\u1E06': 'B',
	        '\u0243': 'B',
	        '\u0182': 'B',
	        '\u0181': 'B',
	        '\u24B8': 'C',
	        '\uFF23': 'C',
	        '\u0106': 'C',
	        '\u0108': 'C',
	        '\u010A': 'C',
	        '\u010C': 'C',
	        '\xC7': 'C',
	        '\u1E08': 'C',
	        '\u0187': 'C',
	        '\u023B': 'C',
	        '\uA73E': 'C',
	        '\u24B9': 'D',
	        '\uFF24': 'D',
	        '\u1E0A': 'D',
	        '\u010E': 'D',
	        '\u1E0C': 'D',
	        '\u1E10': 'D',
	        '\u1E12': 'D',
	        '\u1E0E': 'D',
	        '\u0110': 'D',
	        '\u018B': 'D',
	        '\u018A': 'D',
	        '\u0189': 'D',
	        '\uA779': 'D',
	        '\u01F1': 'DZ',
	        '\u01C4': 'DZ',
	        '\u01F2': 'Dz',
	        '\u01C5': 'Dz',
	        '\u24BA': 'E',
	        '\uFF25': 'E',
	        '\xC8': 'E',
	        '\xC9': 'E',
	        '\xCA': 'E',
	        '\u1EC0': 'E',
	        '\u1EBE': 'E',
	        '\u1EC4': 'E',
	        '\u1EC2': 'E',
	        '\u1EBC': 'E',
	        '\u0112': 'E',
	        '\u1E14': 'E',
	        '\u1E16': 'E',
	        '\u0114': 'E',
	        '\u0116': 'E',
	        '\xCB': 'E',
	        '\u1EBA': 'E',
	        '\u011A': 'E',
	        '\u0204': 'E',
	        '\u0206': 'E',
	        '\u1EB8': 'E',
	        '\u1EC6': 'E',
	        '\u0228': 'E',
	        '\u1E1C': 'E',
	        '\u0118': 'E',
	        '\u1E18': 'E',
	        '\u1E1A': 'E',
	        '\u0190': 'E',
	        '\u018E': 'E',
	        '\u24BB': 'F',
	        '\uFF26': 'F',
	        '\u1E1E': 'F',
	        '\u0191': 'F',
	        '\uA77B': 'F',
	        '\u24BC': 'G',
	        '\uFF27': 'G',
	        '\u01F4': 'G',
	        '\u011C': 'G',
	        '\u1E20': 'G',
	        '\u011E': 'G',
	        '\u0120': 'G',
	        '\u01E6': 'G',
	        '\u0122': 'G',
	        '\u01E4': 'G',
	        '\u0193': 'G',
	        '\uA7A0': 'G',
	        '\uA77D': 'G',
	        '\uA77E': 'G',
	        '\u24BD': 'H',
	        '\uFF28': 'H',
	        '\u0124': 'H',
	        '\u1E22': 'H',
	        '\u1E26': 'H',
	        '\u021E': 'H',
	        '\u1E24': 'H',
	        '\u1E28': 'H',
	        '\u1E2A': 'H',
	        '\u0126': 'H',
	        '\u2C67': 'H',
	        '\u2C75': 'H',
	        '\uA78D': 'H',
	        '\u24BE': 'I',
	        '\uFF29': 'I',
	        '\xCC': 'I',
	        '\xCD': 'I',
	        '\xCE': 'I',
	        '\u0128': 'I',
	        '\u012A': 'I',
	        '\u012C': 'I',
	        '\u0130': 'I',
	        '\xCF': 'I',
	        '\u1E2E': 'I',
	        '\u1EC8': 'I',
	        '\u01CF': 'I',
	        '\u0208': 'I',
	        '\u020A': 'I',
	        '\u1ECA': 'I',
	        '\u012E': 'I',
	        '\u1E2C': 'I',
	        '\u0197': 'I',
	        '\u24BF': 'J',
	        '\uFF2A': 'J',
	        '\u0134': 'J',
	        '\u0248': 'J',
	        '\u24C0': 'K',
	        '\uFF2B': 'K',
	        '\u1E30': 'K',
	        '\u01E8': 'K',
	        '\u1E32': 'K',
	        '\u0136': 'K',
	        '\u1E34': 'K',
	        '\u0198': 'K',
	        '\u2C69': 'K',
	        '\uA740': 'K',
	        '\uA742': 'K',
	        '\uA744': 'K',
	        '\uA7A2': 'K',
	        '\u24C1': 'L',
	        '\uFF2C': 'L',
	        '\u013F': 'L',
	        '\u0139': 'L',
	        '\u013D': 'L',
	        '\u1E36': 'L',
	        '\u1E38': 'L',
	        '\u013B': 'L',
	        '\u1E3C': 'L',
	        '\u1E3A': 'L',
	        '\u0141': 'L',
	        '\u023D': 'L',
	        '\u2C62': 'L',
	        '\u2C60': 'L',
	        '\uA748': 'L',
	        '\uA746': 'L',
	        '\uA780': 'L',
	        '\u01C7': 'LJ',
	        '\u01C8': 'Lj',
	        '\u24C2': 'M',
	        '\uFF2D': 'M',
	        '\u1E3E': 'M',
	        '\u1E40': 'M',
	        '\u1E42': 'M',
	        '\u2C6E': 'M',
	        '\u019C': 'M',
	        '\u24C3': 'N',
	        '\uFF2E': 'N',
	        '\u01F8': 'N',
	        '\u0143': 'N',
	        '\xD1': 'N',
	        '\u1E44': 'N',
	        '\u0147': 'N',
	        '\u1E46': 'N',
	        '\u0145': 'N',
	        '\u1E4A': 'N',
	        '\u1E48': 'N',
	        '\u0220': 'N',
	        '\u019D': 'N',
	        '\uA790': 'N',
	        '\uA7A4': 'N',
	        '\u01CA': 'NJ',
	        '\u01CB': 'Nj',
	        '\u24C4': 'O',
	        '\uFF2F': 'O',
	        '\xD2': 'O',
	        '\xD3': 'O',
	        '\xD4': 'O',
	        '\u1ED2': 'O',
	        '\u1ED0': 'O',
	        '\u1ED6': 'O',
	        '\u1ED4': 'O',
	        '\xD5': 'O',
	        '\u1E4C': 'O',
	        '\u022C': 'O',
	        '\u1E4E': 'O',
	        '\u014C': 'O',
	        '\u1E50': 'O',
	        '\u1E52': 'O',
	        '\u014E': 'O',
	        '\u022E': 'O',
	        '\u0230': 'O',
	        '\xD6': 'O',
	        '\u022A': 'O',
	        '\u1ECE': 'O',
	        '\u0150': 'O',
	        '\u01D1': 'O',
	        '\u020C': 'O',
	        '\u020E': 'O',
	        '\u01A0': 'O',
	        '\u1EDC': 'O',
	        '\u1EDA': 'O',
	        '\u1EE0': 'O',
	        '\u1EDE': 'O',
	        '\u1EE2': 'O',
	        '\u1ECC': 'O',
	        '\u1ED8': 'O',
	        '\u01EA': 'O',
	        '\u01EC': 'O',
	        '\xD8': 'O',
	        '\u01FE': 'O',
	        '\u0186': 'O',
	        '\u019F': 'O',
	        '\uA74A': 'O',
	        '\uA74C': 'O',
	        '\u01A2': 'OI',
	        '\uA74E': 'OO',
	        '\u0222': 'OU',
	        '\u24C5': 'P',
	        '\uFF30': 'P',
	        '\u1E54': 'P',
	        '\u1E56': 'P',
	        '\u01A4': 'P',
	        '\u2C63': 'P',
	        '\uA750': 'P',
	        '\uA752': 'P',
	        '\uA754': 'P',
	        '\u24C6': 'Q',
	        '\uFF31': 'Q',
	        '\uA756': 'Q',
	        '\uA758': 'Q',
	        '\u024A': 'Q',
	        '\u24C7': 'R',
	        '\uFF32': 'R',
	        '\u0154': 'R',
	        '\u1E58': 'R',
	        '\u0158': 'R',
	        '\u0210': 'R',
	        '\u0212': 'R',
	        '\u1E5A': 'R',
	        '\u1E5C': 'R',
	        '\u0156': 'R',
	        '\u1E5E': 'R',
	        '\u024C': 'R',
	        '\u2C64': 'R',
	        '\uA75A': 'R',
	        '\uA7A6': 'R',
	        '\uA782': 'R',
	        '\u24C8': 'S',
	        '\uFF33': 'S',
	        '\u1E9E': 'S',
	        '\u015A': 'S',
	        '\u1E64': 'S',
	        '\u015C': 'S',
	        '\u1E60': 'S',
	        '\u0160': 'S',
	        '\u1E66': 'S',
	        '\u1E62': 'S',
	        '\u1E68': 'S',
	        '\u0218': 'S',
	        '\u015E': 'S',
	        '\u2C7E': 'S',
	        '\uA7A8': 'S',
	        '\uA784': 'S',
	        '\u24C9': 'T',
	        '\uFF34': 'T',
	        '\u1E6A': 'T',
	        '\u0164': 'T',
	        '\u1E6C': 'T',
	        '\u021A': 'T',
	        '\u0162': 'T',
	        '\u1E70': 'T',
	        '\u1E6E': 'T',
	        '\u0166': 'T',
	        '\u01AC': 'T',
	        '\u01AE': 'T',
	        '\u023E': 'T',
	        '\uA786': 'T',
	        '\uA728': 'TZ',
	        '\u24CA': 'U',
	        '\uFF35': 'U',
	        '\xD9': 'U',
	        '\xDA': 'U',
	        '\xDB': 'U',
	        '\u0168': 'U',
	        '\u1E78': 'U',
	        '\u016A': 'U',
	        '\u1E7A': 'U',
	        '\u016C': 'U',
	        '\xDC': 'U',
	        '\u01DB': 'U',
	        '\u01D7': 'U',
	        '\u01D5': 'U',
	        '\u01D9': 'U',
	        '\u1EE6': 'U',
	        '\u016E': 'U',
	        '\u0170': 'U',
	        '\u01D3': 'U',
	        '\u0214': 'U',
	        '\u0216': 'U',
	        '\u01AF': 'U',
	        '\u1EEA': 'U',
	        '\u1EE8': 'U',
	        '\u1EEE': 'U',
	        '\u1EEC': 'U',
	        '\u1EF0': 'U',
	        '\u1EE4': 'U',
	        '\u1E72': 'U',
	        '\u0172': 'U',
	        '\u1E76': 'U',
	        '\u1E74': 'U',
	        '\u0244': 'U',
	        '\u24CB': 'V',
	        '\uFF36': 'V',
	        '\u1E7C': 'V',
	        '\u1E7E': 'V',
	        '\u01B2': 'V',
	        '\uA75E': 'V',
	        '\u0245': 'V',
	        '\uA760': 'VY',
	        '\u24CC': 'W',
	        '\uFF37': 'W',
	        '\u1E80': 'W',
	        '\u1E82': 'W',
	        '\u0174': 'W',
	        '\u1E86': 'W',
	        '\u1E84': 'W',
	        '\u1E88': 'W',
	        '\u2C72': 'W',
	        '\u24CD': 'X',
	        '\uFF38': 'X',
	        '\u1E8A': 'X',
	        '\u1E8C': 'X',
	        '\u24CE': 'Y',
	        '\uFF39': 'Y',
	        '\u1EF2': 'Y',
	        '\xDD': 'Y',
	        '\u0176': 'Y',
	        '\u1EF8': 'Y',
	        '\u0232': 'Y',
	        '\u1E8E': 'Y',
	        '\u0178': 'Y',
	        '\u1EF6': 'Y',
	        '\u1EF4': 'Y',
	        '\u01B3': 'Y',
	        '\u024E': 'Y',
	        '\u1EFE': 'Y',
	        '\u24CF': 'Z',
	        '\uFF3A': 'Z',
	        '\u0179': 'Z',
	        '\u1E90': 'Z',
	        '\u017B': 'Z',
	        '\u017D': 'Z',
	        '\u1E92': 'Z',
	        '\u1E94': 'Z',
	        '\u01B5': 'Z',
	        '\u0224': 'Z',
	        '\u2C7F': 'Z',
	        '\u2C6B': 'Z',
	        '\uA762': 'Z',
	        '\u24D0': 'a',
	        '\uFF41': 'a',
	        '\u1E9A': 'a',
	        '\xE0': 'a',
	        '\xE1': 'a',
	        '\xE2': 'a',
	        '\u1EA7': 'a',
	        '\u1EA5': 'a',
	        '\u1EAB': 'a',
	        '\u1EA9': 'a',
	        '\xE3': 'a',
	        '\u0101': 'a',
	        '\u0103': 'a',
	        '\u1EB1': 'a',
	        '\u1EAF': 'a',
	        '\u1EB5': 'a',
	        '\u1EB3': 'a',
	        '\u0227': 'a',
	        '\u01E1': 'a',
	        '\xE4': 'a',
	        '\u01DF': 'a',
	        '\u1EA3': 'a',
	        '\xE5': 'a',
	        '\u01FB': 'a',
	        '\u01CE': 'a',
	        '\u0201': 'a',
	        '\u0203': 'a',
	        '\u1EA1': 'a',
	        '\u1EAD': 'a',
	        '\u1EB7': 'a',
	        '\u1E01': 'a',
	        '\u0105': 'a',
	        '\u2C65': 'a',
	        '\u0250': 'a',
	        '\uA733': 'aa',
	        '\xE6': 'ae',
	        '\u01FD': 'ae',
	        '\u01E3': 'ae',
	        '\uA735': 'ao',
	        '\uA737': 'au',
	        '\uA739': 'av',
	        '\uA73B': 'av',
	        '\uA73D': 'ay',
	        '\u24D1': 'b',
	        '\uFF42': 'b',
	        '\u1E03': 'b',
	        '\u1E05': 'b',
	        '\u1E07': 'b',
	        '\u0180': 'b',
	        '\u0183': 'b',
	        '\u0253': 'b',
	        '\u24D2': 'c',
	        '\uFF43': 'c',
	        '\u0107': 'c',
	        '\u0109': 'c',
	        '\u010B': 'c',
	        '\u010D': 'c',
	        '\xE7': 'c',
	        '\u1E09': 'c',
	        '\u0188': 'c',
	        '\u023C': 'c',
	        '\uA73F': 'c',
	        '\u2184': 'c',
	        '\u24D3': 'd',
	        '\uFF44': 'd',
	        '\u1E0B': 'd',
	        '\u010F': 'd',
	        '\u1E0D': 'd',
	        '\u1E11': 'd',
	        '\u1E13': 'd',
	        '\u1E0F': 'd',
	        '\u0111': 'd',
	        '\u018C': 'd',
	        '\u0256': 'd',
	        '\u0257': 'd',
	        '\uA77A': 'd',
	        '\u01F3': 'dz',
	        '\u01C6': 'dz',
	        '\u24D4': 'e',
	        '\uFF45': 'e',
	        '\xE8': 'e',
	        '\xE9': 'e',
	        '\xEA': 'e',
	        '\u1EC1': 'e',
	        '\u1EBF': 'e',
	        '\u1EC5': 'e',
	        '\u1EC3': 'e',
	        '\u1EBD': 'e',
	        '\u0113': 'e',
	        '\u1E15': 'e',
	        '\u1E17': 'e',
	        '\u0115': 'e',
	        '\u0117': 'e',
	        '\xEB': 'e',
	        '\u1EBB': 'e',
	        '\u011B': 'e',
	        '\u0205': 'e',
	        '\u0207': 'e',
	        '\u1EB9': 'e',
	        '\u1EC7': 'e',
	        '\u0229': 'e',
	        '\u1E1D': 'e',
	        '\u0119': 'e',
	        '\u1E19': 'e',
	        '\u1E1B': 'e',
	        '\u0247': 'e',
	        '\u025B': 'e',
	        '\u01DD': 'e',
	        '\u24D5': 'f',
	        '\uFF46': 'f',
	        '\u1E1F': 'f',
	        '\u0192': 'f',
	        '\uA77C': 'f',
	        '\u24D6': 'g',
	        '\uFF47': 'g',
	        '\u01F5': 'g',
	        '\u011D': 'g',
	        '\u1E21': 'g',
	        '\u011F': 'g',
	        '\u0121': 'g',
	        '\u01E7': 'g',
	        '\u0123': 'g',
	        '\u01E5': 'g',
	        '\u0260': 'g',
	        '\uA7A1': 'g',
	        '\u1D79': 'g',
	        '\uA77F': 'g',
	        '\u24D7': 'h',
	        '\uFF48': 'h',
	        '\u0125': 'h',
	        '\u1E23': 'h',
	        '\u1E27': 'h',
	        '\u021F': 'h',
	        '\u1E25': 'h',
	        '\u1E29': 'h',
	        '\u1E2B': 'h',
	        '\u1E96': 'h',
	        '\u0127': 'h',
	        '\u2C68': 'h',
	        '\u2C76': 'h',
	        '\u0265': 'h',
	        '\u0195': 'hv',
	        '\u24D8': 'i',
	        '\uFF49': 'i',
	        '\xEC': 'i',
	        '\xED': 'i',
	        '\xEE': 'i',
	        '\u0129': 'i',
	        '\u012B': 'i',
	        '\u012D': 'i',
	        '\xEF': 'i',
	        '\u1E2F': 'i',
	        '\u1EC9': 'i',
	        '\u01D0': 'i',
	        '\u0209': 'i',
	        '\u020B': 'i',
	        '\u1ECB': 'i',
	        '\u012F': 'i',
	        '\u1E2D': 'i',
	        '\u0268': 'i',
	        '\u0131': 'i',
	        '\u24D9': 'j',
	        '\uFF4A': 'j',
	        '\u0135': 'j',
	        '\u01F0': 'j',
	        '\u0249': 'j',
	        '\u24DA': 'k',
	        '\uFF4B': 'k',
	        '\u1E31': 'k',
	        '\u01E9': 'k',
	        '\u1E33': 'k',
	        '\u0137': 'k',
	        '\u1E35': 'k',
	        '\u0199': 'k',
	        '\u2C6A': 'k',
	        '\uA741': 'k',
	        '\uA743': 'k',
	        '\uA745': 'k',
	        '\uA7A3': 'k',
	        '\u24DB': 'l',
	        '\uFF4C': 'l',
	        '\u0140': 'l',
	        '\u013A': 'l',
	        '\u013E': 'l',
	        '\u1E37': 'l',
	        '\u1E39': 'l',
	        '\u013C': 'l',
	        '\u1E3D': 'l',
	        '\u1E3B': 'l',
	        '\u017F': 'l',
	        '\u0142': 'l',
	        '\u019A': 'l',
	        '\u026B': 'l',
	        '\u2C61': 'l',
	        '\uA749': 'l',
	        '\uA781': 'l',
	        '\uA747': 'l',
	        '\u01C9': 'lj',
	        '\u24DC': 'm',
	        '\uFF4D': 'm',
	        '\u1E3F': 'm',
	        '\u1E41': 'm',
	        '\u1E43': 'm',
	        '\u0271': 'm',
	        '\u026F': 'm',
	        '\u24DD': 'n',
	        '\uFF4E': 'n',
	        '\u01F9': 'n',
	        '\u0144': 'n',
	        '\xF1': 'n',
	        '\u1E45': 'n',
	        '\u0148': 'n',
	        '\u1E47': 'n',
	        '\u0146': 'n',
	        '\u1E4B': 'n',
	        '\u1E49': 'n',
	        '\u019E': 'n',
	        '\u0272': 'n',
	        '\u0149': 'n',
	        '\uA791': 'n',
	        '\uA7A5': 'n',
	        '\u01CC': 'nj',
	        '\u24DE': 'o',
	        '\uFF4F': 'o',
	        '\xF2': 'o',
	        '\xF3': 'o',
	        '\xF4': 'o',
	        '\u1ED3': 'o',
	        '\u1ED1': 'o',
	        '\u1ED7': 'o',
	        '\u1ED5': 'o',
	        '\xF5': 'o',
	        '\u1E4D': 'o',
	        '\u022D': 'o',
	        '\u1E4F': 'o',
	        '\u014D': 'o',
	        '\u1E51': 'o',
	        '\u1E53': 'o',
	        '\u014F': 'o',
	        '\u022F': 'o',
	        '\u0231': 'o',
	        '\xF6': 'o',
	        '\u022B': 'o',
	        '\u1ECF': 'o',
	        '\u0151': 'o',
	        '\u01D2': 'o',
	        '\u020D': 'o',
	        '\u020F': 'o',
	        '\u01A1': 'o',
	        '\u1EDD': 'o',
	        '\u1EDB': 'o',
	        '\u1EE1': 'o',
	        '\u1EDF': 'o',
	        '\u1EE3': 'o',
	        '\u1ECD': 'o',
	        '\u1ED9': 'o',
	        '\u01EB': 'o',
	        '\u01ED': 'o',
	        '\xF8': 'o',
	        '\u01FF': 'o',
	        '\u0254': 'o',
	        '\uA74B': 'o',
	        '\uA74D': 'o',
	        '\u0275': 'o',
	        '\u01A3': 'oi',
	        '\u0223': 'ou',
	        '\uA74F': 'oo',
	        '\u24DF': 'p',
	        '\uFF50': 'p',
	        '\u1E55': 'p',
	        '\u1E57': 'p',
	        '\u01A5': 'p',
	        '\u1D7D': 'p',
	        '\uA751': 'p',
	        '\uA753': 'p',
	        '\uA755': 'p',
	        '\u24E0': 'q',
	        '\uFF51': 'q',
	        '\u024B': 'q',
	        '\uA757': 'q',
	        '\uA759': 'q',
	        '\u24E1': 'r',
	        '\uFF52': 'r',
	        '\u0155': 'r',
	        '\u1E59': 'r',
	        '\u0159': 'r',
	        '\u0211': 'r',
	        '\u0213': 'r',
	        '\u1E5B': 'r',
	        '\u1E5D': 'r',
	        '\u0157': 'r',
	        '\u1E5F': 'r',
	        '\u024D': 'r',
	        '\u027D': 'r',
	        '\uA75B': 'r',
	        '\uA7A7': 'r',
	        '\uA783': 'r',
	        '\u24E2': 's',
	        '\uFF53': 's',
	        '\xDF': 's',
	        '\u015B': 's',
	        '\u1E65': 's',
	        '\u015D': 's',
	        '\u1E61': 's',
	        '\u0161': 's',
	        '\u1E67': 's',
	        '\u1E63': 's',
	        '\u1E69': 's',
	        '\u0219': 's',
	        '\u015F': 's',
	        '\u023F': 's',
	        '\uA7A9': 's',
	        '\uA785': 's',
	        '\u1E9B': 's',
	        '\u24E3': 't',
	        '\uFF54': 't',
	        '\u1E6B': 't',
	        '\u1E97': 't',
	        '\u0165': 't',
	        '\u1E6D': 't',
	        '\u021B': 't',
	        '\u0163': 't',
	        '\u1E71': 't',
	        '\u1E6F': 't',
	        '\u0167': 't',
	        '\u01AD': 't',
	        '\u0288': 't',
	        '\u2C66': 't',
	        '\uA787': 't',
	        '\uA729': 'tz',
	        '\u24E4': 'u',
	        '\uFF55': 'u',
	        '\xF9': 'u',
	        '\xFA': 'u',
	        '\xFB': 'u',
	        '\u0169': 'u',
	        '\u1E79': 'u',
	        '\u016B': 'u',
	        '\u1E7B': 'u',
	        '\u016D': 'u',
	        '\xFC': 'u',
	        '\u01DC': 'u',
	        '\u01D8': 'u',
	        '\u01D6': 'u',
	        '\u01DA': 'u',
	        '\u1EE7': 'u',
	        '\u016F': 'u',
	        '\u0171': 'u',
	        '\u01D4': 'u',
	        '\u0215': 'u',
	        '\u0217': 'u',
	        '\u01B0': 'u',
	        '\u1EEB': 'u',
	        '\u1EE9': 'u',
	        '\u1EEF': 'u',
	        '\u1EED': 'u',
	        '\u1EF1': 'u',
	        '\u1EE5': 'u',
	        '\u1E73': 'u',
	        '\u0173': 'u',
	        '\u1E77': 'u',
	        '\u1E75': 'u',
	        '\u0289': 'u',
	        '\u24E5': 'v',
	        '\uFF56': 'v',
	        '\u1E7D': 'v',
	        '\u1E7F': 'v',
	        '\u028B': 'v',
	        '\uA75F': 'v',
	        '\u028C': 'v',
	        '\uA761': 'vy',
	        '\u24E6': 'w',
	        '\uFF57': 'w',
	        '\u1E81': 'w',
	        '\u1E83': 'w',
	        '\u0175': 'w',
	        '\u1E87': 'w',
	        '\u1E85': 'w',
	        '\u1E98': 'w',
	        '\u1E89': 'w',
	        '\u2C73': 'w',
	        '\u24E7': 'x',
	        '\uFF58': 'x',
	        '\u1E8B': 'x',
	        '\u1E8D': 'x',
	        '\u24E8': 'y',
	        '\uFF59': 'y',
	        '\u1EF3': 'y',
	        '\xFD': 'y',
	        '\u0177': 'y',
	        '\u1EF9': 'y',
	        '\u0233': 'y',
	        '\u1E8F': 'y',
	        '\xFF': 'y',
	        '\u1EF7': 'y',
	        '\u1E99': 'y',
	        '\u1EF5': 'y',
	        '\u01B4': 'y',
	        '\u024F': 'y',
	        '\u1EFF': 'y',
	        '\u24E9': 'z',
	        '\uFF5A': 'z',
	        '\u017A': 'z',
	        '\u1E91': 'z',
	        '\u017C': 'z',
	        '\u017E': 'z',
	        '\u1E93': 'z',
	        '\u1E95': 'z',
	        '\u01B6': 'z',
	        '\u0225': 'z',
	        '\u0240': 'z',
	        '\u2C6C': 'z',
	        '\uA763': 'z',
	        '\u0386': '\u0391',
	        '\u0388': '\u0395',
	        '\u0389': '\u0397',
	        '\u038A': '\u0399',
	        '\u03AA': '\u0399',
	        '\u038C': '\u039F',
	        '\u038E': '\u03A5',
	        '\u03AB': '\u03A5',
	        '\u038F': '\u03A9',
	        '\u03AC': '\u03B1',
	        '\u03AD': '\u03B5',
	        '\u03AE': '\u03B7',
	        '\u03AF': '\u03B9',
	        '\u03CA': '\u03B9',
	        '\u0390': '\u03B9',
	        '\u03CC': '\u03BF',
	        '\u03CD': '\u03C5',
	        '\u03CB': '\u03C5',
	        '\u03B0': '\u03C5',
	        '\u03C9': '\u03C9',
	        '\u03C2': '\u03C3'
	      };

	      return diacritics;
	    });

	    S2.define('select2/data/base', ['../utils'], function (Utils) {
	      function BaseAdapter($element, options) {
	        BaseAdapter.__super__.constructor.call(this);
	      }

	      Utils.Extend(BaseAdapter, Utils.Observable);

	      BaseAdapter.prototype.current = function (callback) {
	        throw new Error('The `current` method must be defined in child classes.');
	      };

	      BaseAdapter.prototype.query = function (params, callback) {
	        throw new Error('The `query` method must be defined in child classes.');
	      };

	      BaseAdapter.prototype.bind = function (container, $container) {
	        // Can be implemented in subclasses
	      };

	      BaseAdapter.prototype.destroy = function () {
	        // Can be implemented in subclasses
	      };

	      BaseAdapter.prototype.generateResultId = function (container, data) {
	        var id = container.id + '-result-';

	        id += Utils.generateChars(4);

	        if (data.id != null) {
	          id += '-' + data.id.toString();
	        } else {
	          id += '-' + Utils.generateChars(4);
	        }
	        return id;
	      };

	      return BaseAdapter;
	    });

	    S2.define('select2/data/select', ['./base', '../utils', 'jquery'], function (BaseAdapter, Utils, $) {
	      function SelectAdapter($element, options) {
	        this.$element = $element;
	        this.options = options;

	        SelectAdapter.__super__.constructor.call(this);
	      }

	      Utils.Extend(SelectAdapter, BaseAdapter);

	      SelectAdapter.prototype.current = function (callback) {
	        var data = [];
	        var self = this;

	        this.$element.find(':selected').each(function () {
	          var $option = $(this);

	          var option = self.item($option);

	          data.push(option);
	        });

	        callback(data);
	      };

	      SelectAdapter.prototype.select = function (data) {
	        var self = this;

	        data.selected = true;

	        // If data.element is a DOM node, use it instead
	        if ($(data.element).is('option')) {
	          data.element.selected = true;

	          this.$element.trigger('change');

	          return;
	        }

	        if (this.$element.prop('multiple')) {
	          this.current(function (currentData) {
	            var val = [];

	            data = [data];
	            data.push.apply(data, currentData);

	            for (var d = 0; d < data.length; d++) {
	              var id = data[d].id;

	              if ($.inArray(id, val) === -1) {
	                val.push(id);
	              }
	            }

	            self.$element.val(val);
	            self.$element.trigger('change');
	          });
	        } else {
	          var val = data.id;

	          this.$element.val(val);
	          this.$element.trigger('change');
	        }
	      };

	      SelectAdapter.prototype.unselect = function (data) {
	        var self = this;

	        if (!this.$element.prop('multiple')) {
	          return;
	        }

	        data.selected = false;

	        if ($(data.element).is('option')) {
	          data.element.selected = false;

	          this.$element.trigger('change');

	          return;
	        }

	        this.current(function (currentData) {
	          var val = [];

	          for (var d = 0; d < currentData.length; d++) {
	            var id = currentData[d].id;

	            if (id !== data.id && $.inArray(id, val) === -1) {
	              val.push(id);
	            }
	          }

	          self.$element.val(val);

	          self.$element.trigger('change');
	        });
	      };

	      SelectAdapter.prototype.bind = function (container, $container) {
	        var self = this;

	        this.container = container;

	        container.on('select', function (params) {
	          self.select(params.data);
	        });

	        container.on('unselect', function (params) {
	          self.unselect(params.data);
	        });
	      };

	      SelectAdapter.prototype.destroy = function () {
	        // Remove anything added to child elements
	        this.$element.find('*').each(function () {
	          // Remove any custom data set by Select2
	          $.removeData(this, 'data');
	        });
	      };

	      SelectAdapter.prototype.query = function (params, callback) {
	        var data = [];
	        var self = this;

	        var $options = this.$element.children();

	        $options.each(function () {
	          var $option = $(this);

	          if (!$option.is('option') && !$option.is('optgroup')) {
	            return;
	          }

	          var option = self.item($option);

	          var matches = self.matches(params, option);

	          if (matches !== null) {
	            data.push(matches);
	          }
	        });

	        callback({
	          results: data
	        });
	      };

	      SelectAdapter.prototype.addOptions = function ($options) {
	        Utils.appendMany(this.$element, $options);
	      };

	      SelectAdapter.prototype.option = function (data) {
	        var option;

	        if (data.children) {
	          option = document.createElement('optgroup');
	          option.label = data.text;
	        } else {
	          option = document.createElement('option');

	          if (option.textContent !== undefined) {
	            option.textContent = data.text;
	          } else {
	            option.innerText = data.text;
	          }
	        }

	        if (data.id) {
	          option.value = data.id;
	        }

	        if (data.disabled) {
	          option.disabled = true;
	        }

	        if (data.selected) {
	          option.selected = true;
	        }

	        if (data.title) {
	          option.title = data.title;
	        }

	        var $option = $(option);

	        var normalizedData = this._normalizeItem(data);
	        normalizedData.element = option;

	        // Override the option's data with the combined data
	        $.data(option, 'data', normalizedData);

	        return $option;
	      };

	      SelectAdapter.prototype.item = function ($option) {
	        var data = {};

	        data = $.data($option[0], 'data');

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

	        if ($option.is('option')) {
	          data = {
	            id: $option.val(),
	            text: $option.text(),
	            disabled: $option.prop('disabled'),
	            selected: $option.prop('selected'),
	            title: $option.prop('title')
	          };
	        } else if ($option.is('optgroup')) {
	          data = {
	            text: $option.prop('label'),
	            children: [],
	            title: $option.prop('title')
	          };

	          var $children = $option.children('option');
	          var children = [];

	          for (var c = 0; c < $children.length; c++) {
	            var $child = $($children[c]);

	            var child = this.item($child);

	            children.push(child);
	          }

	          data.children = children;
	        }

	        data = this._normalizeItem(data);
	        data.element = $option[0];

	        $.data($option[0], 'data', data);

	        return data;
	      };

	      SelectAdapter.prototype._normalizeItem = function (item) {
	        if (!$.isPlainObject(item)) {
	          item = {
	            id: item,
	            text: item
	          };
	        }

	        item = $.extend({}, {
	          text: ''
	        }, item);

	        var defaults = {
	          selected: false,
	          disabled: false
	        };

	        if (item.id != null) {
	          item.id = item.id.toString();
	        }

	        if (item.text != null) {
	          item.text = item.text.toString();
	        }

	        if (item._resultId == null && item.id && this.container != null) {
	          item._resultId = this.generateResultId(this.container, item);
	        }

	        return $.extend({}, defaults, item);
	      };

	      SelectAdapter.prototype.matches = function (params, data) {
	        var matcher = this.options.get('matcher');

	        return matcher(params, data);
	      };

	      return SelectAdapter;
	    });

	    S2.define('select2/data/array', ['./select', '../utils', 'jquery'], function (SelectAdapter, Utils, $) {
	      function ArrayAdapter($element, options) {
	        var data = options.get('data') || [];

	        ArrayAdapter.__super__.constructor.call(this, $element, options);

	        this.addOptions(this.convertToOptions(data));
	      }

	      Utils.Extend(ArrayAdapter, SelectAdapter);

	      ArrayAdapter.prototype.select = function (data) {
	        var $option = this.$element.find('option').filter(function (i, elm) {
	          return elm.value == data.id.toString();
	        });

	        if ($option.length === 0) {
	          $option = this.option(data);

	          this.addOptions($option);
	        }

	        ArrayAdapter.__super__.select.call(this, data);
	      };

	      ArrayAdapter.prototype.convertToOptions = function (data) {
	        var self = this;

	        var $existing = this.$element.find('option');
	        var existingIds = $existing.map(function () {
	          return self.item($(this)).id;
	        }).get();

	        var $options = [];

	        // Filter out all items except for the one passed in the argument
	        function onlyItem(item) {
	          return function () {
	            return $(this).val() == item.id;
	          };
	        }

	        for (var d = 0; d < data.length; d++) {
	          var item = this._normalizeItem(data[d]);

	          // Skip items which were pre-loaded, only merge the data
	          if ($.inArray(item.id, existingIds) >= 0) {
	            var $existingOption = $existing.filter(onlyItem(item));

	            var existingData = this.item($existingOption);
	            var newData = $.extend(true, {}, item, existingData);

	            var $newOption = this.option(newData);

	            $existingOption.replaceWith($newOption);

	            continue;
	          }

	          var $option = this.option(item);

	          if (item.children) {
	            var $children = this.convertToOptions(item.children);

	            Utils.appendMany($option, $children);
	          }

	          $options.push($option);
	        }

	        return $options;
	      };

	      return ArrayAdapter;
	    });

	    S2.define('select2/data/ajax', ['./array', '../utils', 'jquery'], function (ArrayAdapter, Utils, $) {
	      function AjaxAdapter($element, options) {
	        this.ajaxOptions = this._applyDefaults(options.get('ajax'));

	        if (this.ajaxOptions.processResults != null) {
	          this.processResults = this.ajaxOptions.processResults;
	        }

	        AjaxAdapter.__super__.constructor.call(this, $element, options);
	      }

	      Utils.Extend(AjaxAdapter, ArrayAdapter);

	      AjaxAdapter.prototype._applyDefaults = function (options) {
	        var defaults = {
	          data: function data(params) {
	            return $.extend({}, params, {
	              q: params.term
	            });
	          },
	          transport: function transport(params, success, failure) {
	            var $request = $.ajax(params);

	            $request.then(success);
	            $request.fail(failure);

	            return $request;
	          }
	        };

	        return $.extend({}, defaults, options, true);
	      };

	      AjaxAdapter.prototype.processResults = function (results) {
	        return results;
	      };

	      AjaxAdapter.prototype.query = function (params, callback) {
	        var matches = [];
	        var self = this;

	        if (this._request != null) {
	          // JSONP requests cannot always be aborted
	          if ($.isFunction(this._request.abort)) {
	            this._request.abort();
	          }

	          this._request = null;
	        }

	        var options = $.extend({
	          type: 'GET'
	        }, this.ajaxOptions);

	        if (typeof options.url === 'function') {
	          options.url = options.url.call(this.$element, params);
	        }

	        if (typeof options.data === 'function') {
	          options.data = options.data.call(this.$element, params);
	        }

	        function request() {
	          var $request = options.transport(options, function (data) {
	            var results = self.processResults(data, params);

	            if (self.options.get('debug') && window.console && console.error) {
	              // Check to make sure that the response included a `results` key.
	              if (!results || !results.results || !$.isArray(results.results)) {
	                console.error('Select2: The AJAX results did not return an array in the ' + '`results` key of the response.');
	              }
	            }

	            callback(results);
	          }, function () {
	            // Attempt to detect if a request was aborted
	            // Only works if the transport exposes a status property
	            if ($request.status && $request.status === '0') {
	              return;
	            }

	            self.trigger('results:message', {
	              message: 'errorLoading'
	            });
	          });

	          self._request = $request;
	        }

	        if (this.ajaxOptions.delay && params.term != null) {
	          if (this._queryTimeout) {
	            window.clearTimeout(this._queryTimeout);
	          }

	          this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
	        } else {
	          request();
	        }
	      };

	      return AjaxAdapter;
	    });

	    S2.define('select2/data/tags', ['jquery'], function ($) {
	      function Tags(decorated, $element, options) {
	        var tags = options.get('tags');

	        var createTag = options.get('createTag');

	        if (createTag !== undefined) {
	          this.createTag = createTag;
	        }

	        var insertTag = options.get('insertTag');

	        if (insertTag !== undefined) {
	          this.insertTag = insertTag;
	        }

	        decorated.call(this, $element, options);

	        if ($.isArray(tags)) {
	          for (var t = 0; t < tags.length; t++) {
	            var tag = tags[t];
	            var item = this._normalizeItem(tag);

	            var $option = this.option(item);

	            this.$element.append($option);
	          }
	        }
	      }

	      Tags.prototype.query = function (decorated, params, callback) {
	        var self = this;

	        this._removeOldTags();

	        if (params.term == null || params.page != null) {
	          decorated.call(this, params, callback);
	          return;
	        }

	        function wrapper(obj, child) {
	          var data = obj.results;

	          for (var i = 0; i < data.length; i++) {
	            var option = data[i];

	            var checkChildren = option.children != null && !wrapper({
	              results: option.children
	            }, true);

	            var checkText = option.text === params.term;

	            if (checkText || checkChildren) {
	              if (child) {
	                return false;
	              }

	              obj.data = data;
	              callback(obj);

	              return;
	            }
	          }

	          if (child) {
	            return true;
	          }

	          var tag = self.createTag(params);

	          if (tag != null) {
	            var $option = self.option(tag);
	            $option.attr('data-select2-tag', true);

	            self.addOptions([$option]);

	            self.insertTag(data, tag);
	          }

	          obj.results = data;

	          callback(obj);
	        }

	        decorated.call(this, params, wrapper);
	      };

	      Tags.prototype.createTag = function (decorated, params) {
	        var term = $.trim(params.term);

	        if (term === '') {
	          return null;
	        }

	        return {
	          id: term,
	          text: term
	        };
	      };

	      Tags.prototype.insertTag = function (_, data, tag) {
	        data.unshift(tag);
	      };

	      Tags.prototype._removeOldTags = function (_) {
	        var tag = this._lastTag;

	        var $options = this.$element.find('option[data-select2-tag]');

	        $options.each(function () {
	          if (this.selected) {
	            return;
	          }

	          $(this).remove();
	        });
	      };

	      return Tags;
	    });

	    S2.define('select2/data/tokenizer', ['jquery'], function ($) {
	      function Tokenizer(decorated, $element, options) {
	        var tokenizer = options.get('tokenizer');

	        if (tokenizer !== undefined) {
	          this.tokenizer = tokenizer;
	        }

	        decorated.call(this, $element, options);
	      }

	      Tokenizer.prototype.bind = function (decorated, container, $container) {
	        decorated.call(this, container, $container);

	        this.$search = container.dropdown.$search || container.selection.$search || $container.find('.select2-search__field');
	      };

	      Tokenizer.prototype.query = function (decorated, params, callback) {
	        var self = this;

	        function createAndSelect(data) {
	          // Normalize the data object so we can use it for checks
	          var item = self._normalizeItem(data);

	          // Check if the data object already exists as a tag
	          // Select it if it doesn't
	          var $existingOptions = self.$element.find('option').filter(function () {
	            return $(this).val() === item.id;
	          });

	          // If an existing option wasn't found for it, create the option
	          if (!$existingOptions.length) {
	            var $option = self.option(item);
	            $option.attr('data-select2-tag', true);

	            self._removeOldTags();
	            self.addOptions([$option]);
	          }

	          // Select the item, now that we know there is an option for it
	          select(item);
	        }

	        function select(data) {
	          self.trigger('select', {
	            data: data
	          });
	        }

	        params.term = params.term || '';

	        var tokenData = this.tokenizer(params, this.options, createAndSelect);

	        if (tokenData.term !== params.term) {
	          // Replace the search term if we have the search box
	          if (this.$search.length) {
	            this.$search.val(tokenData.term);
	            this.$search.focus();
	          }

	          params.term = tokenData.term;
	        }

	        decorated.call(this, params, callback);
	      };

	      Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
	        var separators = options.get('tokenSeparators') || [];
	        var term = params.term;
	        var i = 0;

	        var createTag = this.createTag || function (params) {
	          return {
	            id: params.term,
	            text: params.term
	          };
	        };

	        while (i < term.length) {
	          var termChar = term[i];

	          if ($.inArray(termChar, separators) === -1) {
	            i++;

	            continue;
	          }

	          var part = term.substr(0, i);
	          var partParams = $.extend({}, params, {
	            term: part
	          });

	          var data = createTag(partParams);

	          if (data == null) {
	            i++;
	            continue;
	          }

	          callback(data);

	          // Reset the term to not include the tokenized portion
	          term = term.substr(i + 1) || '';
	          i = 0;
	        }

	        return {
	          term: term
	        };
	      };

	      return Tokenizer;
	    });

	    S2.define('select2/data/minimumInputLength', [], function () {
	      function MinimumInputLength(decorated, $e, options) {
	        this.minimumInputLength = options.get('minimumInputLength');

	        decorated.call(this, $e, options);
	      }

	      MinimumInputLength.prototype.query = function (decorated, params, callback) {
	        params.term = params.term || '';

	        if (params.term.length < this.minimumInputLength) {
	          this.trigger('results:message', {
	            message: 'inputTooShort',
	            args: {
	              minimum: this.minimumInputLength,
	              input: params.term,
	              params: params
	            }
	          });

	          return;
	        }

	        decorated.call(this, params, callback);
	      };

	      return MinimumInputLength;
	    });

	    S2.define('select2/data/maximumInputLength', [], function () {
	      function MaximumInputLength(decorated, $e, options) {
	        this.maximumInputLength = options.get('maximumInputLength');

	        decorated.call(this, $e, options);
	      }

	      MaximumInputLength.prototype.query = function (decorated, params, callback) {
	        params.term = params.term || '';

	        if (this.maximumInputLength > 0 && params.term.length > this.maximumInputLength) {
	          this.trigger('results:message', {
	            message: 'inputTooLong',
	            args: {
	              maximum: this.maximumInputLength,
	              input: params.term,
	              params: params
	            }
	          });

	          return;
	        }

	        decorated.call(this, params, callback);
	      };

	      return MaximumInputLength;
	    });

	    S2.define('select2/data/maximumSelectionLength', [], function () {
	      function MaximumSelectionLength(decorated, $e, options) {
	        this.maximumSelectionLength = options.get('maximumSelectionLength');

	        decorated.call(this, $e, options);
	      }

	      MaximumSelectionLength.prototype.query = function (decorated, params, callback) {
	        var self = this;

	        this.current(function (currentData) {
	          var count = currentData != null ? currentData.length : 0;
	          if (self.maximumSelectionLength > 0 && count >= self.maximumSelectionLength) {
	            self.trigger('results:message', {
	              message: 'maximumSelected',
	              args: {
	                maximum: self.maximumSelectionLength
	              }
	            });
	            return;
	          }
	          decorated.call(self, params, callback);
	        });
	      };

	      return MaximumSelectionLength;
	    });

	    S2.define('select2/dropdown', ['jquery', './utils'], function ($, Utils) {
	      function Dropdown($element, options) {
	        this.$element = $element;
	        this.options = options;

	        Dropdown.__super__.constructor.call(this);
	      }

	      Utils.Extend(Dropdown, Utils.Observable);

	      Dropdown.prototype.render = function () {
	        var $dropdown = $('<span class="select2-dropdown">' + '<span class="select2-results"></span>' + '</span>');

	        $dropdown.attr('dir', this.options.get('dir'));

	        this.$dropdown = $dropdown;

	        return $dropdown;
	      };

	      Dropdown.prototype.bind = function () {
	        // Should be implemented in subclasses
	      };

	      Dropdown.prototype.position = function ($dropdown, $container) {
	        // Should be implmented in subclasses
	      };

	      Dropdown.prototype.destroy = function () {
	        // Remove the dropdown from the DOM
	        this.$dropdown.remove();
	      };

	      return Dropdown;
	    });

	    S2.define('select2/dropdown/search', ['jquery', '../utils'], function ($, Utils) {
	      function Search() {}

	      Search.prototype.render = function (decorated) {
	        var $rendered = decorated.call(this);

	        var $search = $('<span class="select2-search select2-search--dropdown">' + '<input class="select2-search__field" type="search" tabindex="-1"' + ' autocomplete="off" autocorrect="off" autocapitalize="off"' + ' spellcheck="false" role="textbox" />' + '</span>');

	        this.$searchContainer = $search;
	        this.$search = $search.find('input');

	        $rendered.prepend($search);

	        return $rendered;
	      };

	      Search.prototype.bind = function (decorated, container, $container) {
	        var self = this;

	        decorated.call(this, container, $container);

	        this.$search.on('keydown', function (evt) {
	          self.trigger('keypress', evt);

	          self._keyUpPrevented = evt.isDefaultPrevented();
	        });

	        // Workaround for browsers which do not support the `input` event
	        // This will prevent double-triggering of events for browsers which support
	        // both the `keyup` and `input` events.
	        this.$search.on('input', function (evt) {
	          // Unbind the duplicated `keyup` event
	          $(this).off('keyup');
	        });

	        this.$search.on('keyup input', function (evt) {
	          self.handleSearch(evt);
	        });

	        container.on('open', function () {
	          self.$search.attr('tabindex', 0);

	          self.$search.focus();

	          window.setTimeout(function () {
	            self.$search.focus();
	          }, 0);
	        });

	        container.on('close', function () {
	          self.$search.attr('tabindex', -1);

	          self.$search.val('');
	        });

	        container.on('focus', function () {
	          if (container.isOpen()) {
	            self.$search.focus();
	          }
	        });

	        container.on('results:all', function (params) {
	          if (params.query.term == null || params.query.term === '') {
	            var showSearch = self.showSearch(params);

	            if (showSearch) {
	              self.$searchContainer.removeClass('select2-search--hide');
	            } else {
	              self.$searchContainer.addClass('select2-search--hide');
	            }
	          }
	        });
	      };

	      Search.prototype.handleSearch = function (evt) {
	        if (!this._keyUpPrevented) {
	          var input = this.$search.val();

	          this.trigger('query', {
	            term: input
	          });
	        }

	        this._keyUpPrevented = false;
	      };

	      Search.prototype.showSearch = function (_, params) {
	        return true;
	      };

	      return Search;
	    });

	    S2.define('select2/dropdown/hidePlaceholder', [], function () {
	      function HidePlaceholder(decorated, $element, options, dataAdapter) {
	        this.placeholder = this.normalizePlaceholder(options.get('placeholder'));

	        decorated.call(this, $element, options, dataAdapter);
	      }

	      HidePlaceholder.prototype.append = function (decorated, data) {
	        data.results = this.removePlaceholder(data.results);

	        decorated.call(this, data);
	      };

	      HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
	        if (typeof placeholder === 'string') {
	          placeholder = {
	            id: '',
	            text: placeholder
	          };
	        }

	        return placeholder;
	      };

	      HidePlaceholder.prototype.removePlaceholder = function (_, data) {
	        var modifiedData = data.slice(0);

	        for (var d = data.length - 1; d >= 0; d--) {
	          var item = data[d];

	          if (this.placeholder.id === item.id) {
	            modifiedData.splice(d, 1);
	          }
	        }

	        return modifiedData;
	      };

	      return HidePlaceholder;
	    });

	    S2.define('select2/dropdown/infiniteScroll', ['jquery'], function ($) {
	      function InfiniteScroll(decorated, $element, options, dataAdapter) {
	        this.lastParams = {};

	        decorated.call(this, $element, options, dataAdapter);

	        this.$loadingMore = this.createLoadingMore();
	        this.loading = false;
	      }

	      InfiniteScroll.prototype.append = function (decorated, data) {
	        this.$loadingMore.remove();
	        this.loading = false;

	        decorated.call(this, data);

	        if (this.showLoadingMore(data)) {
	          this.$results.append(this.$loadingMore);
	        }
	      };

	      InfiniteScroll.prototype.bind = function (decorated, container, $container) {
	        var self = this;

	        decorated.call(this, container, $container);

	        container.on('query', function (params) {
	          self.lastParams = params;
	          self.loading = true;
	        });

	        container.on('query:append', function (params) {
	          self.lastParams = params;
	          self.loading = true;
	        });

	        this.$results.on('scroll', function () {
	          var isLoadMoreVisible = $.contains(document.documentElement, self.$loadingMore[0]);

	          if (self.loading || !isLoadMoreVisible) {
	            return;
	          }

	          var currentOffset = self.$results.offset().top + self.$results.outerHeight(false);
	          var loadingMoreOffset = self.$loadingMore.offset().top + self.$loadingMore.outerHeight(false);

	          if (currentOffset + 50 >= loadingMoreOffset) {
	            self.loadMore();
	          }
	        });
	      };

	      InfiniteScroll.prototype.loadMore = function () {
	        this.loading = true;

	        var params = $.extend({}, { page: 1 }, this.lastParams);

	        params.page++;

	        this.trigger('query:append', params);
	      };

	      InfiniteScroll.prototype.showLoadingMore = function (_, data) {
	        return data.pagination && data.pagination.more;
	      };

	      InfiniteScroll.prototype.createLoadingMore = function () {
	        var $option = $('<li ' + 'class="select2-results__option select2-results__option--load-more"' + 'role="treeitem" aria-disabled="true"></li>');

	        var message = this.options.get('translations').get('loadingMore');

	        $option.html(message(this.lastParams));

	        return $option;
	      };

	      return InfiniteScroll;
	    });

	    S2.define('select2/dropdown/attachBody', ['jquery', '../utils'], function ($, Utils) {
	      function AttachBody(decorated, $element, options) {
	        this.$dropdownParent = options.get('dropdownParent') || $(document.body);

	        decorated.call(this, $element, options);
	      }

	      AttachBody.prototype.bind = function (decorated, container, $container) {
	        var self = this;

	        var setupResultsEvents = false;

	        decorated.call(this, container, $container);

	        container.on('open', function () {
	          self._showDropdown();
	          self._attachPositioningHandler(container);

	          if (!setupResultsEvents) {
	            setupResultsEvents = true;

	            container.on('results:all', function () {
	              self._positionDropdown();
	              self._resizeDropdown();
	            });

	            container.on('results:append', function () {
	              self._positionDropdown();
	              self._resizeDropdown();
	            });
	          }
	        });

	        container.on('close', function () {
	          self._hideDropdown();
	          self._detachPositioningHandler(container);
	        });

	        this.$dropdownContainer.on('mousedown', function (evt) {
	          evt.stopPropagation();
	        });
	      };

	      AttachBody.prototype.destroy = function (decorated) {
	        decorated.call(this);

	        this.$dropdownContainer.remove();
	      };

	      AttachBody.prototype.position = function (decorated, $dropdown, $container) {
	        // Clone all of the container classes
	        $dropdown.attr('class', $container.attr('class'));

	        $dropdown.removeClass('select2');
	        $dropdown.addClass('select2-container--open');

	        $dropdown.css({
	          position: 'absolute',
	          top: -999999
	        });

	        this.$container = $container;
	      };

	      AttachBody.prototype.render = function (decorated) {
	        var $container = $('<span></span>');

	        var $dropdown = decorated.call(this);
	        $container.append($dropdown);

	        this.$dropdownContainer = $container;

	        return $container;
	      };

	      AttachBody.prototype._hideDropdown = function (decorated) {
	        this.$dropdownContainer.detach();
	      };

	      AttachBody.prototype._attachPositioningHandler = function (decorated, container) {
	        var self = this;

	        var scrollEvent = 'scroll.select2.' + container.id;
	        var resizeEvent = 'resize.select2.' + container.id;
	        var orientationEvent = 'orientationchange.select2.' + container.id;

	        var $watchers = this.$container.parents().filter(Utils.hasScroll);
	        $watchers.each(function () {
	          $(this).data('select2-scroll-position', {
	            x: $(this).scrollLeft(),
	            y: $(this).scrollTop()
	          });
	        });

	        $watchers.on(scrollEvent, function (ev) {
	          var position = $(this).data('select2-scroll-position');
	          $(this).scrollTop(position.y);
	        });

	        $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent, function (e) {
	          self._positionDropdown();
	          self._resizeDropdown();
	        });
	      };

	      AttachBody.prototype._detachPositioningHandler = function (decorated, container) {
	        var scrollEvent = 'scroll.select2.' + container.id;
	        var resizeEvent = 'resize.select2.' + container.id;
	        var orientationEvent = 'orientationchange.select2.' + container.id;

	        var $watchers = this.$container.parents().filter(Utils.hasScroll);
	        $watchers.off(scrollEvent);

	        $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
	      };

	      AttachBody.prototype._positionDropdown = function () {
	        var $window = $(window);

	        var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
	        var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');

	        var newDirection = null;

	        var offset = this.$container.offset();

	        offset.bottom = offset.top + this.$container.outerHeight(false);

	        var container = {
	          height: this.$container.outerHeight(false)
	        };

	        container.top = offset.top;
	        container.bottom = offset.top + container.height;

	        var dropdown = {
	          height: this.$dropdown.outerHeight(false)
	        };

	        var viewport = {
	          top: $window.scrollTop(),
	          bottom: $window.scrollTop() + $window.height()
	        };

	        var enoughRoomAbove = viewport.top < offset.top - dropdown.height;
	        var enoughRoomBelow = viewport.bottom > offset.bottom + dropdown.height;

	        var css = {
	          left: offset.left,
	          top: container.bottom
	        };

	        // Determine what the parent element is to use for calciulating the offset
	        var $offsetParent = this.$dropdownParent;

	        // For statically positoned elements, we need to get the element
	        // that is determining the offset
	        if ($offsetParent.css('position') === 'static') {
	          $offsetParent = $offsetParent.offsetParent();
	        }

	        var parentOffset = $offsetParent.offset();

	        css.top -= parentOffset.top;
	        css.left -= parentOffset.left;

	        if (!isCurrentlyAbove && !isCurrentlyBelow) {
	          newDirection = 'below';
	        }

	        if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
	          newDirection = 'above';
	        } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
	          newDirection = 'below';
	        }

	        if (newDirection == 'above' || isCurrentlyAbove && newDirection !== 'below') {
	          css.top = container.top - parentOffset.top - dropdown.height;
	        }

	        if (newDirection != null) {
	          this.$dropdown.removeClass('select2-dropdown--below select2-dropdown--above').addClass('select2-dropdown--' + newDirection);
	          this.$container.removeClass('select2-container--below select2-container--above').addClass('select2-container--' + newDirection);
	        }

	        this.$dropdownContainer.css(css);
	      };

	      AttachBody.prototype._resizeDropdown = function () {
	        var css = {
	          width: this.$container.outerWidth(false) + 'px'
	        };

	        if (this.options.get('dropdownAutoWidth')) {
	          css.minWidth = css.width;
	          css.position = 'relative';
	          css.width = 'auto';
	        }

	        this.$dropdown.css(css);
	      };

	      AttachBody.prototype._showDropdown = function (decorated) {
	        this.$dropdownContainer.appendTo(this.$dropdownParent);

	        this._positionDropdown();
	        this._resizeDropdown();
	      };

	      return AttachBody;
	    });

	    S2.define('select2/dropdown/minimumResultsForSearch', [], function () {
	      function countResults(data) {
	        var count = 0;

	        for (var d = 0; d < data.length; d++) {
	          var item = data[d];

	          if (item.children) {
	            count += countResults(item.children);
	          } else {
	            count++;
	          }
	        }

	        return count;
	      }

	      function MinimumResultsForSearch(decorated, $element, options, dataAdapter) {
	        this.minimumResultsForSearch = options.get('minimumResultsForSearch');

	        if (this.minimumResultsForSearch < 0) {
	          this.minimumResultsForSearch = Infinity;
	        }

	        decorated.call(this, $element, options, dataAdapter);
	      }

	      MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
	        if (countResults(params.data.results) < this.minimumResultsForSearch) {
	          return false;
	        }

	        return decorated.call(this, params);
	      };

	      return MinimumResultsForSearch;
	    });

	    S2.define('select2/dropdown/selectOnClose', [], function () {
	      function SelectOnClose() {}

	      SelectOnClose.prototype.bind = function (decorated, container, $container) {
	        var self = this;

	        decorated.call(this, container, $container);

	        container.on('close', function (params) {
	          self._handleSelectOnClose(params);
	        });
	      };

	      SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
	        if (params && params.originalSelect2Event != null) {
	          var event = params.originalSelect2Event;

	          // Don't select an item if the close event was triggered from a select or
	          // unselect event
	          if (event._type === 'select' || event._type === 'unselect') {
	            return;
	          }
	        }

	        var $highlightedResults = this.getHighlightedResults();

	        // Only select highlighted results
	        if ($highlightedResults.length < 1) {
	          return;
	        }

	        var data = $highlightedResults.data('data');

	        // Don't re-select already selected resulte
	        if (data.element != null && data.element.selected || data.element == null && data.selected) {
	          return;
	        }

	        this.trigger('select', {
	          data: data
	        });
	      };

	      return SelectOnClose;
	    });

	    S2.define('select2/dropdown/closeOnSelect', [], function () {
	      function CloseOnSelect() {}

	      CloseOnSelect.prototype.bind = function (decorated, container, $container) {
	        var self = this;

	        decorated.call(this, container, $container);

	        container.on('select', function (evt) {
	          self._selectTriggered(evt);
	        });

	        container.on('unselect', function (evt) {
	          self._selectTriggered(evt);
	        });
	      };

	      CloseOnSelect.prototype._selectTriggered = function (_, evt) {
	        var originalEvent = evt.originalEvent;

	        // Don't close if the control key is being held
	        if (originalEvent && originalEvent.ctrlKey) {
	          return;
	        }

	        this.trigger('close', {
	          originalEvent: originalEvent,
	          originalSelect2Event: evt
	        });
	      };

	      return CloseOnSelect;
	    });

	    S2.define('select2/i18n/en', [], function () {
	      // English
	      return {
	        errorLoading: function errorLoading() {
	          return 'The results could not be loaded.';
	        },
	        inputTooLong: function inputTooLong(args) {
	          var overChars = args.input.length - args.maximum;

	          var message = 'Please delete ' + overChars + ' character';

	          if (overChars != 1) {
	            message += 's';
	          }

	          return message;
	        },
	        inputTooShort: function inputTooShort(args) {
	          var remainingChars = args.minimum - args.input.length;

	          var message = 'Please enter ' + remainingChars + ' or more characters';

	          return message;
	        },
	        loadingMore: function loadingMore() {
	          return 'Loading more results…';
	        },
	        maximumSelected: function maximumSelected(args) {
	          var message = 'You can only select ' + args.maximum + ' item';

	          if (args.maximum != 1) {
	            message += 's';
	          }

	          return message;
	        },
	        noResults: function noResults() {
	          return 'No results found';
	        },
	        searching: function searching() {
	          return 'Searching…';
	        }
	      };
	    });

	    S2.define('select2/defaults', ['jquery', 'require', './results', './selection/single', './selection/multiple', './selection/placeholder', './selection/allowClear', './selection/search', './selection/eventRelay', './utils', './translation', './diacritics', './data/select', './data/array', './data/ajax', './data/tags', './data/tokenizer', './data/minimumInputLength', './data/maximumInputLength', './data/maximumSelectionLength', './dropdown', './dropdown/search', './dropdown/hidePlaceholder', './dropdown/infiniteScroll', './dropdown/attachBody', './dropdown/minimumResultsForSearch', './dropdown/selectOnClose', './dropdown/closeOnSelect', './i18n/en'], function ($, require, ResultsList, SingleSelection, MultipleSelection, Placeholder, AllowClear, SelectionSearch, EventRelay, Utils, Translation, DIACRITICS, SelectData, ArrayData, AjaxData, Tags, Tokenizer, MinimumInputLength, MaximumInputLength, MaximumSelectionLength, Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll, AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect, EnglishTranslation) {
	      function Defaults() {
	        this.reset();
	      }

	      Defaults.prototype.apply = function (options) {
	        options = $.extend(true, {}, this.defaults, options);

	        if (options.dataAdapter == null) {
	          if (options.ajax != null) {
	            options.dataAdapter = AjaxData;
	          } else if (options.data != null) {
	            options.dataAdapter = ArrayData;
	          } else {
	            options.dataAdapter = SelectData;
	          }

	          if (options.minimumInputLength > 0) {
	            options.dataAdapter = Utils.Decorate(options.dataAdapter, MinimumInputLength);
	          }

	          if (options.maximumInputLength > 0) {
	            options.dataAdapter = Utils.Decorate(options.dataAdapter, MaximumInputLength);
	          }

	          if (options.maximumSelectionLength > 0) {
	            options.dataAdapter = Utils.Decorate(options.dataAdapter, MaximumSelectionLength);
	          }

	          if (options.tags) {
	            options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
	          }

	          if (options.tokenSeparators != null || options.tokenizer != null) {
	            options.dataAdapter = Utils.Decorate(options.dataAdapter, Tokenizer);
	          }

	          if (options.query != null) {
	            var Query = require(options.amdBase + 'compat/query');

	            options.dataAdapter = Utils.Decorate(options.dataAdapter, Query);
	          }

	          if (options.initSelection != null) {
	            var InitSelection = require(options.amdBase + 'compat/initSelection');

	            options.dataAdapter = Utils.Decorate(options.dataAdapter, InitSelection);
	          }
	        }

	        if (options.resultsAdapter == null) {
	          options.resultsAdapter = ResultsList;

	          if (options.ajax != null) {
	            options.resultsAdapter = Utils.Decorate(options.resultsAdapter, InfiniteScroll);
	          }

	          if (options.placeholder != null) {
	            options.resultsAdapter = Utils.Decorate(options.resultsAdapter, HidePlaceholder);
	          }

	          if (options.selectOnClose) {
	            options.resultsAdapter = Utils.Decorate(options.resultsAdapter, SelectOnClose);
	          }
	        }

	        if (options.dropdownAdapter == null) {
	          if (options.multiple) {
	            options.dropdownAdapter = Dropdown;
	          } else {
	            var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);

	            options.dropdownAdapter = SearchableDropdown;
	          }

	          if (options.minimumResultsForSearch !== 0) {
	            options.dropdownAdapter = Utils.Decorate(options.dropdownAdapter, MinimumResultsForSearch);
	          }

	          if (options.closeOnSelect) {
	            options.dropdownAdapter = Utils.Decorate(options.dropdownAdapter, CloseOnSelect);
	          }

	          if (options.dropdownCssClass != null || options.dropdownCss != null || options.adaptDropdownCssClass != null) {
	            var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');

	            options.dropdownAdapter = Utils.Decorate(options.dropdownAdapter, DropdownCSS);
	          }

	          options.dropdownAdapter = Utils.Decorate(options.dropdownAdapter, AttachBody);
	        }

	        if (options.selectionAdapter == null) {
	          if (options.multiple) {
	            options.selectionAdapter = MultipleSelection;
	          } else {
	            options.selectionAdapter = SingleSelection;
	          }

	          // Add the placeholder mixin if a placeholder was specified
	          if (options.placeholder != null) {
	            options.selectionAdapter = Utils.Decorate(options.selectionAdapter, Placeholder);
	          }

	          if (options.allowClear) {
	            options.selectionAdapter = Utils.Decorate(options.selectionAdapter, AllowClear);
	          }

	          if (options.multiple) {
	            options.selectionAdapter = Utils.Decorate(options.selectionAdapter, SelectionSearch);
	          }

	          if (options.containerCssClass != null || options.containerCss != null || options.adaptContainerCssClass != null) {
	            var ContainerCSS = require(options.amdBase + 'compat/containerCss');

	            options.selectionAdapter = Utils.Decorate(options.selectionAdapter, ContainerCSS);
	          }

	          options.selectionAdapter = Utils.Decorate(options.selectionAdapter, EventRelay);
	        }

	        if (typeof options.language === 'string') {
	          // Check if the language is specified with a region
	          if (options.language.indexOf('-') > 0) {
	            // Extract the region information if it is included
	            var languageParts = options.language.split('-');
	            var baseLanguage = languageParts[0];

	            options.language = [options.language, baseLanguage];
	          } else {
	            options.language = [options.language];
	          }
	        }

	        if ($.isArray(options.language)) {
	          var languages = new Translation();
	          options.language.push('en');

	          var languageNames = options.language;

	          for (var l = 0; l < languageNames.length; l++) {
	            var name = languageNames[l];
	            var language = {};

	            try {
	              // Try to load it with the original name
	              language = Translation.loadPath(name);
	            } catch (e) {
	              try {
	                // If we couldn't load it, check if it wasn't the full path
	                name = this.defaults.amdLanguageBase + name;
	                language = Translation.loadPath(name);
	              } catch (ex) {
	                // The translation could not be loaded at all. Sometimes this is
	                // because of a configuration problem, other times this can be
	                // because of how Select2 helps load all possible translation files.
	                if (options.debug && window.console && console.warn) {
	                  console.warn('Select2: The language file for "' + name + '" could not be ' + 'automatically loaded. A fallback will be used instead.');
	                }

	                continue;
	              }
	            }

	            languages.extend(language);
	          }

	          options.translations = languages;
	        } else {
	          var baseTranslation = Translation.loadPath(this.defaults.amdLanguageBase + 'en');
	          var customTranslation = new Translation(options.language);

	          customTranslation.extend(baseTranslation);

	          options.translations = customTranslation;
	        }

	        return options;
	      };

	      Defaults.prototype.reset = function () {
	        function stripDiacritics(text) {
	          // Used 'uni range + named function' from http://jsperf.com/diacritics/18
	          function match(a) {
	            return DIACRITICS[a] || a;
	          }

	          return text.replace(/[^\u0000-\u007E]/g, match);
	        }

	        function matcher(params, data) {
	          // Always return the object if there is nothing to compare
	          if ($.trim(params.term) === '') {
	            return data;
	          }

	          // Do a recursive check for options with children
	          if (data.children && data.children.length > 0) {
	            // Clone the data object if there are children
	            // This is required as we modify the object to remove any non-matches
	            var match = $.extend(true, {}, data);

	            // Check each child of the option
	            for (var c = data.children.length - 1; c >= 0; c--) {
	              var child = data.children[c];

	              var matches = matcher(params, child);

	              // If there wasn't a match, remove the object in the array
	              if (matches == null) {
	                match.children.splice(c, 1);
	              }
	            }

	            // If any children matched, return the new object
	            if (match.children.length > 0) {
	              return match;
	            }

	            // If there were no matching children, check just the plain object
	            return matcher(params, match);
	          }

	          var original = stripDiacritics(data.text).toUpperCase();
	          var term = stripDiacritics(params.term).toUpperCase();

	          // Check if the text contains the term
	          if (original.indexOf(term) > -1) {
	            return data;
	          }

	          // If it doesn't contain the term, don't return anything
	          return null;
	        }

	        this.defaults = {
	          amdBase: './',
	          amdLanguageBase: './i18n/',
	          closeOnSelect: true,
	          debug: false,
	          dropdownAutoWidth: false,
	          escapeMarkup: Utils.escapeMarkup,
	          language: EnglishTranslation,
	          matcher: matcher,
	          minimumInputLength: 0,
	          maximumInputLength: 0,
	          maximumSelectionLength: 0,
	          minimumResultsForSearch: 0,
	          selectOnClose: false,
	          sorter: function sorter(data) {
	            return data;
	          },
	          templateResult: function templateResult(result) {
	            return result.text;
	          },
	          templateSelection: function templateSelection(selection) {
	            return selection.text;
	          },
	          theme: 'default',
	          width: 'resolve'
	        };
	      };

	      Defaults.prototype.set = function (key, value) {
	        var camelKey = $.camelCase(key);

	        var data = {};
	        data[camelKey] = value;

	        var convertedData = Utils._convertData(data);

	        $.extend(this.defaults, convertedData);
	      };

	      var defaults = new Defaults();

	      return defaults;
	    });

	    S2.define('select2/options', ['require', 'jquery', './defaults', './utils'], function (require, $, Defaults, Utils) {
	      function Options(options, $element) {
	        this.options = options;

	        if ($element != null) {
	          this.fromElement($element);
	        }

	        this.options = Defaults.apply(this.options);

	        if ($element && $element.is('input')) {
	          var InputCompat = require(this.get('amdBase') + 'compat/inputData');

	          this.options.dataAdapter = Utils.Decorate(this.options.dataAdapter, InputCompat);
	        }
	      }

	      Options.prototype.fromElement = function ($e) {
	        var excludedData = ['select2'];

	        if (this.options.multiple == null) {
	          this.options.multiple = $e.prop('multiple');
	        }

	        if (this.options.disabled == null) {
	          this.options.disabled = $e.prop('disabled');
	        }

	        if (this.options.language == null) {
	          if ($e.prop('lang')) {
	            this.options.language = $e.prop('lang').toLowerCase();
	          } else if ($e.closest('[lang]').prop('lang')) {
	            this.options.language = $e.closest('[lang]').prop('lang');
	          }
	        }

	        if (this.options.dir == null) {
	          if ($e.prop('dir')) {
	            this.options.dir = $e.prop('dir');
	          } else if ($e.closest('[dir]').prop('dir')) {
	            this.options.dir = $e.closest('[dir]').prop('dir');
	          } else {
	            this.options.dir = 'ltr';
	          }
	        }

	        $e.prop('disabled', this.options.disabled);
	        $e.prop('multiple', this.options.multiple);

	        if ($e.data('select2Tags')) {
	          if (this.options.debug && window.console && console.warn) {
	            console.warn('Select2: The `data-select2-tags` attribute has been changed to ' + 'use the `data-data` and `data-tags="true"` attributes and will be ' + 'removed in future versions of Select2.');
	          }

	          $e.data('data', $e.data('select2Tags'));
	          $e.data('tags', true);
	        }

	        if ($e.data('ajaxUrl')) {
	          if (this.options.debug && window.console && console.warn) {
	            console.warn('Select2: The `data-ajax-url` attribute has been changed to ' + '`data-ajax--url` and support for the old attribute will be removed' + ' in future versions of Select2.');
	          }

	          $e.attr('ajax--url', $e.data('ajaxUrl'));
	          $e.data('ajax--url', $e.data('ajaxUrl'));
	        }

	        var dataset = {};

	        // Prefer the element's `dataset` attribute if it exists
	        // jQuery 1.x does not correctly handle data attributes with multiple dashes
	        if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
	          dataset = $.extend(true, {}, $e[0].dataset, $e.data());
	        } else {
	          dataset = $e.data();
	        }

	        var data = $.extend(true, {}, dataset);

	        data = Utils._convertData(data);

	        for (var key in data) {
	          if ($.inArray(key, excludedData) > -1) {
	            continue;
	          }

	          if ($.isPlainObject(this.options[key])) {
	            $.extend(this.options[key], data[key]);
	          } else {
	            this.options[key] = data[key];
	          }
	        }

	        return this;
	      };

	      Options.prototype.get = function (key) {
	        return this.options[key];
	      };

	      Options.prototype.set = function (key, val) {
	        this.options[key] = val;
	      };

	      return Options;
	    });

	    S2.define('select2/core', ['jquery', './options', './utils', './keys'], function ($, Options, Utils, KEYS) {
	      var Select2 = function Select2($element, options) {
	        if ($element.data('select2') != null) {
	          $element.data('select2').destroy();
	        }

	        this.$element = $element;

	        this.id = this._generateId($element);

	        options = options || {};

	        this.options = new Options(options, $element);

	        Select2.__super__.constructor.call(this);

	        // Set up the tabindex

	        var tabindex = $element.attr('tabindex') || 0;
	        $element.data('old-tabindex', tabindex);
	        $element.attr('tabindex', '-1');

	        // Set up containers and adapters

	        var DataAdapter = this.options.get('dataAdapter');
	        this.dataAdapter = new DataAdapter($element, this.options);

	        var $container = this.render();

	        this._placeContainer($container);

	        var SelectionAdapter = this.options.get('selectionAdapter');
	        this.selection = new SelectionAdapter($element, this.options);
	        this.$selection = this.selection.render();

	        this.selection.position(this.$selection, $container);

	        var DropdownAdapter = this.options.get('dropdownAdapter');
	        this.dropdown = new DropdownAdapter($element, this.options);
	        this.$dropdown = this.dropdown.render();

	        this.dropdown.position(this.$dropdown, $container);

	        var ResultsAdapter = this.options.get('resultsAdapter');
	        this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
	        this.$results = this.results.render();

	        this.results.position(this.$results, this.$dropdown);

	        // Bind events

	        var self = this;

	        // Bind the container to all of the adapters
	        this._bindAdapters();

	        // Register any DOM event handlers
	        this._registerDomEvents();

	        // Register any internal event handlers
	        this._registerDataEvents();
	        this._registerSelectionEvents();
	        this._registerDropdownEvents();
	        this._registerResultsEvents();
	        this._registerEvents();

	        // Set the initial state
	        this.dataAdapter.current(function (initialData) {
	          self.trigger('selection:update', {
	            data: initialData
	          });
	        });

	        // Hide the original select
	        $element.addClass('select2-hidden-accessible');
	        $element.attr('aria-hidden', 'true');

	        // Synchronize any monitored attributes
	        this._syncAttributes();

	        $element.data('select2', this);
	      };

	      Utils.Extend(Select2, Utils.Observable);

	      Select2.prototype._generateId = function ($element) {
	        var id = '';

	        if ($element.attr('id') != null) {
	          id = $element.attr('id');
	        } else if ($element.attr('name') != null) {
	          id = $element.attr('name') + '-' + Utils.generateChars(2);
	        } else {
	          id = Utils.generateChars(4);
	        }

	        id = id.replace(/(:|\.|\[|\]|,)/g, '');
	        id = 'select2-' + id;

	        return id;
	      };

	      Select2.prototype._placeContainer = function ($container) {
	        $container.insertAfter(this.$element);

	        var width = this._resolveWidth(this.$element, this.options.get('width'));

	        if (width != null) {
	          $container.css('width', width);
	        }
	      };

	      Select2.prototype._resolveWidth = function ($element, method) {
	        var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;

	        if (method == 'resolve') {
	          var styleWidth = this._resolveWidth($element, 'style');

	          if (styleWidth != null) {
	            return styleWidth;
	          }

	          return this._resolveWidth($element, 'element');
	        }

	        if (method == 'element') {
	          var elementWidth = $element.outerWidth(false);

	          if (elementWidth <= 0) {
	            return 'auto';
	          }

	          return elementWidth + 'px';
	        }

	        if (method == 'style') {
	          var style = $element.attr('style');

	          if (typeof style !== 'string') {
	            return null;
	          }

	          var attrs = style.split(';');

	          for (var i = 0, l = attrs.length; i < l; i = i + 1) {
	            var attr = attrs[i].replace(/\s/g, '');
	            var matches = attr.match(WIDTH);

	            if (matches !== null && matches.length >= 1) {
	              return matches[1];
	            }
	          }

	          return null;
	        }

	        return method;
	      };

	      Select2.prototype._bindAdapters = function () {
	        this.dataAdapter.bind(this, this.$container);
	        this.selection.bind(this, this.$container);

	        this.dropdown.bind(this, this.$container);
	        this.results.bind(this, this.$container);
	      };

	      Select2.prototype._registerDomEvents = function () {
	        var self = this;

	        this.$element.on('change.select2', function () {
	          self.dataAdapter.current(function (data) {
	            self.trigger('selection:update', {
	              data: data
	            });
	          });
	        });

	        this.$element.on('focus.select2', function (evt) {
	          self.trigger('focus', evt);
	        });

	        this._syncA = Utils.bind(this._syncAttributes, this);
	        this._syncS = Utils.bind(this._syncSubtree, this);

	        if (this.$element[0].attachEvent) {
	          this.$element[0].attachEvent('onpropertychange', this._syncA);
	        }

	        var observer = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

	        if (observer != null) {
	          this._observer = new observer(function (mutations) {
	            $.each(mutations, self._syncA);
	            $.each(mutations, self._syncS);
	          });
	          this._observer.observe(this.$element[0], {
	            attributes: true,
	            childList: true,
	            subtree: false
	          });
	        } else if (this.$element[0].addEventListener) {
	          this.$element[0].addEventListener('DOMAttrModified', self._syncA, false);
	          this.$element[0].addEventListener('DOMNodeInserted', self._syncS, false);
	          this.$element[0].addEventListener('DOMNodeRemoved', self._syncS, false);
	        }
	      };

	      Select2.prototype._registerDataEvents = function () {
	        var self = this;

	        this.dataAdapter.on('*', function (name, params) {
	          self.trigger(name, params);
	        });
	      };

	      Select2.prototype._registerSelectionEvents = function () {
	        var self = this;
	        var nonRelayEvents = ['toggle', 'focus'];

	        this.selection.on('toggle', function () {
	          self.toggleDropdown();
	        });

	        this.selection.on('focus', function (params) {
	          self.focus(params);
	        });

	        this.selection.on('*', function (name, params) {
	          if ($.inArray(name, nonRelayEvents) !== -1) {
	            return;
	          }

	          self.trigger(name, params);
	        });
	      };

	      Select2.prototype._registerDropdownEvents = function () {
	        var self = this;

	        this.dropdown.on('*', function (name, params) {
	          self.trigger(name, params);
	        });
	      };

	      Select2.prototype._registerResultsEvents = function () {
	        var self = this;

	        this.results.on('*', function (name, params) {
	          self.trigger(name, params);
	        });
	      };

	      Select2.prototype._registerEvents = function () {
	        var self = this;

	        this.on('open', function () {
	          self.$container.addClass('select2-container--open');
	        });

	        this.on('close', function () {
	          self.$container.removeClass('select2-container--open');
	        });

	        this.on('enable', function () {
	          self.$container.removeClass('select2-container--disabled');
	        });

	        this.on('disable', function () {
	          self.$container.addClass('select2-container--disabled');
	        });

	        this.on('blur', function () {
	          self.$container.removeClass('select2-container--focus');
	        });

	        this.on('query', function (params) {
	          if (!self.isOpen()) {
	            self.trigger('open', {});
	          }

	          this.dataAdapter.query(params, function (data) {
	            self.trigger('results:all', {
	              data: data,
	              query: params
	            });
	          });
	        });

	        this.on('query:append', function (params) {
	          this.dataAdapter.query(params, function (data) {
	            self.trigger('results:append', {
	              data: data,
	              query: params
	            });
	          });
	        });

	        this.on('keypress', function (evt) {
	          var key = evt.which;

	          if (self.isOpen()) {
	            if (key === KEYS.ESC || key === KEYS.TAB || key === KEYS.UP && evt.altKey) {
	              self.close();

	              evt.preventDefault();
	            } else if (key === KEYS.ENTER) {
	              self.trigger('results:select', {});

	              evt.preventDefault();
	            } else if (key === KEYS.SPACE && evt.ctrlKey) {
	              self.trigger('results:toggle', {});

	              evt.preventDefault();
	            } else if (key === KEYS.UP) {
	              self.trigger('results:previous', {});

	              evt.preventDefault();
	            } else if (key === KEYS.DOWN) {
	              self.trigger('results:next', {});

	              evt.preventDefault();
	            }
	          } else {
	            if (key === KEYS.ENTER || key === KEYS.SPACE || key === KEYS.DOWN && evt.altKey) {
	              self.open();

	              evt.preventDefault();
	            }
	          }
	        });
	      };

	      Select2.prototype._syncAttributes = function () {
	        this.options.set('disabled', this.$element.prop('disabled'));

	        if (this.options.get('disabled')) {
	          if (this.isOpen()) {
	            this.close();
	          }

	          this.trigger('disable', {});
	        } else {
	          this.trigger('enable', {});
	        }
	      };

	      Select2.prototype._syncSubtree = function (evt, mutations) {
	        var changed = false;
	        var self = this;

	        // Ignore any mutation events raised for elements that aren't options or
	        // optgroups. This handles the case when the select element is destroyed
	        if (evt && evt.target && evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP') {
	          return;
	        }

	        if (!mutations) {
	          // If mutation events aren't supported, then we can only assume that the
	          // change affected the selections
	          changed = true;
	        } else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
	          for (var n = 0; n < mutations.addedNodes.length; n++) {
	            var node = mutations.addedNodes[n];

	            if (node.selected) {
	              changed = true;
	            }
	          }
	        } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
	          changed = true;
	        }

	        // Only re-pull the data if we think there is a change
	        if (changed) {
	          this.dataAdapter.current(function (currentData) {
	            self.trigger('selection:update', {
	              data: currentData
	            });
	          });
	        }
	      };

	      /**
	       * Override the trigger method to automatically trigger pre-events when
	       * there are events that can be prevented.
	       */
	      Select2.prototype.trigger = function (name, args) {
	        var actualTrigger = Select2.__super__.trigger;
	        var preTriggerMap = {
	          'open': 'opening',
	          'close': 'closing',
	          'select': 'selecting',
	          'unselect': 'unselecting'
	        };

	        if (args === undefined) {
	          args = {};
	        }

	        if (name in preTriggerMap) {
	          var preTriggerName = preTriggerMap[name];
	          var preTriggerArgs = {
	            prevented: false,
	            name: name,
	            args: args
	          };

	          actualTrigger.call(this, preTriggerName, preTriggerArgs);

	          if (preTriggerArgs.prevented) {
	            args.prevented = true;

	            return;
	          }
	        }

	        actualTrigger.call(this, name, args);
	      };

	      Select2.prototype.toggleDropdown = function () {
	        if (this.options.get('disabled')) {
	          return;
	        }

	        if (this.isOpen()) {
	          this.close();
	        } else {
	          this.open();
	        }
	      };

	      Select2.prototype.open = function () {
	        if (this.isOpen()) {
	          return;
	        }

	        this.trigger('query', {});
	      };

	      Select2.prototype.close = function () {
	        if (!this.isOpen()) {
	          return;
	        }

	        this.trigger('close', {});
	      };

	      Select2.prototype.isOpen = function () {
	        return this.$container.hasClass('select2-container--open');
	      };

	      Select2.prototype.hasFocus = function () {
	        return this.$container.hasClass('select2-container--focus');
	      };

	      Select2.prototype.focus = function (data) {
	        // No need to re-trigger focus events if we are already focused
	        if (this.hasFocus()) {
	          return;
	        }

	        this.$container.addClass('select2-container--focus');
	        this.trigger('focus', {});
	      };

	      Select2.prototype.enable = function (args) {
	        if (this.options.get('debug') && window.console && console.warn) {
	          console.warn('Select2: The `select2("enable")` method has been deprecated and will' + ' be removed in later Select2 versions. Use $element.prop("disabled")' + ' instead.');
	        }

	        if (args == null || args.length === 0) {
	          args = [true];
	        }

	        var disabled = !args[0];

	        this.$element.prop('disabled', disabled);
	      };

	      Select2.prototype.data = function () {
	        if (this.options.get('debug') && arguments.length > 0 && window.console && console.warn) {
	          console.warn('Select2: Data can no longer be set using `select2("data")`. You ' + 'should consider setting the value instead using `$element.val()`.');
	        }

	        var data = [];

	        this.dataAdapter.current(function (currentData) {
	          data = currentData;
	        });

	        return data;
	      };

	      Select2.prototype.val = function (args) {
	        if (this.options.get('debug') && window.console && console.warn) {
	          console.warn('Select2: The `select2("val")` method has been deprecated and will be' + ' removed in later Select2 versions. Use $element.val() instead.');
	        }

	        if (args == null || args.length === 0) {
	          return this.$element.val();
	        }

	        var newVal = args[0];

	        if ($.isArray(newVal)) {
	          newVal = $.map(newVal, function (obj) {
	            return obj.toString();
	          });
	        }

	        this.$element.val(newVal).trigger('change');
	      };

	      Select2.prototype.destroy = function () {
	        this.$container.remove();

	        if (this.$element[0].detachEvent) {
	          this.$element[0].detachEvent('onpropertychange', this._syncA);
	        }

	        if (this._observer != null) {
	          this._observer.disconnect();
	          this._observer = null;
	        } else if (this.$element[0].removeEventListener) {
	          this.$element[0].removeEventListener('DOMAttrModified', this._syncA, false);
	          this.$element[0].removeEventListener('DOMNodeInserted', this._syncS, false);
	          this.$element[0].removeEventListener('DOMNodeRemoved', this._syncS, false);
	        }

	        this._syncA = null;
	        this._syncS = null;

	        this.$element.off('.select2');
	        this.$element.attr('tabindex', this.$element.data('old-tabindex'));

	        this.$element.removeClass('select2-hidden-accessible');
	        this.$element.attr('aria-hidden', 'false');
	        this.$element.removeData('select2');

	        this.dataAdapter.destroy();
	        this.selection.destroy();
	        this.dropdown.destroy();
	        this.results.destroy();

	        this.dataAdapter = null;
	        this.selection = null;
	        this.dropdown = null;
	        this.results = null;
	      };

	      Select2.prototype.render = function () {
	        var $container = $('<span class="select2 select2-container">' + '<span class="selection"></span>' + '<span class="dropdown-wrapper" aria-hidden="true"></span>' + '</span>');

	        $container.attr('dir', this.options.get('dir'));

	        this.$container = $container;

	        this.$container.addClass('select2-container--' + this.options.get('theme'));

	        $container.data('element', this.$element);

	        return $container;
	      };

	      return Select2;
	    });

	    S2.define('select2/compat/utils', ['jquery'], function ($) {
	      function syncCssClasses($dest, $src, adapter) {
	        var classes,
	            replacements = [],
	            adapted;

	        classes = $.trim($dest.attr('class'));

	        if (classes) {
	          classes = '' + classes; // for IE which returns object

	          $(classes.split(/\s+/)).each(function () {
	            // Save all Select2 classes
	            if (this.indexOf('select2-') === 0) {
	              replacements.push(this);
	            }
	          });
	        }

	        classes = $.trim($src.attr('class'));

	        if (classes) {
	          classes = '' + classes; // for IE which returns object

	          $(classes.split(/\s+/)).each(function () {
	            // Only adapt non-Select2 classes
	            if (this.indexOf('select2-') !== 0) {
	              adapted = adapter(this);

	              if (adapted != null) {
	                replacements.push(adapted);
	              }
	            }
	          });
	        }

	        $dest.attr('class', replacements.join(' '));
	      }

	      return {
	        syncCssClasses: syncCssClasses
	      };
	    });

	    S2.define('select2/compat/containerCss', ['jquery', './utils'], function ($, CompatUtils) {
	      // No-op CSS adapter that discards all classes by default
	      function _containerAdapter(clazz) {
	        return null;
	      }

	      function ContainerCSS() {}

	      ContainerCSS.prototype.render = function (decorated) {
	        var $container = decorated.call(this);

	        var containerCssClass = this.options.get('containerCssClass') || '';

	        if ($.isFunction(containerCssClass)) {
	          containerCssClass = containerCssClass(this.$element);
	        }

	        var containerCssAdapter = this.options.get('adaptContainerCssClass');
	        containerCssAdapter = containerCssAdapter || _containerAdapter;

	        if (containerCssClass.indexOf(':all:') !== -1) {
	          containerCssClass = containerCssClass.replace(':all:', '');

	          var _cssAdapter = containerCssAdapter;

	          containerCssAdapter = function containerCssAdapter(clazz) {
	            var adapted = _cssAdapter(clazz);

	            if (adapted != null) {
	              // Append the old one along with the adapted one
	              return adapted + ' ' + clazz;
	            }

	            return clazz;
	          };
	        }

	        var containerCss = this.options.get('containerCss') || {};

	        if ($.isFunction(containerCss)) {
	          containerCss = containerCss(this.$element);
	        }

	        CompatUtils.syncCssClasses($container, this.$element, containerCssAdapter);

	        $container.css(containerCss);
	        $container.addClass(containerCssClass);

	        return $container;
	      };

	      return ContainerCSS;
	    });

	    S2.define('select2/compat/dropdownCss', ['jquery', './utils'], function ($, CompatUtils) {
	      // No-op CSS adapter that discards all classes by default
	      function _dropdownAdapter(clazz) {
	        return null;
	      }

	      function DropdownCSS() {}

	      DropdownCSS.prototype.render = function (decorated) {
	        var $dropdown = decorated.call(this);

	        var dropdownCssClass = this.options.get('dropdownCssClass') || '';

	        if ($.isFunction(dropdownCssClass)) {
	          dropdownCssClass = dropdownCssClass(this.$element);
	        }

	        var dropdownCssAdapter = this.options.get('adaptDropdownCssClass');
	        dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter;

	        if (dropdownCssClass.indexOf(':all:') !== -1) {
	          dropdownCssClass = dropdownCssClass.replace(':all:', '');

	          var _cssAdapter = dropdownCssAdapter;

	          dropdownCssAdapter = function dropdownCssAdapter(clazz) {
	            var adapted = _cssAdapter(clazz);

	            if (adapted != null) {
	              // Append the old one along with the adapted one
	              return adapted + ' ' + clazz;
	            }

	            return clazz;
	          };
	        }

	        var dropdownCss = this.options.get('dropdownCss') || {};

	        if ($.isFunction(dropdownCss)) {
	          dropdownCss = dropdownCss(this.$element);
	        }

	        CompatUtils.syncCssClasses($dropdown, this.$element, dropdownCssAdapter);

	        $dropdown.css(dropdownCss);
	        $dropdown.addClass(dropdownCssClass);

	        return $dropdown;
	      };

	      return DropdownCSS;
	    });

	    S2.define('select2/compat/initSelection', ['jquery'], function ($) {
	      function InitSelection(decorated, $element, options) {
	        if (options.get('debug') && window.console && console.warn) {
	          console.warn('Select2: The `initSelection` option has been deprecated in favor' + ' of a custom data adapter that overrides the `current` method. ' + 'This method is now called multiple times instead of a single ' + 'time when the instance is initialized. Support will be removed ' + 'for the `initSelection` option in future versions of Select2');
	        }

	        this.initSelection = options.get('initSelection');
	        this._isInitialized = false;

	        decorated.call(this, $element, options);
	      }

	      InitSelection.prototype.current = function (decorated, callback) {
	        var self = this;

	        if (this._isInitialized) {
	          decorated.call(this, callback);

	          return;
	        }

	        this.initSelection.call(null, this.$element, function (data) {
	          self._isInitialized = true;

	          if (!$.isArray(data)) {
	            data = [data];
	          }

	          callback(data);
	        });
	      };

	      return InitSelection;
	    });

	    S2.define('select2/compat/inputData', ['jquery'], function ($) {
	      function InputData(decorated, $element, options) {
	        this._currentData = [];
	        this._valueSeparator = options.get('valueSeparator') || ',';

	        if ($element.prop('type') === 'hidden') {
	          if (options.get('debug') && console && console.warn) {
	            console.warn('Select2: Using a hidden input with Select2 is no longer ' + 'supported and may stop working in the future. It is recommended ' + 'to use a `<select>` element instead.');
	          }
	        }

	        decorated.call(this, $element, options);
	      }

	      InputData.prototype.current = function (_, callback) {
	        function getSelected(data, selectedIds) {
	          var selected = [];

	          if (data.selected || $.inArray(data.id, selectedIds) !== -1) {
	            data.selected = true;
	            selected.push(data);
	          } else {
	            data.selected = false;
	          }

	          if (data.children) {
	            selected.push.apply(selected, getSelected(data.children, selectedIds));
	          }

	          return selected;
	        }

	        var selected = [];

	        for (var d = 0; d < this._currentData.length; d++) {
	          var data = this._currentData[d];

	          selected.push.apply(selected, getSelected(data, this.$element.val().split(this._valueSeparator)));
	        }

	        callback(selected);
	      };

	      InputData.prototype.select = function (_, data) {
	        if (!this.options.get('multiple')) {
	          this.current(function (allData) {
	            $.map(allData, function (data) {
	              data.selected = false;
	            });
	          });

	          this.$element.val(data.id);
	          this.$element.trigger('change');
	        } else {
	          var value = this.$element.val();
	          value += this._valueSeparator + data.id;

	          this.$element.val(value);
	          this.$element.trigger('change');
	        }
	      };

	      InputData.prototype.unselect = function (_, data) {
	        var self = this;

	        data.selected = false;

	        this.current(function (allData) {
	          var values = [];

	          for (var d = 0; d < allData.length; d++) {
	            var item = allData[d];

	            if (data.id == item.id) {
	              continue;
	            }

	            values.push(item.id);
	          }

	          self.$element.val(values.join(self._valueSeparator));
	          self.$element.trigger('change');
	        });
	      };

	      InputData.prototype.query = function (_, params, callback) {
	        var results = [];

	        for (var d = 0; d < this._currentData.length; d++) {
	          var data = this._currentData[d];

	          var matches = this.matches(params, data);

	          if (matches !== null) {
	            results.push(matches);
	          }
	        }

	        callback({
	          results: results
	        });
	      };

	      InputData.prototype.addOptions = function (_, $options) {
	        var options = $.map($options, function ($option) {
	          return $.data($option[0], 'data');
	        });

	        this._currentData.push.apply(this._currentData, options);
	      };

	      return InputData;
	    });

	    S2.define('select2/compat/matcher', ['jquery'], function ($) {
	      function oldMatcher(matcher) {
	        function wrappedMatcher(params, data) {
	          var match = $.extend(true, {}, data);

	          if (params.term == null || $.trim(params.term) === '') {
	            return match;
	          }

	          if (data.children) {
	            for (var c = data.children.length - 1; c >= 0; c--) {
	              var child = data.children[c];

	              // Check if the child object matches
	              // The old matcher returned a boolean true or false
	              var doesMatch = matcher(params.term, child.text, child);

	              // If the child didn't match, pop it off
	              if (!doesMatch) {
	                match.children.splice(c, 1);
	              }
	            }

	            if (match.children.length > 0) {
	              return match;
	            }
	          }

	          if (matcher(params.term, data.text, data)) {
	            return match;
	          }

	          return null;
	        }

	        return wrappedMatcher;
	      }

	      return oldMatcher;
	    });

	    S2.define('select2/compat/query', [], function () {
	      function Query(decorated, $element, options) {
	        if (options.get('debug') && window.console && console.warn) {
	          console.warn('Select2: The `query` option has been deprecated in favor of a ' + 'custom data adapter that overrides the `query` method. Support ' + 'will be removed for the `query` option in future versions of ' + 'Select2.');
	        }

	        decorated.call(this, $element, options);
	      }

	      Query.prototype.query = function (_, params, callback) {
	        params.callback = callback;

	        var query = this.options.get('query');

	        query.call(null, params);
	      };

	      return Query;
	    });

	    S2.define('select2/dropdown/attachContainer', [], function () {
	      function AttachContainer(decorated, $element, options) {
	        decorated.call(this, $element, options);
	      }

	      AttachContainer.prototype.position = function (decorated, $dropdown, $container) {
	        var $dropdownContainer = $container.find('.dropdown-wrapper');
	        $dropdownContainer.append($dropdown);

	        $dropdown.addClass('select2-dropdown--below');
	        $container.addClass('select2-container--below');
	      };

	      return AttachContainer;
	    });

	    S2.define('select2/dropdown/stopPropagation', [], function () {
	      function StopPropagation() {}

	      StopPropagation.prototype.bind = function (decorated, container, $container) {
	        decorated.call(this, container, $container);

	        var stoppedEvents = ['blur', 'change', 'click', 'dblclick', 'focus', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'keypress', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseover', 'mouseup', 'search', 'touchend', 'touchstart'];

	        this.$dropdown.on(stoppedEvents.join(' '), function (evt) {
	          evt.stopPropagation();
	        });
	      };

	      return StopPropagation;
	    });

	    S2.define('select2/selection/stopPropagation', [], function () {
	      function StopPropagation() {}

	      StopPropagation.prototype.bind = function (decorated, container, $container) {
	        decorated.call(this, container, $container);

	        var stoppedEvents = ['blur', 'change', 'click', 'dblclick', 'focus', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'keypress', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseover', 'mouseup', 'search', 'touchend', 'touchstart'];

	        this.$selection.on(stoppedEvents.join(' '), function (evt) {
	          evt.stopPropagation();
	        });
	      };

	      return StopPropagation;
	    });

	    /*!
	     * jQuery Mousewheel 3.1.13
	     *
	     * Copyright jQuery Foundation and other contributors
	     * Released under the MIT license
	     * http://jquery.org/license
	     */

	    (function (factory) {
	      if (typeof S2.define === 'function' && S2.define.amd) {
	        // AMD. Register as an anonymous module.
	        S2.define('jquery-mousewheel', ['jquery'], factory);
	      } else if (( false ? 'undefined' : _typeof(exports)) === 'object') {
	        // Node/CommonJS style for Browserify
	        module.exports = factory;
	      } else {
	        // Browser globals
	        factory(jQuery);
	      }
	    })(function ($) {

	      var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
	          toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
	          slice = Array.prototype.slice,
	          nullLowestDeltaTimeout,
	          lowestDelta;

	      if ($.event.fixHooks) {
	        for (var i = toFix.length; i;) {
	          $.event.fixHooks[toFix[--i]] = $.event.mouseHooks;
	        }
	      }

	      var special = $.event.special.mousewheel = {
	        version: '3.1.12',

	        setup: function setup() {
	          if (this.addEventListener) {
	            for (var i = toBind.length; i;) {
	              this.addEventListener(toBind[--i], handler, false);
	            }
	          } else {
	            this.onmousewheel = handler;
	          }
	          // Store the line height and page height for this particular element
	          $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
	          $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
	        },

	        teardown: function teardown() {
	          if (this.removeEventListener) {
	            for (var i = toBind.length; i;) {
	              this.removeEventListener(toBind[--i], handler, false);
	            }
	          } else {
	            this.onmousewheel = null;
	          }
	          // Clean up the data we added to the element
	          $.removeData(this, 'mousewheel-line-height');
	          $.removeData(this, 'mousewheel-page-height');
	        },

	        getLineHeight: function getLineHeight(elem) {
	          var $elem = $(elem),
	              $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
	          if (!$parent.length) {
	            $parent = $('body');
	          }
	          return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
	        },

	        getPageHeight: function getPageHeight(elem) {
	          return $(elem).height();
	        },

	        settings: {
	          adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
	          normalizeOffset: true // calls getBoundingClientRect for each event
	        }
	      };

	      $.fn.extend({
	        mousewheel: function mousewheel(fn) {
	          return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
	        },

	        unmousewheel: function unmousewheel(fn) {
	          return this.unbind('mousewheel', fn);
	        }
	      });

	      function handler(event) {
	        var orgEvent = event || window.event,
	            args = slice.call(arguments, 1),
	            delta = 0,
	            deltaX = 0,
	            deltaY = 0,
	            absDelta = 0,
	            offsetX = 0,
	            offsetY = 0;
	        event = $.event.fix(orgEvent);
	        event.type = 'mousewheel';

	        // Old school scrollwheel delta
	        if ('detail' in orgEvent) {
	          deltaY = orgEvent.detail * -1;
	        }
	        if ('wheelDelta' in orgEvent) {
	          deltaY = orgEvent.wheelDelta;
	        }
	        if ('wheelDeltaY' in orgEvent) {
	          deltaY = orgEvent.wheelDeltaY;
	        }
	        if ('wheelDeltaX' in orgEvent) {
	          deltaX = orgEvent.wheelDeltaX * -1;
	        }

	        // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
	        if ('axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
	          deltaX = deltaY * -1;
	          deltaY = 0;
	        }

	        // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
	        delta = deltaY === 0 ? deltaX : deltaY;

	        // New school wheel delta (wheel event)
	        if ('deltaY' in orgEvent) {
	          deltaY = orgEvent.deltaY * -1;
	          delta = deltaY;
	        }
	        if ('deltaX' in orgEvent) {
	          deltaX = orgEvent.deltaX;
	          if (deltaY === 0) {
	            delta = deltaX * -1;
	          }
	        }

	        // No change actually happened, no reason to go any further
	        if (deltaY === 0 && deltaX === 0) {
	          return;
	        }

	        // Need to convert lines and pages to pixels if we aren't already in pixels
	        // There are three delta modes:
	        //   * deltaMode 0 is by pixels, nothing to do
	        //   * deltaMode 1 is by lines
	        //   * deltaMode 2 is by pages
	        if (orgEvent.deltaMode === 1) {
	          var lineHeight = $.data(this, 'mousewheel-line-height');
	          delta *= lineHeight;
	          deltaY *= lineHeight;
	          deltaX *= lineHeight;
	        } else if (orgEvent.deltaMode === 2) {
	          var pageHeight = $.data(this, 'mousewheel-page-height');
	          delta *= pageHeight;
	          deltaY *= pageHeight;
	          deltaX *= pageHeight;
	        }

	        // Store lowest absolute delta to normalize the delta values
	        absDelta = Math.max(Math.abs(deltaY), Math.abs(deltaX));

	        if (!lowestDelta || absDelta < lowestDelta) {
	          lowestDelta = absDelta;

	          // Adjust older deltas if necessary
	          if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
	            lowestDelta /= 40;
	          }
	        }

	        // Adjust older deltas if necessary
	        if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
	          // Divide all the things by 40!
	          delta /= 40;
	          deltaX /= 40;
	          deltaY /= 40;
	        }

	        // Get a whole, normalized value for the deltas
	        delta = Math[delta >= 1 ? 'floor' : 'ceil'](delta / lowestDelta);
	        deltaX = Math[deltaX >= 1 ? 'floor' : 'ceil'](deltaX / lowestDelta);
	        deltaY = Math[deltaY >= 1 ? 'floor' : 'ceil'](deltaY / lowestDelta);

	        // Normalise offsetX and offsetY properties
	        if (special.settings.normalizeOffset && this.getBoundingClientRect) {
	          var boundingRect = this.getBoundingClientRect();
	          offsetX = event.clientX - boundingRect.left;
	          offsetY = event.clientY - boundingRect.top;
	        }

	        // Add information to the event object
	        event.deltaX = deltaX;
	        event.deltaY = deltaY;
	        event.deltaFactor = lowestDelta;
	        event.offsetX = offsetX;
	        event.offsetY = offsetY;
	        // Go ahead and set deltaMode to 0 since we converted to pixels
	        // Although this is a little odd since we overwrite the deltaX/Y
	        // properties with normalized deltas.
	        event.deltaMode = 0;

	        // Add event and delta to the front of the arguments
	        args.unshift(event, delta, deltaX, deltaY);

	        // Clearout lowestDelta after sometime to better
	        // handle multiple device types that give different
	        // a different lowestDelta
	        // Ex: trackpad = 3 and mouse wheel = 120
	        if (nullLowestDeltaTimeout) {
	          clearTimeout(nullLowestDeltaTimeout);
	        }
	        nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);

	        return ($.event.dispatch || $.event.handle).apply(this, args);
	      }

	      function nullLowestDelta() {
	        lowestDelta = null;
	      }

	      function shouldAdjustOldDeltas(orgEvent, absDelta) {
	        // If this is an older event and the delta is divisable by 120,
	        // then we are assuming that the browser is treating this as an
	        // older mouse wheel event and that we should divide the deltas
	        // by 40 to try and get a more usable deltaFactor.
	        // Side note, this actually impacts the reported scroll distance
	        // in older browsers and can cause scrolling to be slower than native.
	        // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
	        return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
	      }
	    });

	    S2.define('jquery.select2', ['jquery', 'jquery-mousewheel', './select2/core', './select2/defaults'], function ($, _, Select2, Defaults) {
	      if ($.fn.select2 == null) {
	        // All methods that should return the element
	        var thisMethods = ['open', 'close', 'destroy'];

	        $.fn.select2 = function (options) {
	          options = options || {};

	          if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
	            this.each(function () {
	              var instanceOptions = $.extend(true, {}, options);

	              var instance = new Select2($(this), instanceOptions);
	            });

	            return this;
	          } else if (typeof options === 'string') {
	            var ret;
	            var args = Array.prototype.slice.call(arguments, 1);

	            this.each(function () {
	              var instance = $(this).data('select2');

	              if (instance == null && window.console && console.error) {
	                console.error('The select2(\'' + options + '\') method was called on an ' + 'element that is not using Select2.');
	              }

	              ret = instance[options].apply(instance, args);
	            });

	            // Check if we should be returning `this`
	            if ($.inArray(options, thisMethods) > -1) {
	              return this;
	            }

	            return ret;
	          } else {
	            throw new Error('Invalid arguments for Select2: ' + options);
	          }
	        };
	      }

	      if ($.fn.select2.defaults == null) {
	        $.fn.select2.defaults = Defaults;
	      }

	      return Select2;
	    });

	    // Return the AMD loader configuration so it can be used outside of this file
	    return {
	      define: S2.define,
	      require: S2.require
	    };
	  }();

	  // Autoload the jQuery bindings
	  // We know that all of the modules exist above this, so we're safe
	  var select2 = S2.require('jquery.select2');

	  // Hold the AMD module references on the jQuery function that was just loaded
	  // This allows Select2 to use the internal loader outside of this file, such
	  // as in the language files.
	  jQuery.fn.select2.amd = S2;

	  // Return the Select2 instance for anyone who is importing it.
	  return select2;
	});

/***/ },
/* 443 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _calendar = __webpack_require__(444);

	var _calendar2 = _interopRequireDefault(_calendar);

	var _form = __webpack_require__(446);

	var _form2 = _interopRequireDefault(_form);

	var _list = __webpack_require__(447);

	var _list2 = _interopRequireDefault(_list);

	var _project_session_form = __webpack_require__(449);

	var _project_session_form2 = _interopRequireDefault(_project_session_form);

	var _project_user_list = __webpack_require__(450);

	var _project_user_list2 = _interopRequireDefault(_project_user_list);

	var _radios = __webpack_require__(451);

	var _radios2 = _interopRequireDefault(_radios);

	var _chart = __webpack_require__(452);

	var _chart2 = _interopRequireDefault(_chart);

	var _rules = __webpack_require__(453);

	var _rules2 = _interopRequireDefault(_rules);

	var _scales = __webpack_require__(454);

	var _scales2 = _interopRequireDefault(_scales);

	var _skills = __webpack_require__(456);

	var _skills2 = _interopRequireDefault(_skills);

	var _project = __webpack_require__(457);

	var _project2 = _interopRequireDefault(_project);

	var _quest_form_options = __webpack_require__(458);

	var _quest_form_options2 = _interopRequireDefault(_quest_form_options);

	var _quests_users = __webpack_require__(459);

	var _quests_users2 = _interopRequireDefault(_quests_users);

	var _answer = __webpack_require__(460);

	var _answer2 = _interopRequireDefault(_answer);

	__webpack_require__(461);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Project = function Project() {
	  _classCallCheck(this, Project);

	  (0, _answer2.default)();

	  new _calendar2.default();
	  new _form2.default();
	  new _list2.default();
	  new _project_user_list2.default();
	  new _project_session_form2.default();
	  new _radios2.default();
	  new _chart2.default();
	  new _rules2.default();
	  new _scales2.default();
	  new _skills2.default();
	  new _project2.default();
	  new _quest_form_options2.default();
	  new _quests_users2.default();
	};

	exports.default = Project;

/***/ },
/* 444 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _noty = __webpack_require__(415);

	var _noty2 = _interopRequireDefault(_noty);

	var _moment = __webpack_require__(215);

	var _moment2 = _interopRequireDefault(_moment);

	__webpack_require__(445);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Calendar = function () {
	  function Calendar() {
	    var _this = this;

	    _classCallCheck(this, Calendar);

	    if ((0, _jquery2.default)("#calendar").length === 0) return;

	    var mthis = this;
	    this._$modal = (0, _jquery2.default)('#slotSelectionModalContainer');
	    this._$calendar = (0, _jquery2.default)("#calendar");
	    this._$loading = (0, _jquery2.default)("#loading");
	    this._waitingAjax = false;

	    this.calendar = this._$calendar.fullCalendar({
	      header: {
	        left: '',
	        center: "title",
	        right: 'today prev next'
	      },
	      axisFormat: 'h:mm a',
	      defaultDate: (0, _moment2.default)(),
	      defaultView: 'agendaWeek',
	      firstDay: 1,
	      allDaySlot: false,
	      slotEventOverlap: false,
	      selectable: false,
	      selectHelper: true,
	      slotDuration: '00:30:00',
	      snapDuration: '00:15:00',

	      eventClick: function eventClick(calEvent) {
	        if (_this._waitingAjax) return;
	        var ids = calEvent.ids.split(',');

	        mthis._populateModal(ids, calEvent);
	        mthis._$modal.modal('show');
	      },

	      loading: function loading(isLoading) {
	        _this._isLoading = isLoading;
	        if (_this._isLoading) {
	          _this._intervalHandler = clearInterval(_this._intervalHandler);
	          _this._timeOutHandler = setTimeout(function (_) {
	            _this._loadingEnable = true;
	            _this._$loading.show();
	            _this._intervalHandler = setInterval(function (_) {
	              if (!_this._isLoading) {
	                _this._$loading.fadeOut();
	                _this._loadingEnable = false;
	                _this._intervalHandler = clearInterval(_this._intervalHandler);
	              }
	            }, 1000);
	          }, 100);
	        } else {
	          if (!_this._loadingEnable) clearTimeout(_this._timeOutHandler);
	        }
	      },

	      events: function events(start, end, timezone, callback) {
	        var data = {
	          'start': start.format(),
	          'end': end.format()
	        };

	        _jquery2.default.getJSON(mthis._$calendar.data('index-url'), data, function (events) {
	          callback(events);
	        });
	      }
	    });

	    this._bind();
	  }

	  _createClass(Calendar, [{
	    key: '_bind',
	    value: function _bind() {
	      this._$modal.on('hidden.bs.modal', '.btn-primary', function () {
	        (0, _jquery2.default)(this).off('.modal');
	      });
	      this._$modal.on('click.modal', '.btn-primary:not(.disable)', this._sendSelectedSession.bind(this));
	    }
	  }, {
	    key: '_sendSelectedSession',
	    value: function _sendSelectedSession() {
	      var _this2 = this;

	      var $list = this._$modal.find('.modal-body select');
	      var indexSelectedId = $list.val() >> 0;
	      var ids = $list.data('ids').split(",").slice(indexSelectedId, indexSelectedId + this._$calendar.data('duration')).join(',');
	      var url = this._$calendar.data('update-url').replace(':ids', ids);

	      this._waitingAjax = true;
	      this._$loading.show();
	      this._$modal.find('.btn-primary').addClass('disable');
	      _jquery2.default.ajax({
	        url: url,
	        type: 'post',
	        dataType: 'json',
	        data: {
	          'start': this._$calendar.fullCalendar('getView').start.format(),
	          'end': this._$calendar.fullCalendar('getView').end.format(),
	          '_method': "put"
	        },
	        success: function success(data) {
	          if (data.status == 200) document.location = _this2._$calendar.data('reload-url');
	        },
	        complete: function complete(data) {
	          _this2._showNotification(data);
	          _this2._$loading.fadeOut();
	          _this2._waitingAjax = false;
	        },
	        error: function error(_) {
	          _this2._$modal.find('.btn-primary').removeClass('disable');
	        }
	      });
	    }
	  }, {
	    key: '_populateModal',
	    value: function _populateModal(ids, event) {
	      var saveStartMoment = (0, _moment2.default)(event._start);
	      var nbSlot = this._$calendar.data('duration');
	      var slotDuration = 15;
	      var $list = this._$modal.find('.modal-body select');
	      var nbChoices = ids.length - nbSlot + 1;
	      var i = 0;

	      $list.empty();
	      while (i < nbChoices) {
	        $list.append((0, _jquery2.default)('<option value="' + i + '"> From ' + event._start.format('LT') + ' to ' + event._start.add(slotDuration * nbSlot, 'm').format('LT') + ' </option>'));
	        event._start.subtract((nbSlot - 1) * slotDuration, 'm');
	        i += 1;
	      }
	      event._start = saveStartMoment;
	      $list.data('ids', ids.join(','));
	    }

	    // show notif

	  }, {
	    key: '_showNotification',
	    value: function _showNotification(data) {
	      if (data.responseJSON) data = data.responseJSON;else {
	        data = {
	          status: 500,
	          message: 'Error'
	        };
	      }
	      (0, _noty2.default)({
	        layout: 'topRight',
	        type: data.status == 200 ? 'success' : 'error',
	        text: data.message,
	        timeout: 4000
	      });
	    }
	  }]);

	  return Calendar;
	}();

	exports.default = Calendar;

/***/ },
/* 445 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
	 * FullCalendar v3.0.0-beta
	 * Docs & License: http://fullcalendar.io/
	 * (c) 2016 Adam Shaw
	 */

	(function(factory) {
		if (true) {
			!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(5), __webpack_require__(215) ], __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 if (typeof exports === 'object') { // Node/CommonJS
			module.exports = factory(require('jquery'), require('moment'));
		}
		else {
			factory(jQuery, moment);
		}
	})(function($, moment) {

	;;

	var FC = $.fullCalendar = {
		version: "3.0.0-beta",
		internalApiVersion: 5
	};
	var fcViews = FC.views = {};


	$.fn.fullCalendar = function(options) {
		var args = Array.prototype.slice.call(arguments, 1); // for a possible method call
		var res = this; // what this function will return (this jQuery object by default)

		this.each(function(i, _element) { // loop each DOM element involved
			var element = $(_element);
			var calendar = element.data('fullCalendar'); // get the existing calendar object (if any)
			var singleRes; // the returned value of this single method call

			// a method call
			if (typeof options === 'string') {
				if (calendar && $.isFunction(calendar[options])) {
					singleRes = calendar[options].apply(calendar, args);
					if (!i) {
						res = singleRes; // record the first method call result
					}
					if (options === 'destroy') { // for the destroy method, must remove Calendar object data
						element.removeData('fullCalendar');
					}
				}
			}
			// a new calendar initialization
			else if (!calendar) { // don't initialize twice
				calendar = new Calendar(element, options);
				element.data('fullCalendar', calendar);
				calendar.render();
			}
		});
		
		return res;
	};


	var complexOptions = [ // names of options that are objects whose properties should be combined
		'header',
		'buttonText',
		'buttonIcons',
		'themeButtonIcons'
	];


	// Merges an array of option objects into a single object
	function mergeOptions(optionObjs) {
		return mergeProps(optionObjs, complexOptions);
	}


	// Given options specified for the calendar's constructor, massages any legacy options into a non-legacy form.
	// Converts View-Option-Hashes into the View-Specific-Options format.
	function massageOverrides(input) {
		var overrides = { views: input.views || {} }; // the output. ensure a `views` hash
		var subObj;

		// iterate through all option override properties (except `views`)
		$.each(input, function(name, val) {
			if (name != 'views') {

				// could the value be a legacy View-Option-Hash?
				if (
					$.isPlainObject(val) &&
					!/(time|duration|interval)$/i.test(name) && // exclude duration options. might be given as objects
					$.inArray(name, complexOptions) == -1 // complex options aren't allowed to be View-Option-Hashes
				) {
					subObj = null;

					// iterate through the properties of this possible View-Option-Hash value
					$.each(val, function(subName, subVal) {

						// is the property targeting a view?
						if (/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(subName)) {
							if (!overrides.views[subName]) { // ensure the view-target entry exists
								overrides.views[subName] = {};
							}
							overrides.views[subName][name] = subVal; // record the value in the `views` object
						}
						else { // a non-View-Option-Hash property
							if (!subObj) {
								subObj = {};
							}
							subObj[subName] = subVal; // accumulate these unrelated values for later
						}
					});

					if (subObj) { // non-View-Option-Hash properties? transfer them as-is
						overrides[name] = subObj;
					}
				}
				else {
					overrides[name] = val; // transfer normal options as-is
				}
			}
		});

		return overrides;
	}

	;;

	// exports
	FC.intersectRanges = intersectRanges;
	FC.applyAll = applyAll;
	FC.debounce = debounce;
	FC.isInt = isInt;
	FC.htmlEscape = htmlEscape;
	FC.cssToStr = cssToStr;
	FC.proxy = proxy;
	FC.capitaliseFirstLetter = capitaliseFirstLetter;


	/* FullCalendar-specific DOM Utilities
	----------------------------------------------------------------------------------------------------------------------*/


	// Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left
	// and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that.
	function compensateScroll(rowEls, scrollbarWidths) {
		if (scrollbarWidths.left) {
			rowEls.css({
				'border-left-width': 1,
				'margin-left': scrollbarWidths.left - 1
			});
		}
		if (scrollbarWidths.right) {
			rowEls.css({
				'border-right-width': 1,
				'margin-right': scrollbarWidths.right - 1
			});
		}
	}


	// Undoes compensateScroll and restores all borders/margins
	function uncompensateScroll(rowEls) {
		rowEls.css({
			'margin-left': '',
			'margin-right': '',
			'border-left-width': '',
			'border-right-width': ''
		});
	}


	// Make the mouse cursor express that an event is not allowed in the current area
	function disableCursor() {
		$('body').addClass('fc-not-allowed');
	}


	// Returns the mouse cursor to its original look
	function enableCursor() {
		$('body').removeClass('fc-not-allowed');
	}


	// Given a total available height to fill, have `els` (essentially child rows) expand to accomodate.
	// By default, all elements that are shorter than the recommended height are expanded uniformly, not considering
	// any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and 
	// reduces the available height.
	function distributeHeight(els, availableHeight, shouldRedistribute) {

		// *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions,
		// and it is better to be shorter than taller, to avoid creating unnecessary scrollbars.

		var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element
		var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE*
		var flexEls = []; // elements that are allowed to expand. array of DOM nodes
		var flexOffsets = []; // amount of vertical space it takes up
		var flexHeights = []; // actual css height
		var usedHeight = 0;

		undistributeHeight(els); // give all elements their natural height

		// find elements that are below the recommended height (expandable).
		// important to query for heights in a single first pass (to avoid reflow oscillation).
		els.each(function(i, el) {
			var minOffset = i === els.length - 1 ? minOffset2 : minOffset1;
			var naturalOffset = $(el).outerHeight(true);

			if (naturalOffset < minOffset) {
				flexEls.push(el);
				flexOffsets.push(naturalOffset);
				flexHeights.push($(el).height());
			}
			else {
				// this element stretches past recommended height (non-expandable). mark the space as occupied.
				usedHeight += naturalOffset;
			}
		});

		// readjust the recommended height to only consider the height available to non-maxed-out rows.
		if (shouldRedistribute) {
			availableHeight -= usedHeight;
			minOffset1 = Math.floor(availableHeight / flexEls.length);
			minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE*
		}

		// assign heights to all expandable elements
		$(flexEls).each(function(i, el) {
			var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1;
			var naturalOffset = flexOffsets[i];
			var naturalHeight = flexHeights[i];
			var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding

			if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things
				$(el).height(newHeight);
			}
		});
	}


	// Undoes distrubuteHeight, restoring all els to their natural height
	function undistributeHeight(els) {
		els.height('');
	}


	// Given `els`, a jQuery set of <td> cells, find the cell with the largest natural width and set the widths of all the
	// cells to be that width.
	// PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline
	function matchCellWidths(els) {
		var maxInnerWidth = 0;

		els.find('> span').each(function(i, innerEl) {
			var innerWidth = $(innerEl).outerWidth();
			if (innerWidth > maxInnerWidth) {
				maxInnerWidth = innerWidth;
			}
		});

		maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance

		els.width(maxInnerWidth);

		return maxInnerWidth;
	}


	// Given one element that resides inside another,
	// Subtracts the height of the inner element from the outer element.
	function subtractInnerElHeight(outerEl, innerEl) {
		var both = outerEl.add(innerEl);
		var diff;

		// effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked
		both.css({
			position: 'relative', // cause a reflow, which will force fresh dimension recalculation
			left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll
		});
		diff = outerEl.outerHeight() - innerEl.outerHeight(); // grab the dimensions
		both.css({ position: '', left: '' }); // undo hack

		return diff;
	}


	/* Element Geom Utilities
	----------------------------------------------------------------------------------------------------------------------*/

	FC.getOuterRect = getOuterRect;
	FC.getClientRect = getClientRect;
	FC.getContentRect = getContentRect;
	FC.getScrollbarWidths = getScrollbarWidths;


	// borrowed from https://github.com/jquery/jquery-ui/blob/1.11.0/ui/core.js#L51
	function getScrollParent(el) {
		var position = el.css('position'),
			scrollParent = el.parents().filter(function() {
				var parent = $(this);
				return (/(auto|scroll)/).test(
					parent.css('overflow') + parent.css('overflow-y') + parent.css('overflow-x')
				);
			}).eq(0);

		return position === 'fixed' || !scrollParent.length ? $(el[0].ownerDocument || document) : scrollParent;
	}


	// Queries the outer bounding area of a jQuery element.
	// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
	// Origin is optional.
	function getOuterRect(el, origin) {
		var offset = el.offset();
		var left = offset.left - (origin ? origin.left : 0);
		var top = offset.top - (origin ? origin.top : 0);

		return {
			left: left,
			right: left + el.outerWidth(),
			top: top,
			bottom: top + el.outerHeight()
		};
	}


	// Queries the area within the margin/border/scrollbars of a jQuery element. Does not go within the padding.
	// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
	// Origin is optional.
	// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser.
	function getClientRect(el, origin) {
		var offset = el.offset();
		var scrollbarWidths = getScrollbarWidths(el);
		var left = offset.left + getCssFloat(el, 'border-left-width') + scrollbarWidths.left - (origin ? origin.left : 0);
		var top = offset.top + getCssFloat(el, 'border-top-width') + scrollbarWidths.top - (origin ? origin.top : 0);

		return {
			left: left,
			right: left + el[0].clientWidth, // clientWidth includes padding but NOT scrollbars
			top: top,
			bottom: top + el[0].clientHeight // clientHeight includes padding but NOT scrollbars
		};
	}


	// Queries the area within the margin/border/padding of a jQuery element. Assumed not to have scrollbars.
	// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
	// Origin is optional.
	function getContentRect(el, origin) {
		var offset = el.offset(); // just outside of border, margin not included
		var left = offset.left + getCssFloat(el, 'border-left-width') + getCssFloat(el, 'padding-left') -
			(origin ? origin.left : 0);
		var top = offset.top + getCssFloat(el, 'border-top-width') + getCssFloat(el, 'padding-top') -
			(origin ? origin.top : 0);

		return {
			left: left,
			right: left + el.width(),
			top: top,
			bottom: top + el.height()
		};
	}


	// Returns the computed left/right/top/bottom scrollbar widths for the given jQuery element.
	// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser.
	function getScrollbarWidths(el) {
		var leftRightWidth = el.innerWidth() - el[0].clientWidth; // the paddings cancel out, leaving the scrollbars
		var widths = {
			left: 0,
			right: 0,
			top: 0,
			bottom: el.innerHeight() - el[0].clientHeight // the paddings cancel out, leaving the bottom scrollbar
		};

		if (getIsLeftRtlScrollbars() && el.css('direction') == 'rtl') { // is the scrollbar on the left side?
			widths.left = leftRightWidth;
		}
		else {
			widths.right = leftRightWidth;
		}

		return widths;
	}


	// Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side

	var _isLeftRtlScrollbars = null;

	function getIsLeftRtlScrollbars() { // responsible for caching the computation
		if (_isLeftRtlScrollbars === null) {
			_isLeftRtlScrollbars = computeIsLeftRtlScrollbars();
		}
		return _isLeftRtlScrollbars;
	}

	function computeIsLeftRtlScrollbars() { // creates an offscreen test element, then removes it
		var el = $('<div><div/></div>')
			.css({
				position: 'absolute',
				top: -1000,
				left: 0,
				border: 0,
				padding: 0,
				overflow: 'scroll',
				direction: 'rtl'
			})
			.appendTo('body');
		var innerEl = el.children();
		var res = innerEl.offset().left > el.offset().left; // is the inner div shifted to accommodate a left scrollbar?
		el.remove();
		return res;
	}


	// Retrieves a jQuery element's computed CSS value as a floating-point number.
	// If the queried value is non-numeric (ex: IE can return "medium" for border width), will just return zero.
	function getCssFloat(el, prop) {
		return parseFloat(el.css(prop)) || 0;
	}


	/* Mouse / Touch Utilities
	----------------------------------------------------------------------------------------------------------------------*/

	FC.preventDefault = preventDefault;


	// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
	function isPrimaryMouseButton(ev) {
		return ev.which == 1 && !ev.ctrlKey;
	}


	function getEvX(ev) {
		if (ev.pageX !== undefined) {
			return ev.pageX;
		}
		var touches = ev.originalEvent.touches;
		if (touches) {
			return touches[0].pageX;
		}
	}


	function getEvY(ev) {
		if (ev.pageY !== undefined) {
			return ev.pageY;
		}
		var touches = ev.originalEvent.touches;
		if (touches) {
			return touches[0].pageY;
		}
	}


	function getEvIsTouch(ev) {
		return /^touch/.test(ev.type);
	}


	function preventSelection(el) {
		el.addClass('fc-unselectable')
			.on('selectstart', preventDefault);
	}


	// Stops a mouse/touch event from doing it's native browser action
	function preventDefault(ev) {
		ev.preventDefault();
	}


	// attach a handler to get called when ANY scroll action happens on the page.
	// this was impossible to do with normal on/off because 'scroll' doesn't bubble.
	// http://stackoverflow.com/a/32954565/96342
	// returns `true` on success.
	function bindAnyScroll(handler) {
		if (window.addEventListener) {
			window.addEventListener('scroll', handler, true); // useCapture=true
			return true;
		}
		return false;
	}


	// undoes bindAnyScroll. must pass in the original function.
	// returns `true` on success.
	function unbindAnyScroll(handler) {
		if (window.removeEventListener) {
			window.removeEventListener('scroll', handler, true); // useCapture=true
			return true;
		}
		return false;
	}


	/* General Geometry Utils
	----------------------------------------------------------------------------------------------------------------------*/

	FC.intersectRects = intersectRects;

	// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
	function intersectRects(rect1, rect2) {
		var res = {
			left: Math.max(rect1.left, rect2.left),
			right: Math.min(rect1.right, rect2.right),
			top: Math.max(rect1.top, rect2.top),
			bottom: Math.min(rect1.bottom, rect2.bottom)
		};

		if (res.left < res.right && res.top < res.bottom) {
			return res;
		}
		return false;
	}


	// Returns a new point that will have been moved to reside within the given rectangle
	function constrainPoint(point, rect) {
		return {
			left: Math.min(Math.max(point.left, rect.left), rect.right),
			top: Math.min(Math.max(point.top, rect.top), rect.bottom)
		};
	}


	// Returns a point that is the center of the given rectangle
	function getRectCenter(rect) {
		return {
			left: (rect.left + rect.right) / 2,
			top: (rect.top + rect.bottom) / 2
		};
	}


	// Subtracts point2's coordinates from point1's coordinates, returning a delta
	function diffPoints(point1, point2) {
		return {
			left: point1.left - point2.left,
			top: point1.top - point2.top
		};
	}


	/* Object Ordering by Field
	----------------------------------------------------------------------------------------------------------------------*/

	FC.parseFieldSpecs = parseFieldSpecs;
	FC.compareByFieldSpecs = compareByFieldSpecs;
	FC.compareByFieldSpec = compareByFieldSpec;
	FC.flexibleCompare = flexibleCompare;


	function parseFieldSpecs(input) {
		var specs = [];
		var tokens = [];
		var i, token;

		if (typeof input === 'string') {
			tokens = input.split(/\s*,\s*/);
		}
		else if (typeof input === 'function') {
			tokens = [ input ];
		}
		else if ($.isArray(input)) {
			tokens = input;
		}

		for (i = 0; i < tokens.length; i++) {
			token = tokens[i];

			if (typeof token === 'string') {
				specs.push(
					token.charAt(0) == '-' ?
						{ field: token.substring(1), order: -1 } :
						{ field: token, order: 1 }
				);
			}
			else if (typeof token === 'function') {
				specs.push({ func: token });
			}
		}

		return specs;
	}


	function compareByFieldSpecs(obj1, obj2, fieldSpecs) {
		var i;
		var cmp;

		for (i = 0; i < fieldSpecs.length; i++) {
			cmp = compareByFieldSpec(obj1, obj2, fieldSpecs[i]);
			if (cmp) {
				return cmp;
			}
		}

		return 0;
	}


	function compareByFieldSpec(obj1, obj2, fieldSpec) {
		if (fieldSpec.func) {
			return fieldSpec.func(obj1, obj2);
		}
		return flexibleCompare(obj1[fieldSpec.field], obj2[fieldSpec.field]) *
			(fieldSpec.order || 1);
	}


	function flexibleCompare(a, b) {
		if (!a && !b) {
			return 0;
		}
		if (b == null) {
			return -1;
		}
		if (a == null) {
			return 1;
		}
		if ($.type(a) === 'string' || $.type(b) === 'string') {
			return String(a).localeCompare(String(b));
		}
		return a - b;
	}


	/* FullCalendar-specific Misc Utilities
	----------------------------------------------------------------------------------------------------------------------*/


	// Computes the intersection of the two ranges. Will return fresh date clones in a range.
	// Returns undefined if no intersection.
	// Expects all dates to be normalized to the same timezone beforehand.
	// TODO: move to date section?
	function intersectRanges(subjectRange, constraintRange) {
		var subjectStart = subjectRange.start;
		var subjectEnd = subjectRange.end;
		var constraintStart = constraintRange.start;
		var constraintEnd = constraintRange.end;
		var segStart, segEnd;
		var isStart, isEnd;

		if (subjectEnd > constraintStart && subjectStart < constraintEnd) { // in bounds at all?

			if (subjectStart >= constraintStart) {
				segStart = subjectStart.clone();
				isStart = true;
			}
			else {
				segStart = constraintStart.clone();
				isStart =  false;
			}

			if (subjectEnd <= constraintEnd) {
				segEnd = subjectEnd.clone();
				isEnd = true;
			}
			else {
				segEnd = constraintEnd.clone();
				isEnd = false;
			}

			return {
				start: segStart,
				end: segEnd,
				isStart: isStart,
				isEnd: isEnd
			};
		}
	}


	/* Date Utilities
	----------------------------------------------------------------------------------------------------------------------*/

	FC.computeIntervalUnit = computeIntervalUnit;
	FC.divideRangeByDuration = divideRangeByDuration;
	FC.divideDurationByDuration = divideDurationByDuration;
	FC.multiplyDuration = multiplyDuration;
	FC.durationHasTime = durationHasTime;

	var dayIDs = [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ];
	var intervalUnits = [ 'year', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond' ];


	// Diffs the two moments into a Duration where full-days are recorded first, then the remaining time.
	// Moments will have their timezones normalized.
	function diffDayTime(a, b) {
		return moment.duration({
			days: a.clone().stripTime().diff(b.clone().stripTime(), 'days'),
			ms: a.time() - b.time() // time-of-day from day start. disregards timezone
		});
	}


	// Diffs the two moments via their start-of-day (regardless of timezone). Produces whole-day durations.
	function diffDay(a, b) {
		return moment.duration({
			days: a.clone().stripTime().diff(b.clone().stripTime(), 'days')
		});
	}


	// Diffs two moments, producing a duration, made of a whole-unit-increment of the given unit. Uses rounding.
	function diffByUnit(a, b, unit) {
		return moment.duration(
			Math.round(a.diff(b, unit, true)), // returnFloat=true
			unit
		);
	}


	// Computes the unit name of the largest whole-unit period of time.
	// For example, 48 hours will be "days" whereas 49 hours will be "hours".
	// Accepts start/end, a range object, or an original duration object.
	function computeIntervalUnit(start, end) {
		var i, unit;
		var val;

		for (i = 0; i < intervalUnits.length; i++) {
			unit = intervalUnits[i];
			val = computeRangeAs(unit, start, end);

			if (val >= 1 && isInt(val)) {
				break;
			}
		}

		return unit; // will be "milliseconds" if nothing else matches
	}


	// Computes the number of units (like "hours") in the given range.
	// Range can be a {start,end} object, separate start/end args, or a Duration.
	// Results are based on Moment's .as() and .diff() methods, so results can depend on internal handling
	// of month-diffing logic (which tends to vary from version to version).
	function computeRangeAs(unit, start, end) {

		if (end != null) { // given start, end
			return end.diff(start, unit, true);
		}
		else if (moment.isDuration(start)) { // given duration
			return start.as(unit);
		}
		else { // given { start, end } range object
			return start.end.diff(start.start, unit, true);
		}
	}


	// Intelligently divides a range (specified by a start/end params) by a duration
	function divideRangeByDuration(start, end, dur) {
		var months;

		if (durationHasTime(dur)) {
			return (end - start) / dur;
		}
		months = dur.asMonths();
		if (Math.abs(months) >= 1 && isInt(months)) {
			return end.diff(start, 'months', true) / months;
		}
		return end.diff(start, 'days', true) / dur.asDays();
	}


	// Intelligently divides one duration by another
	function divideDurationByDuration(dur1, dur2) {
		var months1, months2;

		if (durationHasTime(dur1) || durationHasTime(dur2)) {
			return dur1 / dur2;
		}
		months1 = dur1.asMonths();
		months2 = dur2.asMonths();
		if (
			Math.abs(months1) >= 1 && isInt(months1) &&
			Math.abs(months2) >= 1 && isInt(months2)
		) {
			return months1 / months2;
		}
		return dur1.asDays() / dur2.asDays();
	}


	// Intelligently multiplies a duration by a number
	function multiplyDuration(dur, n) {
		var months;

		if (durationHasTime(dur)) {
			return moment.duration(dur * n);
		}
		months = dur.asMonths();
		if (Math.abs(months) >= 1 && isInt(months)) {
			return moment.duration({ months: months * n });
		}
		return moment.duration({ days: dur.asDays() * n });
	}


	// Returns a boolean about whether the given duration has any time parts (hours/minutes/seconds/ms)
	function durationHasTime(dur) {
		return Boolean(dur.hours() || dur.minutes() || dur.seconds() || dur.milliseconds());
	}


	function isNativeDate(input) {
		return  Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date;
	}


	// Returns a boolean about whether the given input is a time string, like "06:40:00" or "06:00"
	function isTimeString(str) {
		return /^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(str);
	}


	/* Logging and Debug
	----------------------------------------------------------------------------------------------------------------------*/

	FC.log = function() {
		var console = window.console;

		if (console && console.log) {
			return console.log.apply(console, arguments);
		}
	};

	FC.warn = function() {
		var console = window.console;

		if (console && console.warn) {
			return console.warn.apply(console, arguments);
		}
		else {
			return FC.log.apply(FC, arguments);
		}
	};


	/* General Utilities
	----------------------------------------------------------------------------------------------------------------------*/

	var hasOwnPropMethod = {}.hasOwnProperty;


	// Merges an array of objects into a single object.
	// The second argument allows for an array of property names who's object values will be merged together.
	function mergeProps(propObjs, complexProps) {
		var dest = {};
		var i, name;
		var complexObjs;
		var j, val;
		var props;

		if (complexProps) {
			for (i = 0; i < complexProps.length; i++) {
				name = complexProps[i];
				complexObjs = [];

				// collect the trailing object values, stopping when a non-object is discovered
				for (j = propObjs.length - 1; j >= 0; j--) {
					val = propObjs[j][name];

					if (typeof val === 'object') {
						complexObjs.unshift(val);
					}
					else if (val !== undefined) {
						dest[name] = val; // if there were no objects, this value will be used
						break;
					}
				}

				// if the trailing values were objects, use the merged value
				if (complexObjs.length) {
					dest[name] = mergeProps(complexObjs);
				}
			}
		}

		// copy values into the destination, going from last to first
		for (i = propObjs.length - 1; i >= 0; i--) {
			props = propObjs[i];

			for (name in props) {
				if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
					dest[name] = props[name];
				}
			}
		}

		return dest;
	}


	// Create an object that has the given prototype. Just like Object.create
	function createObject(proto) {
		var f = function() {};
		f.prototype = proto;
		return new f();
	}


	function copyOwnProps(src, dest) {
		for (var name in src) {
			if (hasOwnProp(src, name)) {
				dest[name] = src[name];
			}
		}
	}


	function hasOwnProp(obj, name) {
		return hasOwnPropMethod.call(obj, name);
	}


	// Is the given value a non-object non-function value?
	function isAtomic(val) {
		return /undefined|null|boolean|number|string/.test($.type(val));
	}


	function applyAll(functions, thisObj, args) {
		if ($.isFunction(functions)) {
			functions = [ functions ];
		}
		if (functions) {
			var i;
			var ret;
			for (i=0; i<functions.length; i++) {
				ret = functions[i].apply(thisObj, args) || ret;
			}
			return ret;
		}
	}


	function firstDefined() {
		for (var i=0; i<arguments.length; i++) {
			if (arguments[i] !== undefined) {
				return arguments[i];
			}
		}
	}


	function htmlEscape(s) {
		return (s + '').replace(/&/g, '&amp;')
			.replace(/</g, '&lt;')
			.replace(/>/g, '&gt;')
			.replace(/'/g, '&#039;')
			.replace(/"/g, '&quot;')
			.replace(/\n/g, '<br />');
	}


	function stripHtmlEntities(text) {
		return text.replace(/&.*?;/g, '');
	}


	// Given a hash of CSS properties, returns a string of CSS.
	// Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values.
	function cssToStr(cssProps) {
		var statements = [];

		$.each(cssProps, function(name, val) {
			if (val != null) {
				statements.push(name + ':' + val);
			}
		});

		return statements.join(';');
	}


	function capitaliseFirstLetter(str) {
		return str.charAt(0).toUpperCase() + str.slice(1);
	}


	function compareNumbers(a, b) { // for .sort()
		return a - b;
	}


	function isInt(n) {
		return n % 1 === 0;
	}


	// Returns a method bound to the given object context.
	// Just like one of the jQuery.proxy signatures, but without the undesired behavior of treating the same method with
	// different contexts as identical when binding/unbinding events.
	function proxy(obj, methodName) {
		var method = obj[methodName];

		return function() {
			return method.apply(obj, arguments);
		};
	}


	// 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.
	// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714
	function debounce(func, wait, immediate) {
		var timeout, args, context, timestamp, result;

		var later = function() {
			var last = +new Date() - timestamp;
			if (last < wait) {
				timeout = setTimeout(later, wait - last);
			}
			else {
				timeout = null;
				if (!immediate) {
					result = func.apply(context, args);
					context = args = null;
				}
			}
		};

		return function() {
			context = this;
			args = arguments;
			timestamp = +new Date();
			var callNow = immediate && !timeout;
			if (!timeout) {
				timeout = setTimeout(later, wait);
			}
			if (callNow) {
				result = func.apply(context, args);
				context = args = null;
			}
			return result;
		};
	}


	// HACK around jQuery's now A+ promises: execute callback synchronously if already resolved.
	// thenFunc shouldn't accept args.
	// similar to whenResources in Scheduler plugin.
	function syncThen(promise, thenFunc) {
		// not a promise, or an already-resolved promise?
		if (!promise || !promise.then || promise.state() === 'resolved') {
			return $.when(thenFunc()); // resolve immediately
		}
		else if (thenFunc) {
			return promise.then(thenFunc);
		}
	}

	;;

	/*
	GENERAL NOTE on moments throughout the *entire rest* of the codebase:
	All moments are assumed to be ambiguously-zoned unless otherwise noted,
	with the NOTABLE EXCEOPTION of start/end dates that live on *Event Objects*.
	Ambiguously-TIMED moments are assumed to be ambiguously-zoned by nature.
	*/

	var ambigDateOfMonthRegex = /^\s*\d{4}-\d\d$/;
	var ambigTimeOrZoneRegex =
		/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/;
	var newMomentProto = moment.fn; // where we will attach our new methods
	var oldMomentProto = $.extend({}, newMomentProto); // copy of original moment methods

	// tell momentjs to transfer these properties upon clone
	var momentProperties = moment.momentProperties;
	momentProperties.push('_fullCalendar');
	momentProperties.push('_ambigTime');
	momentProperties.push('_ambigZone');


	// Creating
	// -------------------------------------------------------------------------------------------------

	// Creates a new moment, similar to the vanilla moment(...) constructor, but with
	// extra features (ambiguous time, enhanced formatting). When given an existing moment,
	// it will function as a clone (and retain the zone of the moment). Anything else will
	// result in a moment in the local zone.
	FC.moment = function() {
		return makeMoment(arguments);
	};

	// Sames as FC.moment, but forces the resulting moment to be in the UTC timezone.
	FC.moment.utc = function() {
		var mom = makeMoment(arguments, true);

		// Force it into UTC because makeMoment doesn't guarantee it
		// (if given a pre-existing moment for example)
		if (mom.hasTime()) { // don't give ambiguously-timed moments a UTC zone
			mom.utc();
		}

		return mom;
	};

	// Same as FC.moment, but when given an ISO8601 string, the timezone offset is preserved.
	// ISO8601 strings with no timezone offset will become ambiguously zoned.
	FC.moment.parseZone = function() {
		return makeMoment(arguments, true, true);
	};

	// Builds an enhanced moment from args. When given an existing moment, it clones. When given a
	// native Date, or called with no arguments (the current time), the resulting moment will be local.
	// Anything else needs to be "parsed" (a string or an array), and will be affected by:
	//    parseAsUTC - if there is no zone information, should we parse the input in UTC?
	//    parseZone - if there is zone information, should we force the zone of the moment?
	function makeMoment(args, parseAsUTC, parseZone) {
		var input = args[0];
		var isSingleString = args.length == 1 && typeof input === 'string';
		var isAmbigTime;
		var isAmbigZone;
		var ambigMatch;
		var mom;

		if (moment.isMoment(input) || isNativeDate(input) || input === undefined) {
			mom = moment.apply(null, args);
		}
		else { // "parsing" is required
			isAmbigTime = false;
			isAmbigZone = false;

			if (isSingleString) {
				if (ambigDateOfMonthRegex.test(input)) {
					// accept strings like '2014-05', but convert to the first of the month
					input += '-01';
					args = [ input ]; // for when we pass it on to moment's constructor
					isAmbigTime = true;
					isAmbigZone = true;
				}
				else if ((ambigMatch = ambigTimeOrZoneRegex.exec(input))) {
					isAmbigTime = !ambigMatch[5]; // no time part?
					isAmbigZone = true;
				}
			}
			else if ($.isArray(input)) {
				// arrays have no timezone information, so assume ambiguous zone
				isAmbigZone = true;
			}
			// otherwise, probably a string with a format

			if (parseAsUTC || isAmbigTime) {
				mom = moment.utc.apply(moment, args);
			}
			else {
				mom = moment.apply(null, args);
			}

			if (isAmbigTime) {
				mom._ambigTime = true;
				mom._ambigZone = true; // ambiguous time always means ambiguous zone
			}
			else if (parseZone) { // let's record the inputted zone somehow
				if (isAmbigZone) {
					mom._ambigZone = true;
				}
				else if (isSingleString) {
					mom.utcOffset(input); // if not a valid zone, will assign UTC
				}
			}
		}

		mom._fullCalendar = true; // flag for extended functionality

		return mom;
	}


	// Week Number
	// -------------------------------------------------------------------------------------------------


	// Returns the week number, considering the locale's custom week number calcuation
	// `weeks` is an alias for `week`
	newMomentProto.week = newMomentProto.weeks = function(input) {
		var weekCalc = this._locale._fullCalendar_weekCalc;

		if (input == null && typeof weekCalc === 'function') { // custom function only works for getter
			return weekCalc(this);
		}
		else if (weekCalc === 'ISO') {
			return oldMomentProto.isoWeek.apply(this, arguments); // ISO getter/setter
		}

		return oldMomentProto.week.apply(this, arguments); // local getter/setter
	};


	// Time-of-day
	// -------------------------------------------------------------------------------------------------

	// GETTER
	// Returns a Duration with the hours/minutes/seconds/ms values of the moment.
	// If the moment has an ambiguous time, a duration of 00:00 will be returned.
	//
	// SETTER
	// You can supply a Duration, a Moment, or a Duration-like argument.
	// When setting the time, and the moment has an ambiguous time, it then becomes unambiguous.
	newMomentProto.time = function(time) {

		// Fallback to the original method (if there is one) if this moment wasn't created via FullCalendar.
		// `time` is a generic enough method name where this precaution is necessary to avoid collisions w/ other plugins.
		if (!this._fullCalendar) {
			return oldMomentProto.time.apply(this, arguments);
		}

		if (time == null) { // getter
			return moment.duration({
				hours: this.hours(),
				minutes: this.minutes(),
				seconds: this.seconds(),
				milliseconds: this.milliseconds()
			});
		}
		else { // setter

			this._ambigTime = false; // mark that the moment now has a time

			if (!moment.isDuration(time) && !moment.isMoment(time)) {
				time = moment.duration(time);
			}

			// The day value should cause overflow (so 24 hours becomes 00:00:00 of next day).
			// Only for Duration times, not Moment times.
			var dayHours = 0;
			if (moment.isDuration(time)) {
				dayHours = Math.floor(time.asDays()) * 24;
			}

			// We need to set the individual fields.
			// Can't use startOf('day') then add duration. In case of DST at start of day.
			return this.hours(dayHours + time.hours())
				.minutes(time.minutes())
				.seconds(time.seconds())
				.milliseconds(time.milliseconds());
		}
	};

	// Converts the moment to UTC, stripping out its time-of-day and timezone offset,
	// but preserving its YMD. A moment with a stripped time will display no time
	// nor timezone offset when .format() is called.
	newMomentProto.stripTime = function() {

		if (!this._ambigTime) {

			this.utc(true); // keepLocalTime=true (for keeping *date* value)

			// set time to zero
			this.set({
				hours: 0,
				minutes: 0,
				seconds: 0,
				ms: 0
			});

			// Mark the time as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),
			// which clears all ambig flags.
			this._ambigTime = true;
			this._ambigZone = true; // if ambiguous time, also ambiguous timezone offset
		}

		return this; // for chaining
	};

	// Returns if the moment has a non-ambiguous time (boolean)
	newMomentProto.hasTime = function() {
		return !this._ambigTime;
	};


	// Timezone
	// -------------------------------------------------------------------------------------------------

	// Converts the moment to UTC, stripping out its timezone offset, but preserving its
	// YMD and time-of-day. A moment with a stripped timezone offset will display no
	// timezone offset when .format() is called.
	newMomentProto.stripZone = function() {
		var wasAmbigTime;

		if (!this._ambigZone) {

			wasAmbigTime = this._ambigTime;

			this.utc(true); // keepLocalTime=true (for keeping date and time values)

			// the above call to .utc()/.utcOffset() unfortunately might clear the ambig flags, so restore
			this._ambigTime = wasAmbigTime || false;

			// Mark the zone as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),
			// which clears the ambig flags.
			this._ambigZone = true;
		}

		return this; // for chaining
	};

	// Returns of the moment has a non-ambiguous timezone offset (boolean)
	newMomentProto.hasZone = function() {
		return !this._ambigZone;
	};


	// implicitly marks a zone
	newMomentProto.local = function(keepLocalTime) {

		// for when converting from ambiguously-zoned to local,
		// keep the time values when converting from UTC -> local
		oldMomentProto.local.call(this, this._ambigZone || keepLocalTime);

		// ensure non-ambiguous
		// this probably already happened via local() -> utcOffset(), but don't rely on Moment's internals
		this._ambigTime = false;
		this._ambigZone = false;

		return this; // for chaining
	};


	// implicitly marks a zone
	newMomentProto.utc = function(keepLocalTime) {

		oldMomentProto.utc.call(this, keepLocalTime);

		// ensure non-ambiguous
		// this probably already happened via utc() -> utcOffset(), but don't rely on Moment's internals
		this._ambigTime = false;
		this._ambigZone = false;

		return this;
	};


	// implicitly marks a zone (will probably get called upon .utc() and .local())
	newMomentProto.utcOffset = function(tzo) {

		if (tzo != null) { // setter
			// these assignments needs to happen before the original zone method is called.
			// I forget why, something to do with a browser crash.
			this._ambigTime = false;
			this._ambigZone = false;
		}

		return oldMomentProto.utcOffset.apply(this, arguments);
	};


	// Formatting
	// -------------------------------------------------------------------------------------------------

	newMomentProto.format = function() {
		if (this._fullCalendar && arguments[0]) { // an enhanced moment? and a format string provided?
			return formatDate(this, arguments[0]); // our extended formatting
		}
		if (this._ambigTime) {
			return oldMomentFormat(this, 'YYYY-MM-DD');
		}
		if (this._ambigZone) {
			return oldMomentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');
		}
		return oldMomentProto.format.apply(this, arguments);
	};

	newMomentProto.toISOString = function() {
		if (this._ambigTime) {
			return oldMomentFormat(this, 'YYYY-MM-DD');
		}
		if (this._ambigZone) {
			return oldMomentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');
		}
		return oldMomentProto.toISOString.apply(this, arguments);
	};

	;;

	// Single Date Formatting
	// -------------------------------------------------------------------------------------------------


	// call this if you want Moment's original format method to be used
	function oldMomentFormat(mom, formatStr) {
		return oldMomentProto.format.call(mom, formatStr); // oldMomentProto defined in moment-ext.js
	}


	// Formats `date` with a Moment formatting string, but allow our non-zero areas and
	// additional token.
	function formatDate(date, formatStr) {
		return formatDateWithChunks(date, getFormatStringChunks(formatStr));
	}


	function formatDateWithChunks(date, chunks) {
		var s = '';
		var i;

		for (i=0; i<chunks.length; i++) {
			s += formatDateWithChunk(date, chunks[i]);
		}

		return s;
	}


	// addition formatting tokens we want recognized
	var tokenOverrides = {
		t: function(date) { // "a" or "p"
			return oldMomentFormat(date, 'a').charAt(0);
		},
		T: function(date) { // "A" or "P"
			return oldMomentFormat(date, 'A').charAt(0);
		}
	};


	function formatDateWithChunk(date, chunk) {
		var token;
		var maybeStr;

		if (typeof chunk === 'string') { // a literal string
			return chunk;
		}
		else if ((token = chunk.token)) { // a token, like "YYYY"
			if (tokenOverrides[token]) {
				return tokenOverrides[token](date); // use our custom token
			}
			return oldMomentFormat(date, token);
		}
		else if (chunk.maybe) { // a grouping of other chunks that must be non-zero
			maybeStr = formatDateWithChunks(date, chunk.maybe);
			if (maybeStr.match(/[1-9]/)) {
				return maybeStr;
			}
		}

		return '';
	}


	// Date Range Formatting
	// -------------------------------------------------------------------------------------------------
	// TODO: make it work with timezone offset

	// Using a formatting string meant for a single date, generate a range string, like
	// "Sep 2 - 9 2013", that intelligently inserts a separator where the dates differ.
	// If the dates are the same as far as the format string is concerned, just return a single
	// rendering of one date, without any separator.
	function formatRange(date1, date2, formatStr, separator, isRTL) {
		var localeData;

		date1 = FC.moment.parseZone(date1);
		date2 = FC.moment.parseZone(date2);

		localeData = date1.localeData();

		// Expand localized format strings, like "LL" -> "MMMM D YYYY"
		formatStr = localeData.longDateFormat(formatStr) || formatStr;
		// BTW, this is not important for `formatDate` because it is impossible to put custom tokens
		// or non-zero areas in Moment's localized format strings.

		separator = separator || ' - ';

		return formatRangeWithChunks(
			date1,
			date2,
			getFormatStringChunks(formatStr),
			separator,
			isRTL
		);
	}
	FC.formatRange = formatRange; // expose


	function formatRangeWithChunks(date1, date2, chunks, separator, isRTL) {
		var unzonedDate1 = date1.clone().stripZone(); // for formatSimilarChunk
		var unzonedDate2 = date2.clone().stripZone(); // "
		var chunkStr; // the rendering of the chunk
		var leftI;
		var leftStr = '';
		var rightI;
		var rightStr = '';
		var middleI;
		var middleStr1 = '';
		var middleStr2 = '';
		var middleStr = '';

		// Start at the leftmost side of the formatting string and continue until you hit a token
		// that is not the same between dates.
		for (leftI=0; leftI<chunks.length; leftI++) {
			chunkStr = formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2, chunks[leftI]);
			if (chunkStr === false) {
				break;
			}
			leftStr += chunkStr;
		}

		// Similarly, start at the rightmost side of the formatting string and move left
		for (rightI=chunks.length-1; rightI>leftI; rightI--) {
			chunkStr = formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2,  chunks[rightI]);
			if (chunkStr === false) {
				break;
			}
			rightStr = chunkStr + rightStr;
		}

		// The area in the middle is different for both of the dates.
		// Collect them distinctly so we can jam them together later.
		for (middleI=leftI; middleI<=rightI; middleI++) {
			middleStr1 += formatDateWithChunk(date1, chunks[middleI]);
			middleStr2 += formatDateWithChunk(date2, chunks[middleI]);
		}

		if (middleStr1 || middleStr2) {
			if (isRTL) {
				middleStr = middleStr2 + separator + middleStr1;
			}
			else {
				middleStr = middleStr1 + separator + middleStr2;
			}
		}

		return leftStr + middleStr + rightStr;
	}


	var similarUnitMap = {
		Y: 'year',
		M: 'month',
		D: 'day', // day of month
		d: 'day', // day of week
		// prevents a separator between anything time-related...
		A: 'second', // AM/PM
		a: 'second', // am/pm
		T: 'second', // A/P
		t: 'second', // a/p
		H: 'second', // hour (24)
		h: 'second', // hour (12)
		m: 'second', // minute
		s: 'second' // second
	};
	// TODO: week maybe?


	// Given a formatting chunk, and given that both dates are similar in the regard the
	// formatting chunk is concerned, format date1 against `chunk`. Otherwise, return `false`.
	function formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2, chunk) {
		var token;
		var unit;

		if (typeof chunk === 'string') { // a literal string
			return chunk;
		}
		else if ((token = chunk.token)) {
			unit = similarUnitMap[token.charAt(0)];

			// are the dates the same for this unit of measurement?
			// use the unzoned dates for this calculation because unreliable when near DST (bug #2396)
			if (unit && unzonedDate1.isSame(unzonedDate2, unit)) {
				return oldMomentFormat(date1, token); // would be the same if we used `date2`
				// BTW, don't support custom tokens
			}
		}

		return false; // the chunk is NOT the same for the two dates
		// BTW, don't support splitting on non-zero areas
	}


	// Chunking Utils
	// -------------------------------------------------------------------------------------------------


	var formatStringChunkCache = {};


	function getFormatStringChunks(formatStr) {
		if (formatStr in formatStringChunkCache) {
			return formatStringChunkCache[formatStr];
		}
		return (formatStringChunkCache[formatStr] = chunkFormatString(formatStr));
	}


	// Break the formatting string into an array of chunks
	function chunkFormatString(formatStr) {
		var chunks = [];
		var chunker = /\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g; // TODO: more descrimination
		var match;

		while ((match = chunker.exec(formatStr))) {
			if (match[1]) { // a literal string inside [ ... ]
				chunks.push(match[1]);
			}
			else if (match[2]) { // non-zero formatting inside ( ... )
				chunks.push({ maybe: chunkFormatString(match[2]) });
			}
			else if (match[3]) { // a formatting token
				chunks.push({ token: match[3] });
			}
			else if (match[5]) { // an unenclosed literal string
				chunks.push(match[5]);
			}
		}

		return chunks;
	}

	;;

	FC.Class = Class; // export

	// Class that all other classes will inherit from
	function Class() { }


	// Called on a class to create a subclass.
	// Last argument contains instance methods. Any argument before the last are considered mixins.
	Class.extend = function() {
		var len = arguments.length;
		var i;
		var members;

		for (i = 0; i < len; i++) {
			members = arguments[i];
			if (i < len - 1) { // not the last argument?
				mixIntoClass(this, members);
			}
		}

		return extendClass(this, members || {}); // members will be undefined if no arguments
	};


	// Adds new member variables/methods to the class's prototype.
	// Can be called with another class, or a plain object hash containing new members.
	Class.mixin = function(members) {
		mixIntoClass(this, members);
	};


	function extendClass(superClass, members) {
		var subClass;

		// ensure a constructor for the subclass, forwarding all arguments to the super-constructor if it doesn't exist
		if (hasOwnProp(members, 'constructor')) {
			subClass = members.constructor;
		}
		if (typeof subClass !== 'function') {
			subClass = members.constructor = function() {
				superClass.apply(this, arguments);
			};
		}

		// build the base prototype for the subclass, which is an new object chained to the superclass's prototype
		subClass.prototype = createObject(superClass.prototype);

		// copy each member variable/method onto the the subclass's prototype
		copyOwnProps(members, subClass.prototype);

		// copy over all class variables/methods to the subclass, such as `extend` and `mixin`
		copyOwnProps(superClass, subClass);

		return subClass;
	}


	function mixIntoClass(theClass, members) {
		copyOwnProps(members, theClass.prototype);
	}
	;;

	var EmitterMixin = FC.EmitterMixin = {

		// jQuery-ification via $(this) allows a non-DOM object to have
		// the same event handling capabilities (including namespaces).


		on: function(types, handler) {

			// handlers are always called with an "event" object as their first param.
			// sneak the `this` context and arguments into the extra parameter object
			// and forward them on to the original handler.
			var intercept = function(ev, extra) {
				return handler.apply(
					extra.context || this,
					extra.args || []
				);
			};

			// mimick jQuery's internal "proxy" system (risky, I know)
			// causing all functions with the same .guid to appear to be the same.
			// https://github.com/jquery/jquery/blob/2.2.4/src/core.js#L448
			// this is needed for calling .off with the original non-intercept handler.
			if (!handler.guid) {
				handler.guid = $.guid++;
			}
			intercept.guid = handler.guid;

			$(this).on(types, intercept);

			return this; // for chaining
		},


		off: function(types, handler) {
			$(this).off(types, handler);

			return this; // for chaining
		},


		trigger: function(types) {
			var args = Array.prototype.slice.call(arguments, 1); // arguments after the first

			// pass in "extra" info to the intercept
			$(this).triggerHandler(types, { args: args });

			return this; // for chaining
		},


		triggerWith: function(types, context, args) {

			// `triggerHandler` is less reliant on the DOM compared to `trigger`.
			// pass in "extra" info to the intercept.
			$(this).triggerHandler(types, { context: context, args: args });

			return this; // for chaining
		}

	};

	;;

	/*
	Utility methods for easily listening to events on another object,
	and more importantly, easily unlistening from them.
	*/
	var ListenerMixin = FC.ListenerMixin = (function() {
		var guid = 0;
		var ListenerMixin = {

			listenerId: null,

			/*
			Given an `other` object that has on/off methods, bind the given `callback` to an event by the given name.
			The `callback` will be called with the `this` context of the object that .listenTo is being called on.
			Can be called:
				.listenTo(other, eventName, callback)
			OR
				.listenTo(other, {
					eventName1: callback1,
					eventName2: callback2
				})
			*/
			listenTo: function(other, arg, callback) {
				if (typeof arg === 'object') { // given dictionary of callbacks
					for (var eventName in arg) {
						if (arg.hasOwnProperty(eventName)) {
							this.listenTo(other, eventName, arg[eventName]);
						}
					}
				}
				else if (typeof arg === 'string') {
					other.on(
						arg + '.' + this.getListenerNamespace(), // use event namespacing to identify this object
						$.proxy(callback, this) // always use `this` context
							// the usually-undesired jQuery guid behavior doesn't matter,
							// because we always unbind via namespace
					);
				}
			},

			/*
			Causes the current object to stop listening to events on the `other` object.
			`eventName` is optional. If omitted, will stop listening to ALL events on `other`.
			*/
			stopListeningTo: function(other, eventName) {
				other.off((eventName || '') + '.' + this.getListenerNamespace());
			},

			/*
			Returns a string, unique to this object, to be used for event namespacing
			*/
			getListenerNamespace: function() {
				if (this.listenerId == null) {
					this.listenerId = guid++;
				}
				return '_listener' + this.listenerId;
			}

		};
		return ListenerMixin;
	})();
	;;

	// simple class for toggle a `isIgnoringMouse` flag on delay
	// initMouseIgnoring must first be called, with a millisecond delay setting.
	var MouseIgnorerMixin = {

		isIgnoringMouse: false, // bool
		delayUnignoreMouse: null, // method


		initMouseIgnoring: function(delay) {
			this.delayUnignoreMouse = debounce(proxy(this, 'unignoreMouse'), delay || 1000);
		},


		// temporarily ignore mouse actions on segments
		tempIgnoreMouse: function() {
			this.isIgnoringMouse = true;
			this.delayUnignoreMouse();
		},


		// delayUnignoreMouse eventually calls this
		unignoreMouse: function() {
			this.isIgnoringMouse = false;
		}

	};

	;;

	/* A rectangular panel that is absolutely positioned over other content
	------------------------------------------------------------------------------------------------------------------------
	Options:
		- className (string)
		- content (HTML string or jQuery element set)
		- parentEl
		- top
		- left
		- right (the x coord of where the right edge should be. not a "CSS" right)
		- autoHide (boolean)
		- show (callback)
		- hide (callback)
	*/

	var Popover = Class.extend(ListenerMixin, {

		isHidden: true,
		options: null,
		el: null, // the container element for the popover. generated by this object
		margin: 10, // the space required between the popover and the edges of the scroll container


		constructor: function(options) {
			this.options = options || {};
		},


		// Shows the popover on the specified position. Renders it if not already
		show: function() {
			if (this.isHidden) {
				if (!this.el) {
					this.render();
				}
				this.el.show();
				this.position();
				this.isHidden = false;
				this.trigger('show');
			}
		},


		// Hides the popover, through CSS, but does not remove it from the DOM
		hide: function() {
			if (!this.isHidden) {
				this.el.hide();
				this.isHidden = true;
				this.trigger('hide');
			}
		},


		// Creates `this.el` and renders content inside of it
		render: function() {
			var _this = this;
			var options = this.options;

			this.el = $('<div class="fc-popover"/>')
				.addClass(options.className || '')
				.css({
					// position initially to the top left to avoid creating scrollbars
					top: 0,
					left: 0
				})
				.append(options.content)
				.appendTo(options.parentEl);

			// when a click happens on anything inside with a 'fc-close' className, hide the popover
			this.el.on('click', '.fc-close', function() {
				_this.hide();
			});

			if (options.autoHide) {
				this.listenTo($(document), 'mousedown', this.documentMousedown);
			}
		},


		// Triggered when the user clicks *anywhere* in the document, for the autoHide feature
		documentMousedown: function(ev) {
			// only hide the popover if the click happened outside the popover
			if (this.el && !$(ev.target).closest(this.el).length) {
				this.hide();
			}
		},


		// Hides and unregisters any handlers
		removeElement: function() {
			this.hide();

			if (this.el) {
				this.el.remove();
				this.el = null;
			}

			this.stopListeningTo($(document), 'mousedown');
		},


		// Positions the popover optimally, using the top/left/right options
		position: function() {
			var options = this.options;
			var origin = this.el.offsetParent().offset();
			var width = this.el.outerWidth();
			var height = this.el.outerHeight();
			var windowEl = $(window);
			var viewportEl = getScrollParent(this.el);
			var viewportTop;
			var viewportLeft;
			var viewportOffset;
			var top; // the "position" (not "offset") values for the popover
			var left; //

			// compute top and left
			top = options.top || 0;
			if (options.left !== undefined) {
				left = options.left;
			}
			else if (options.right !== undefined) {
				left = options.right - width; // derive the left value from the right value
			}
			else {
				left = 0;
			}

			if (viewportEl.is(window) || viewportEl.is(document)) { // normalize getScrollParent's result
				viewportEl = windowEl;
				viewportTop = 0; // the window is always at the top left
				viewportLeft = 0; // (and .offset() won't work if called here)
			}
			else {
				viewportOffset = viewportEl.offset();
				viewportTop = viewportOffset.top;
				viewportLeft = viewportOffset.left;
			}

			// if the window is scrolled, it causes the visible area to be further down
			viewportTop += windowEl.scrollTop();
			viewportLeft += windowEl.scrollLeft();

			// constrain to the view port. if constrained by two edges, give precedence to top/left
			if (options.viewportConstrain !== false) {
				top = Math.min(top, viewportTop + viewportEl.outerHeight() - height - this.margin);
				top = Math.max(top, viewportTop + this.margin);
				left = Math.min(left, viewportLeft + viewportEl.outerWidth() - width - this.margin);
				left = Math.max(left, viewportLeft + this.margin);
			}

			this.el.css({
				top: top - origin.top,
				left: left - origin.left
			});
		},


		// Triggers a callback. Calls a function in the option hash of the same name.
		// Arguments beyond the first `name` are forwarded on.
		// TODO: better code reuse for this. Repeat code
		trigger: function(name) {
			if (this.options[name]) {
				this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
			}
		}

	});

	;;

	/*
	A cache for the left/right/top/bottom/width/height values for one or more elements.
	Works with both offset (from topleft document) and position (from offsetParent).

	options:
	- els
	- isHorizontal
	- isVertical
	*/
	var CoordCache = FC.CoordCache = Class.extend({

		els: null, // jQuery set (assumed to be siblings)
		forcedOffsetParentEl: null, // options can override the natural offsetParent
		origin: null, // {left,top} position of offsetParent of els
		boundingRect: null, // constrain cordinates to this rectangle. {left,right,top,bottom} or null
		isHorizontal: false, // whether to query for left/right/width
		isVertical: false, // whether to query for top/bottom/height

		// arrays of coordinates (offsets from topleft of document)
		lefts: null,
		rights: null,
		tops: null,
		bottoms: null,


		constructor: function(options) {
			this.els = $(options.els);
			this.isHorizontal = options.isHorizontal;
			this.isVertical = options.isVertical;
			this.forcedOffsetParentEl = options.offsetParent ? $(options.offsetParent) : null;
		},


		// Queries the els for coordinates and stores them.
		// Call this method before using and of the get* methods below.
		build: function() {
			var offsetParentEl = this.forcedOffsetParentEl || this.els.eq(0).offsetParent();

			this.origin = offsetParentEl.offset();
			this.boundingRect = this.queryBoundingRect();

			if (this.isHorizontal) {
				this.buildElHorizontals();
			}
			if (this.isVertical) {
				this.buildElVerticals();
			}
		},


		// Destroys all internal data about coordinates, freeing memory
		clear: function() {
			this.origin = null;
			this.boundingRect = null;
			this.lefts = null;
			this.rights = null;
			this.tops = null;
			this.bottoms = null;
		},


		// When called, if coord caches aren't built, builds them
		ensureBuilt: function() {
			if (!this.origin) {
				this.build();
			}
		},


		// Populates the left/right internal coordinate arrays
		buildElHorizontals: function() {
			var lefts = [];
			var rights = [];

			this.els.each(function(i, node) {
				var el = $(node);
				var left = el.offset().left;
				var width = el.outerWidth();

				lefts.push(left);
				rights.push(left + width);
			});

			this.lefts = lefts;
			this.rights = rights;
		},


		// Populates the top/bottom internal coordinate arrays
		buildElVerticals: function() {
			var tops = [];
			var bottoms = [];

			this.els.each(function(i, node) {
				var el = $(node);
				var top = el.offset().top;
				var height = el.outerHeight();

				tops.push(top);
				bottoms.push(top + height);
			});

			this.tops = tops;
			this.bottoms = bottoms;
		},


		// Given a left offset (from document left), returns the index of the el that it horizontally intersects.
		// If no intersection is made, returns undefined.
		getHorizontalIndex: function(leftOffset) {
			this.ensureBuilt();

			var lefts = this.lefts;
			var rights = this.rights;
			var len = lefts.length;
			var i;

			for (i = 0; i < len; i++) {
				if (leftOffset >= lefts[i] && leftOffset < rights[i]) {
					return i;
				}
			}
		},


		// Given a top offset (from document top), returns the index of the el that it vertically intersects.
		// If no intersection is made, returns undefined.
		getVerticalIndex: function(topOffset) {
			this.ensureBuilt();

			var tops = this.tops;
			var bottoms = this.bottoms;
			var len = tops.length;
			var i;

			for (i = 0; i < len; i++) {
				if (topOffset >= tops[i] && topOffset < bottoms[i]) {
					return i;
				}
			}
		},


		// Gets the left offset (from document left) of the element at the given index
		getLeftOffset: function(leftIndex) {
			this.ensureBuilt();
			return this.lefts[leftIndex];
		},


		// Gets the left position (from offsetParent left) of the element at the given index
		getLeftPosition: function(leftIndex) {
			this.ensureBuilt();
			return this.lefts[leftIndex] - this.origin.left;
		},


		// Gets the right offset (from document left) of the element at the given index.
		// This value is NOT relative to the document's right edge, like the CSS concept of "right" would be.
		getRightOffset: function(leftIndex) {
			this.ensureBuilt();
			return this.rights[leftIndex];
		},


		// Gets the right position (from offsetParent left) of the element at the given index.
		// This value is NOT relative to the offsetParent's right edge, like the CSS concept of "right" would be.
		getRightPosition: function(leftIndex) {
			this.ensureBuilt();
			return this.rights[leftIndex] - this.origin.left;
		},


		// Gets the width of the element at the given index
		getWidth: function(leftIndex) {
			this.ensureBuilt();
			return this.rights[leftIndex] - this.lefts[leftIndex];
		},


		// Gets the top offset (from document top) of the element at the given index
		getTopOffset: function(topIndex) {
			this.ensureBuilt();
			return this.tops[topIndex];
		},


		// Gets the top position (from offsetParent top) of the element at the given position
		getTopPosition: function(topIndex) {
			this.ensureBuilt();
			return this.tops[topIndex] - this.origin.top;
		},

		// Gets the bottom offset (from the document top) of the element at the given index.
		// This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of "bottom" would be.
		getBottomOffset: function(topIndex) {
			this.ensureBuilt();
			return this.bottoms[topIndex];
		},


		// Gets the bottom position (from the offsetParent top) of the element at the given index.
		// This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of "bottom" would be.
		getBottomPosition: function(topIndex) {
			this.ensureBuilt();
			return this.bottoms[topIndex] - this.origin.top;
		},


		// Gets the height of the element at the given index
		getHeight: function(topIndex) {
			this.ensureBuilt();
			return this.bottoms[topIndex] - this.tops[topIndex];
		},


		// Bounding Rect
		// TODO: decouple this from CoordCache

		// Compute and return what the elements' bounding rectangle is, from the user's perspective.
		// Right now, only returns a rectangle if constrained by an overflow:scroll element.
		queryBoundingRect: function() {
			var scrollParentEl = getScrollParent(this.els.eq(0));

			if (!scrollParentEl.is(document)) {
				return getClientRect(scrollParentEl);
			}
		},

		isPointInBounds: function(leftOffset, topOffset) {
			return this.isLeftInBounds(leftOffset) && this.isTopInBounds(topOffset);
		},

		isLeftInBounds: function(leftOffset) {
			return !this.boundingRect || (leftOffset >= this.boundingRect.left && leftOffset < this.boundingRect.right);
		},

		isTopInBounds: function(topOffset) {
			return !this.boundingRect || (topOffset >= this.boundingRect.top && topOffset < this.boundingRect.bottom);
		}

	});

	;;

	/* Tracks a drag's mouse movement, firing various handlers
	----------------------------------------------------------------------------------------------------------------------*/
	// TODO: use Emitter

	var DragListener = FC.DragListener = Class.extend(ListenerMixin, MouseIgnorerMixin, {

		options: null,
		subjectEl: null,

		// coordinates of the initial mousedown
		originX: null,
		originY: null,

		// the wrapping element that scrolls, or MIGHT scroll if there's overflow.
		// TODO: do this for wrappers that have overflow:hidden as well.
		scrollEl: null,

		isInteracting: false,
		isDistanceSurpassed: false,
		isDelayEnded: false,
		isDragging: false,
		isTouch: false,

		delay: null,
		delayTimeoutId: null,
		minDistance: null,

		handleTouchScrollProxy: null, // calls handleTouchScroll, always bound to `this`


		constructor: function(options) {
			this.options = options || {};
			this.handleTouchScrollProxy = proxy(this, 'handleTouchScroll');
			this.initMouseIgnoring(500);
		},


		// Interaction (high-level)
		// -----------------------------------------------------------------------------------------------------------------


		startInteraction: function(ev, extraOptions) {
			var isTouch = getEvIsTouch(ev);

			if (ev.type === 'mousedown') {
				if (this.isIgnoringMouse) {
					return;
				}
				else if (!isPrimaryMouseButton(ev)) {
					return;
				}
				else {
					ev.preventDefault(); // prevents native selection in most browsers
				}
			}

			if (!this.isInteracting) {

				// process options
				extraOptions = extraOptions || {};
				this.delay = firstDefined(extraOptions.delay, this.options.delay, 0);
				this.minDistance = firstDefined(extraOptions.distance, this.options.distance, 0);
				this.subjectEl = this.options.subjectEl;

				this.isInteracting = true;
				this.isTouch = isTouch;
				this.isDelayEnded = false;
				this.isDistanceSurpassed = false;

				this.originX = getEvX(ev);
				this.originY = getEvY(ev);
				this.scrollEl = getScrollParent($(ev.target));

				this.bindHandlers();
				this.initAutoScroll();
				this.handleInteractionStart(ev);
				this.startDelay(ev);

				if (!this.minDistance) {
					this.handleDistanceSurpassed(ev);
				}
			}
		},


		handleInteractionStart: function(ev) {
			this.trigger('interactionStart', ev);
		},


		endInteraction: function(ev, isCancelled) {
			if (this.isInteracting) {
				this.endDrag(ev);

				if (this.delayTimeoutId) {
					clearTimeout(this.delayTimeoutId);
					this.delayTimeoutId = null;
				}

				this.destroyAutoScroll();
				this.unbindHandlers();

				this.isInteracting = false;
				this.handleInteractionEnd(ev, isCancelled);

				// a touchstart+touchend on the same element will result in the following addition simulated events:
				// mouseover + mouseout + click
				// let's ignore these bogus events
				if (this.isTouch) {
					this.tempIgnoreMouse();
				}
			}
		},


		handleInteractionEnd: function(ev, isCancelled) {
			this.trigger('interactionEnd', ev, isCancelled || false);
		},


		// Binding To DOM
		// -----------------------------------------------------------------------------------------------------------------


		bindHandlers: function() {
			var _this = this;
			var touchStartIgnores = 1;

			if (this.isTouch) {
				this.listenTo($(document), {
					touchmove: this.handleTouchMove,
					touchend: this.endInteraction,
					touchcancel: this.endInteraction,

					// Sometimes touchend doesn't fire
					// (can't figure out why. touchcancel doesn't fire either. has to do with scrolling?)
					// If another touchstart happens, we know it's bogus, so cancel the drag.
					// touchend will continue to be broken until user does a shorttap/scroll, but this is best we can do.
					touchstart: function(ev) {
						if (touchStartIgnores) { // bindHandlers is called from within a touchstart,
							touchStartIgnores--; // and we don't want this to fire immediately, so ignore.
						}
						else {
							_this.endInteraction(ev, true); // isCancelled=true
						}
					}
				});

				// listen to ALL scroll actions on the page
				if (
					!bindAnyScroll(this.handleTouchScrollProxy) && // hopefully this works and short-circuits the rest
					this.scrollEl // otherwise, attach a single handler to this
				) {
					this.listenTo(this.scrollEl, 'scroll', this.handleTouchScroll);
				}
			}
			else {
				this.listenTo($(document), {
					mousemove: this.handleMouseMove,
					mouseup: this.endInteraction
				});
			}

			this.listenTo($(document), {
				selectstart: preventDefault, // don't allow selection while dragging
				contextmenu: preventDefault // long taps would open menu on Chrome dev tools
			});
		},


		unbindHandlers: function() {
			this.stopListeningTo($(document));

			// unbind scroll listening
			unbindAnyScroll(this.handleTouchScrollProxy);
			if (this.scrollEl) {
				this.stopListeningTo(this.scrollEl, 'scroll');
			}
		},


		// Drag (high-level)
		// -----------------------------------------------------------------------------------------------------------------


		// extraOptions ignored if drag already started
		startDrag: function(ev, extraOptions) {
			this.startInteraction(ev, extraOptions); // ensure interaction began

			if (!this.isDragging) {
				this.isDragging = true;
				this.handleDragStart(ev);
			}
		},


		handleDragStart: function(ev) {
			this.trigger('dragStart', ev);
		},


		handleMove: function(ev) {
			var dx = getEvX(ev) - this.originX;
			var dy = getEvY(ev) - this.originY;
			var minDistance = this.minDistance;
			var distanceSq; // current distance from the origin, squared

			if (!this.isDistanceSurpassed) {
				distanceSq = dx * dx + dy * dy;
				if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
					this.handleDistanceSurpassed(ev);
				}
			}

			if (this.isDragging) {
				this.handleDrag(dx, dy, ev);
			}
		},


		// Called while the mouse is being moved and when we know a legitimate drag is taking place
		handleDrag: function(dx, dy, ev) {
			this.trigger('drag', dx, dy, ev);
			this.updateAutoScroll(ev); // will possibly cause scrolling
		},


		endDrag: function(ev) {
			if (this.isDragging) {
				this.isDragging = false;
				this.handleDragEnd(ev);
			}
		},


		handleDragEnd: function(ev) {
			this.trigger('dragEnd', ev);
		},


		// Delay
		// -----------------------------------------------------------------------------------------------------------------


		startDelay: function(initialEv) {
			var _this = this;

			if (this.delay) {
				this.delayTimeoutId = setTimeout(function() {
					_this.handleDelayEnd(initialEv);
				}, this.delay);
			}
			else {
				this.handleDelayEnd(initialEv);
			}
		},


		handleDelayEnd: function(initialEv) {
			this.isDelayEnded = true;

			if (this.isDistanceSurpassed) {
				this.startDrag(initialEv);
			}
		},


		// Distance
		// -----------------------------------------------------------------------------------------------------------------


		handleDistanceSurpassed: function(ev) {
			this.isDistanceSurpassed = true;

			if (this.isDelayEnded) {
				this.startDrag(ev);
			}
		},


		// Mouse / Touch
		// -----------------------------------------------------------------------------------------------------------------


		handleTouchMove: function(ev) {
			// prevent inertia and touchmove-scrolling while dragging
			if (this.isDragging) {
				ev.preventDefault();
			}

			this.handleMove(ev);
		},


		handleMouseMove: function(ev) {
			this.handleMove(ev);
		},


		// Scrolling (unrelated to auto-scroll)
		// -----------------------------------------------------------------------------------------------------------------


		handleTouchScroll: function(ev) {
			// if the drag is being initiated by touch, but a scroll happens before
			// the drag-initiating delay is over, cancel the drag
			if (!this.isDragging) {
				this.endInteraction(ev, true); // isCancelled=true
			}
		},


		// Utils
		// -----------------------------------------------------------------------------------------------------------------


		// Triggers a callback. Calls a function in the option hash of the same name.
		// Arguments beyond the first `name` are forwarded on.
		trigger: function(name) {
			if (this.options[name]) {
				this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
			}
			// makes _methods callable by event name. TODO: kill this
			if (this['_' + name]) {
				this['_' + name].apply(this, Array.prototype.slice.call(arguments, 1));
			}
		}


	});

	;;
	/*
	this.scrollEl is set in DragListener
	*/
	DragListener.mixin({

		isAutoScroll: false,

		scrollBounds: null, // { top, bottom, left, right }
		scrollTopVel: null, // pixels per second
		scrollLeftVel: null, // pixels per second
		scrollIntervalId: null, // ID of setTimeout for scrolling animation loop

		// defaults
		scrollSensitivity: 30, // pixels from edge for scrolling to start
		scrollSpeed: 200, // pixels per second, at maximum speed
		scrollIntervalMs: 50, // millisecond wait between scroll increment


		initAutoScroll: function() {
			var scrollEl = this.scrollEl;

			this.isAutoScroll =
				this.options.scroll &&
				scrollEl &&
				!scrollEl.is(window) &&
				!scrollEl.is(document);

			if (this.isAutoScroll) {
				// debounce makes sure rapid calls don't happen
				this.listenTo(scrollEl, 'scroll', debounce(this.handleDebouncedScroll, 100));
			}
		},


		destroyAutoScroll: function() {
			this.endAutoScroll(); // kill any animation loop

			// remove the scroll handler if there is a scrollEl
			if (this.isAutoScroll) {
				this.stopListeningTo(this.scrollEl, 'scroll'); // will probably get removed by unbindHandlers too :(
			}
		},


		// Computes and stores the bounding rectangle of scrollEl
		computeScrollBounds: function() {
			if (this.isAutoScroll) {
				this.scrollBounds = getOuterRect(this.scrollEl);
				// TODO: use getClientRect in future. but prevents auto scrolling when on top of scrollbars
			}
		},


		// Called when the dragging is in progress and scrolling should be updated
		updateAutoScroll: function(ev) {
			var sensitivity = this.scrollSensitivity;
			var bounds = this.scrollBounds;
			var topCloseness, bottomCloseness;
			var leftCloseness, rightCloseness;
			var topVel = 0;
			var leftVel = 0;

			if (bounds) { // only scroll if scrollEl exists

				// compute closeness to edges. valid range is from 0.0 - 1.0
				topCloseness = (sensitivity - (getEvY(ev) - bounds.top)) / sensitivity;
				bottomCloseness = (sensitivity - (bounds.bottom - getEvY(ev))) / sensitivity;
				leftCloseness = (sensitivity - (getEvX(ev) - bounds.left)) / sensitivity;
				rightCloseness = (sensitivity - (bounds.right - getEvX(ev))) / sensitivity;

				// translate vertical closeness into velocity.
				// mouse must be completely in bounds for velocity to happen.
				if (topCloseness >= 0 && topCloseness <= 1) {
					topVel = topCloseness * this.scrollSpeed * -1; // negative. for scrolling up
				}
				else if (bottomCloseness >= 0 && bottomCloseness <= 1) {
					topVel = bottomCloseness * this.scrollSpeed;
				}

				// translate horizontal closeness into velocity
				if (leftCloseness >= 0 && leftCloseness <= 1) {
					leftVel = leftCloseness * this.scrollSpeed * -1; // negative. for scrolling left
				}
				else if (rightCloseness >= 0 && rightCloseness <= 1) {
					leftVel = rightCloseness * this.scrollSpeed;
				}
			}

			this.setScrollVel(topVel, leftVel);
		},


		// Sets the speed-of-scrolling for the scrollEl
		setScrollVel: function(topVel, leftVel) {

			this.scrollTopVel = topVel;
			this.scrollLeftVel = leftVel;

			this.constrainScrollVel(); // massages into realistic values

			// if there is non-zero velocity, and an animation loop hasn't already started, then START
			if ((this.scrollTopVel || this.scrollLeftVel) && !this.scrollIntervalId) {
				this.scrollIntervalId = setInterval(
					proxy(this, 'scrollIntervalFunc'), // scope to `this`
					this.scrollIntervalMs
				);
			}
		},


		// Forces scrollTopVel and scrollLeftVel to be zero if scrolling has already gone all the way
		constrainScrollVel: function() {
			var el = this.scrollEl;

			if (this.scrollTopVel < 0) { // scrolling up?
				if (el.scrollTop() <= 0) { // already scrolled all the way up?
					this.scrollTopVel = 0;
				}
			}
			else if (this.scrollTopVel > 0) { // scrolling down?
				if (el.scrollTop() + el[0].clientHeight >= el[0].scrollHeight) { // already scrolled all the way down?
					this.scrollTopVel = 0;
				}
			}

			if (this.scrollLeftVel < 0) { // scrolling left?
				if (el.scrollLeft() <= 0) { // already scrolled all the left?
					this.scrollLeftVel = 0;
				}
			}
			else if (this.scrollLeftVel > 0) { // scrolling right?
				if (el.scrollLeft() + el[0].clientWidth >= el[0].scrollWidth) { // already scrolled all the way right?
					this.scrollLeftVel = 0;
				}
			}
		},


		// This function gets called during every iteration of the scrolling animation loop
		scrollIntervalFunc: function() {
			var el = this.scrollEl;
			var frac = this.scrollIntervalMs / 1000; // considering animation frequency, what the vel should be mult'd by

			// change the value of scrollEl's scroll
			if (this.scrollTopVel) {
				el.scrollTop(el.scrollTop() + this.scrollTopVel * frac);
			}
			if (this.scrollLeftVel) {
				el.scrollLeft(el.scrollLeft() + this.scrollLeftVel * frac);
			}

			this.constrainScrollVel(); // since the scroll values changed, recompute the velocities

			// if scrolled all the way, which causes the vels to be zero, stop the animation loop
			if (!this.scrollTopVel && !this.scrollLeftVel) {
				this.endAutoScroll();
			}
		},


		// Kills any existing scrolling animation loop
		endAutoScroll: function() {
			if (this.scrollIntervalId) {
				clearInterval(this.scrollIntervalId);
				this.scrollIntervalId = null;

				this.handleScrollEnd();
			}
		},


		// Get called when the scrollEl is scrolled (NOTE: this is delayed via debounce)
		handleDebouncedScroll: function() {
			// recompute all coordinates, but *only* if this is *not* part of our scrolling animation
			if (!this.scrollIntervalId) {
				this.handleScrollEnd();
			}
		},


		// Called when scrolling has stopped, whether through auto scroll, or the user scrolling
		handleScrollEnd: function() {
		}

	});
	;;

	/* Tracks mouse movements over a component and raises events about which hit the mouse is over.
	------------------------------------------------------------------------------------------------------------------------
	options:
	- subjectEl
	- subjectCenter
	*/

	var HitDragListener = DragListener.extend({

		component: null, // converts coordinates to hits
			// methods: prepareHits, releaseHits, queryHit

		origHit: null, // the hit the mouse was over when listening started
		hit: null, // the hit the mouse is over
		coordAdjust: null, // delta that will be added to the mouse coordinates when computing collisions


		constructor: function(component, options) {
			DragListener.call(this, options); // call the super-constructor

			this.component = component;
		},


		// Called when drag listening starts (but a real drag has not necessarily began).
		// ev might be undefined if dragging was started manually.
		handleInteractionStart: function(ev) {
			var subjectEl = this.subjectEl;
			var subjectRect;
			var origPoint;
			var point;

			this.computeCoords();

			if (ev) {
				origPoint = { left: getEvX(ev), top: getEvY(ev) };
				point = origPoint;

				// constrain the point to bounds of the element being dragged
				if (subjectEl) {
					subjectRect = getOuterRect(subjectEl); // used for centering as well
					point = constrainPoint(point, subjectRect);
				}

				this.origHit = this.queryHit(point.left, point.top);

				// treat the center of the subject as the collision point?
				if (subjectEl && this.options.subjectCenter) {

					// only consider the area the subject overlaps the hit. best for large subjects.
					// TODO: skip this if hit didn't supply left/right/top/bottom
					if (this.origHit) {
						subjectRect = intersectRects(this.origHit, subjectRect) ||
							subjectRect; // in case there is no intersection
					}

					point = getRectCenter(subjectRect);
				}

				this.coordAdjust = diffPoints(point, origPoint); // point - origPoint
			}
			else {
				this.origHit = null;
				this.coordAdjust = null;
			}

			// call the super-method. do it after origHit has been computed
			DragListener.prototype.handleInteractionStart.apply(this, arguments);
		},


		// Recomputes the drag-critical positions of elements
		computeCoords: function() {
			this.component.prepareHits();
			this.computeScrollBounds(); // why is this here??????
		},


		// Called when the actual drag has started
		handleDragStart: function(ev) {
			var hit;

			DragListener.prototype.handleDragStart.apply(this, arguments); // call the super-method

			// might be different from this.origHit if the min-distance is large
			hit = this.queryHit(getEvX(ev), getEvY(ev));

			// report the initial hit the mouse is over
			// especially important if no min-distance and drag starts immediately
			if (hit) {
				this.handleHitOver(hit);
			}
		},


		// Called when the drag moves
		handleDrag: function(dx, dy, ev) {
			var hit;

			DragListener.prototype.handleDrag.apply(this, arguments); // call the super-method

			hit = this.queryHit(getEvX(ev), getEvY(ev));

			if (!isHitsEqual(hit, this.hit)) { // a different hit than before?
				if (this.hit) {
					this.handleHitOut();
				}
				if (hit) {
					this.handleHitOver(hit);
				}
			}
		},


		// Called when dragging has been stopped
		handleDragEnd: function() {
			this.handleHitDone();
			DragListener.prototype.handleDragEnd.apply(this, arguments); // call the super-method
		},


		// Called when a the mouse has just moved over a new hit
		handleHitOver: function(hit) {
			var isOrig = isHitsEqual(hit, this.origHit);

			this.hit = hit;

			this.trigger('hitOver', this.hit, isOrig, this.origHit);
		},


		// Called when the mouse has just moved out of a hit
		handleHitOut: function() {
			if (this.hit) {
				this.trigger('hitOut', this.hit);
				this.handleHitDone();
				this.hit = null;
			}
		},


		// Called after a hitOut. Also called before a dragStop
		handleHitDone: function() {
			if (this.hit) {
				this.trigger('hitDone', this.hit);
			}
		},


		// Called when the interaction ends, whether there was a real drag or not
		handleInteractionEnd: function() {
			DragListener.prototype.handleInteractionEnd.apply(this, arguments); // call the super-method

			this.origHit = null;
			this.hit = null;

			this.component.releaseHits();
		},


		// Called when scrolling has stopped, whether through auto scroll, or the user scrolling
		handleScrollEnd: function() {
			DragListener.prototype.handleScrollEnd.apply(this, arguments); // call the super-method

			this.computeCoords(); // hits' absolute positions will be in new places. recompute
		},


		// Gets the hit underneath the coordinates for the given mouse event
		queryHit: function(left, top) {

			if (this.coordAdjust) {
				left += this.coordAdjust.left;
				top += this.coordAdjust.top;
			}

			return this.component.queryHit(left, top);
		}

	});


	// Returns `true` if the hits are identically equal. `false` otherwise. Must be from the same component.
	// Two null values will be considered equal, as two "out of the component" states are the same.
	function isHitsEqual(hit0, hit1) {

		if (!hit0 && !hit1) {
			return true;
		}

		if (hit0 && hit1) {
			return hit0.component === hit1.component &&
				isHitPropsWithin(hit0, hit1) &&
				isHitPropsWithin(hit1, hit0); // ensures all props are identical
		}

		return false;
	}


	// Returns true if all of subHit's non-standard properties are within superHit
	function isHitPropsWithin(subHit, superHit) {
		for (var propName in subHit) {
			if (!/^(component|left|right|top|bottom)$/.test(propName)) {
				if (subHit[propName] !== superHit[propName]) {
					return false;
				}
			}
		}
		return true;
	}

	;;

	/* Creates a clone of an element and lets it track the mouse as it moves
	----------------------------------------------------------------------------------------------------------------------*/

	var MouseFollower = Class.extend(ListenerMixin, {

		options: null,

		sourceEl: null, // the element that will be cloned and made to look like it is dragging
		el: null, // the clone of `sourceEl` that will track the mouse
		parentEl: null, // the element that `el` (the clone) will be attached to

		// the initial position of el, relative to the offset parent. made to match the initial offset of sourceEl
		top0: null,
		left0: null,

		// the absolute coordinates of the initiating touch/mouse action
		y0: null,
		x0: null,

		// the number of pixels the mouse has moved from its initial position
		topDelta: null,
		leftDelta: null,

		isFollowing: false,
		isHidden: false,
		isAnimating: false, // doing the revert animation?

		constructor: function(sourceEl, options) {
			this.options = options = options || {};
			this.sourceEl = sourceEl;
			this.parentEl = options.parentEl ? $(options.parentEl) : sourceEl.parent(); // default to sourceEl's parent
		},


		// Causes the element to start following the mouse
		start: function(ev) {
			if (!this.isFollowing) {
				this.isFollowing = true;

				this.y0 = getEvY(ev);
				this.x0 = getEvX(ev);
				this.topDelta = 0;
				this.leftDelta = 0;

				if (!this.isHidden) {
					this.updatePosition();
				}

				if (getEvIsTouch(ev)) {
					this.listenTo($(document), 'touchmove', this.handleMove);
				}
				else {
					this.listenTo($(document), 'mousemove', this.handleMove);
				}
			}
		},


		// Causes the element to stop following the mouse. If shouldRevert is true, will animate back to original position.
		// `callback` gets invoked when the animation is complete. If no animation, it is invoked immediately.
		stop: function(shouldRevert, callback) {
			var _this = this;
			var revertDuration = this.options.revertDuration;

			function complete() { // might be called by .animate(), which might change `this` context
				_this.isAnimating = false;
				_this.removeElement();

				_this.top0 = _this.left0 = null; // reset state for future updatePosition calls

				if (callback) {
					callback();
				}
			}

			if (this.isFollowing && !this.isAnimating) { // disallow more than one stop animation at a time
				this.isFollowing = false;

				this.stopListeningTo($(document));

				if (shouldRevert && revertDuration && !this.isHidden) { // do a revert animation?
					this.isAnimating = true;
					this.el.animate({
						top: this.top0,
						left: this.left0
					}, {
						duration: revertDuration,
						complete: complete
					});
				}
				else {
					complete();
				}
			}
		},


		// Gets the tracking element. Create it if necessary
		getEl: function() {
			var el = this.el;

			if (!el) {
				el = this.el = this.sourceEl.clone()
					.addClass(this.options.additionalClass || '')
					.css({
						position: 'absolute',
						visibility: '', // in case original element was hidden (commonly through hideEvents())
						display: this.isHidden ? 'none' : '', // for when initially hidden
						margin: 0,
						right: 'auto', // erase and set width instead
						bottom: 'auto', // erase and set height instead
						width: this.sourceEl.width(), // explicit height in case there was a 'right' value
						height: this.sourceEl.height(), // explicit width in case there was a 'bottom' value
						opacity: this.options.opacity || '',
						zIndex: this.options.zIndex
					});

				// we don't want long taps or any mouse interaction causing selection/menus.
				// would use preventSelection(), but that prevents selectstart, causing problems.
				el.addClass('fc-unselectable');

				el.appendTo(this.parentEl);
			}

			return el;
		},


		// Removes the tracking element if it has already been created
		removeElement: function() {
			if (this.el) {
				this.el.remove();
				this.el = null;
			}
		},


		// Update the CSS position of the tracking element
		updatePosition: function() {
			var sourceOffset;
			var origin;

			this.getEl(); // ensure this.el

			// make sure origin info was computed
			if (this.top0 === null) {
				sourceOffset = this.sourceEl.offset();
				origin = this.el.offsetParent().offset();
				this.top0 = sourceOffset.top - origin.top;
				this.left0 = sourceOffset.left - origin.left;
			}

			this.el.css({
				top: this.top0 + this.topDelta,
				left: this.left0 + this.leftDelta
			});
		},


		// Gets called when the user moves the mouse
		handleMove: function(ev) {
			this.topDelta = getEvY(ev) - this.y0;
			this.leftDelta = getEvX(ev) - this.x0;

			if (!this.isHidden) {
				this.updatePosition();
			}
		},


		// Temporarily makes the tracking element invisible. Can be called before following starts
		hide: function() {
			if (!this.isHidden) {
				this.isHidden = true;
				if (this.el) {
					this.el.hide();
				}
			}
		},


		// Show the tracking element after it has been temporarily hidden
		show: function() {
			if (this.isHidden) {
				this.isHidden = false;
				this.updatePosition();
				this.getEl().show();
			}
		}

	});

	;;

	/* An abstract class comprised of a "grid" of areas that each represent a specific datetime
	----------------------------------------------------------------------------------------------------------------------*/

	var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {

		// self-config, overridable by subclasses
		hasDayInteractions: true, // can user click/select ranges of time?

		view: null, // a View object
		isRTL: null, // shortcut to the view's isRTL option

		start: null,
		end: null,

		el: null, // the containing element
		elsByFill: null, // a hash of jQuery element sets used for rendering each fill. Keyed by fill name.

		// derived from options
		eventTimeFormat: null,
		displayEventTime: null,
		displayEventEnd: null,

		minResizeDuration: null, // TODO: hack. set by subclasses. minumum event resize duration

		// if defined, holds the unit identified (ex: "year" or "month") that determines the level of granularity
		// of the date areas. if not defined, assumes to be day and time granularity.
		// TODO: port isTimeScale into same system?
		largeUnit: null,

		dayDragListener: null,
		segDragListener: null,
		segResizeListener: null,
		externalDragListener: null,


		constructor: function(view) {
			this.view = view;
			this.isRTL = view.opt('isRTL');
			this.elsByFill = {};

			this.dayDragListener = this.buildDayDragListener();
			this.initMouseIgnoring();
		},


		/* Options
		------------------------------------------------------------------------------------------------------------------*/


		// Generates the format string used for event time text, if not explicitly defined by 'timeFormat'
		computeEventTimeFormat: function() {
			return this.view.opt('smallTimeFormat');
		},


		// Determines whether events should have their end times displayed, if not explicitly defined by 'displayEventTime'.
		// Only applies to non-all-day events.
		computeDisplayEventTime: function() {
			return true;
		},


		// Determines whether events should have their end times displayed, if not explicitly defined by 'displayEventEnd'
		computeDisplayEventEnd: function() {
			return true;
		},


		/* Dates
		------------------------------------------------------------------------------------------------------------------*/


		// Tells the grid about what period of time to display.
		// Any date-related internal data should be generated.
		setRange: function(range) {
			this.start = range.start.clone();
			this.end = range.end.clone();

			this.rangeUpdated();
			this.processRangeOptions();
		},


		// Called when internal variables that rely on the range should be updated
		rangeUpdated: function() {
		},


		// Updates values that rely on options and also relate to range
		processRangeOptions: function() {
			var view = this.view;
			var displayEventTime;
			var displayEventEnd;

			this.eventTimeFormat =
				view.opt('eventTimeFormat') ||
				view.opt('timeFormat') || // deprecated
				this.computeEventTimeFormat();

			displayEventTime = view.opt('displayEventTime');
			if (displayEventTime == null) {
				displayEventTime = this.computeDisplayEventTime(); // might be based off of range
			}

			displayEventEnd = view.opt('displayEventEnd');
			if (displayEventEnd == null) {
				displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range
			}

			this.displayEventTime = displayEventTime;
			this.displayEventEnd = displayEventEnd;
		},


		// Converts a span (has unzoned start/end and any other grid-specific location information)
		// into an array of segments (pieces of events whose format is decided by the grid).
		spanToSegs: function(span) {
			// subclasses must implement
		},


		// Diffs the two dates, returning a duration, based on granularity of the grid
		// TODO: port isTimeScale into this system?
		diffDates: function(a, b) {
			if (this.largeUnit) {
				return diffByUnit(a, b, this.largeUnit);
			}
			else {
				return diffDayTime(a, b);
			}
		},


		/* Hit Area
		------------------------------------------------------------------------------------------------------------------*/


		// Called before one or more queryHit calls might happen. Should prepare any cached coordinates for queryHit
		prepareHits: function() {
		},


		// Called when queryHit calls have subsided. Good place to clear any coordinate caches.
		releaseHits: function() {
		},


		// Given coordinates from the topleft of the document, return data about the date-related area underneath.
		// Can return an object with arbitrary properties (although top/right/left/bottom are encouraged).
		// Must have a `grid` property, a reference to this current grid. TODO: avoid this
		// The returned object will be processed by getHitSpan and getHitEl.
		queryHit: function(leftOffset, topOffset) {
		},


		// Given position-level information about a date-related area within the grid,
		// should return an object with at least a start/end date. Can provide other information as well.
		getHitSpan: function(hit) {
		},


		// Given position-level information about a date-related area within the grid,
		// should return a jQuery element that best represents it. passed to dayClick callback.
		getHitEl: function(hit) {
		},


		/* Rendering
		------------------------------------------------------------------------------------------------------------------*/


		// Sets the container element that the grid should render inside of.
		// Does other DOM-related initializations.
		setElement: function(el) {
			this.el = el;

			if (this.hasDayInteractions) {
				preventSelection(el);

				this.bindDayHandler('touchstart', this.dayTouchStart);
				this.bindDayHandler('mousedown', this.dayMousedown);
			}

			// attach event-element-related handlers. in Grid.events
			// same garbage collection note as above.
			this.bindSegHandlers();

			this.bindGlobalHandlers();
		},


		bindDayHandler: function(name, handler) {
			var _this = this;

			// attach a handler to the grid's root element.
			// jQuery will take care of unregistering them when removeElement gets called.
			this.el.on(name, function(ev) {
				if (
					!$(ev.target).is('.fc-event-container *, .fc-more') // not an an event element, or "more.." link
				) {
					return handler.call(_this, ev);
				}
			});
		},


		// Removes the grid's container element from the DOM. Undoes any other DOM-related attachments.
		// DOES NOT remove any content beforehand (doesn't clear events or call unrenderDates), unlike View
		removeElement: function() {
			this.unbindGlobalHandlers();
			this.clearDragListeners();

			this.el.remove();

			// NOTE: we don't null-out this.el for the same reasons we don't do it within View::removeElement
		},


		// Renders the basic structure of grid view before any content is rendered
		renderSkeleton: function() {
			// subclasses should implement
		},


		// Renders the grid's date-related content (like areas that represent days/times).
		// Assumes setRange has already been called and the skeleton has already been rendered.
		renderDates: function() {
			// subclasses should implement
		},


		// Unrenders the grid's date-related content
		unrenderDates: function() {
			// subclasses should implement
		},


		/* Handlers
		------------------------------------------------------------------------------------------------------------------*/


		// Binds DOM handlers to elements that reside outside the grid, such as the document
		bindGlobalHandlers: function() {
			this.listenTo($(document), {
				dragstart: this.externalDragStart, // jqui
				sortstart: this.externalDragStart // jqui
			});
		},


		// Unbinds DOM handlers from elements that reside outside the grid
		unbindGlobalHandlers: function() {
			this.stopListeningTo($(document));
		},


		// Process a mousedown on an element that represents a day. For day clicking and selecting.
		dayMousedown: function(ev) {
			if (!this.isIgnoringMouse) {
				this.dayDragListener.startInteraction(ev, {
					//distance: 5, // needs more work if we want dayClick to fire correctly
				});
			}
		},


		dayTouchStart: function(ev) {
			var view = this.view;

			// HACK to prevent a user's clickaway for unselecting a range or an event
			// from causing a dayClick.
			if (view.isSelected || view.selectedEvent) {
				this.tempIgnoreMouse();
			}

			this.dayDragListener.startInteraction(ev, {
				delay: this.view.opt('longPressDelay')
			});
		},


		// Creates a listener that tracks the user's drag across day elements.
		// For day clicking and selecting.
		buildDayDragListener: function() {
			var _this = this;
			var view = this.view;
			var isSelectable = view.opt('selectable');
			var dayClickHit; // null if invalid dayClick
			var selectionSpan; // null if invalid selection

			// this listener tracks a mousedown on a day element, and a subsequent drag.
			// if the drag ends on the same day, it is a 'dayClick'.
			// if 'selectable' is enabled, this listener also detects selections.
			var dragListener = new HitDragListener(this, {
				scroll: view.opt('dragScroll'),
				interactionStart: function() {
					dayClickHit = dragListener.origHit; // for dayClick, where no dragging happens
					selectionSpan = null;
				},
				dragStart: function() {
					view.unselect(); // since we could be rendering a new selection, we want to clear any old one
				},
				hitOver: function(hit, isOrig, origHit) {
					if (origHit) { // click needs to have started on a hit

						// if user dragged to another cell at any point, it can no longer be a dayClick
						if (!isOrig) {
							dayClickHit = null;
						}

						if (isSelectable) {
							selectionSpan = _this.computeSelection(
								_this.getHitSpan(origHit),
								_this.getHitSpan(hit)
							);
							if (selectionSpan) {
								_this.renderSelection(selectionSpan);
							}
							else if (selectionSpan === false) {
								disableCursor();
							}
						}
					}
				},
				hitOut: function() { // called before mouse moves to a different hit OR moved out of all hits
					dayClickHit = null;
					selectionSpan = null;
					_this.unrenderSelection();
				},
				hitDone: function() { // called after a hitOut OR before a dragEnd
					enableCursor();
				},
				interactionEnd: function(ev, isCancelled) {
					if (!isCancelled) {
						if (
							dayClickHit &&
							!_this.isIgnoringMouse // see hack in dayTouchStart
						) {
							view.triggerDayClick(
								_this.getHitSpan(dayClickHit),
								_this.getHitEl(dayClickHit),
								ev
							);
						}
						if (selectionSpan) {
							// the selection will already have been rendered. just report it
							view.reportSelection(selectionSpan, ev);
						}
					}
				}
			});

			return dragListener;
		},


		// Kills all in-progress dragging.
		// Useful for when public API methods that result in re-rendering are invoked during a drag.
		// Also useful for when touch devices misbehave and don't fire their touchend.
		clearDragListeners: function() {
			this.dayDragListener.endInteraction();

			if (this.segDragListener) {
				this.segDragListener.endInteraction(); // will clear this.segDragListener
			}
			if (this.segResizeListener) {
				this.segResizeListener.endInteraction(); // will clear this.segResizeListener
			}
			if (this.externalDragListener) {
				this.externalDragListener.endInteraction(); // will clear this.externalDragListener
			}
		},


		/* Event Helper
		------------------------------------------------------------------------------------------------------------------*/
		// TODO: should probably move this to Grid.events, like we did event dragging / resizing


		// Renders a mock event at the given event location, which contains zoned start/end properties.
		// Returns all mock event elements.
		renderEventLocationHelper: function(eventLocation, sourceSeg) {
			var fakeEvent = this.fabricateHelperEvent(eventLocation, sourceSeg);

			return this.renderHelper(fakeEvent, sourceSeg); // do the actual rendering
		},


		// Builds a fake event given zoned event date properties and a segment is should be inspired from.
		// The range's end can be null, in which case the mock event that is rendered will have a null end time.
		// `sourceSeg` is the internal segment object involved in the drag. If null, something external is dragging.
		fabricateHelperEvent: function(eventLocation, sourceSeg) {
			var fakeEvent = sourceSeg ? createObject(sourceSeg.event) : {}; // mask the original event object if possible

			fakeEvent.start = eventLocation.start.clone();
			fakeEvent.end = eventLocation.end ? eventLocation.end.clone() : null;
			fakeEvent.allDay = null; // force it to be freshly computed by normalizeEventDates
			this.view.calendar.normalizeEventDates(fakeEvent);

			// this extra className will be useful for differentiating real events from mock events in CSS
			fakeEvent.className = (fakeEvent.className || []).concat('fc-helper');

			// if something external is being dragged in, don't render a resizer
			if (!sourceSeg) {
				fakeEvent.editable = false;
			}

			return fakeEvent;
		},


		// Renders a mock event. Given zoned event date properties.
		// Must return all mock event elements.
		renderHelper: function(eventLocation, sourceSeg) {
			// subclasses must implement
		},


		// Unrenders a mock event
		unrenderHelper: function() {
			// subclasses must implement
		},


		/* Selection
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of a selection. Will highlight by default but can be overridden by subclasses.
		// Given a span (unzoned start/end and other misc data)
		renderSelection: function(span) {
			this.renderHighlight(span);
		},


		// Unrenders any visual indications of a selection. Will unrender a highlight by default.
		unrenderSelection: function() {
			this.unrenderHighlight();
		},


		// Given the first and last date-spans of a selection, returns another date-span object.
		// Subclasses can override and provide additional data in the span object. Will be passed to renderSelection().
		// Will return false if the selection is invalid and this should be indicated to the user.
		// Will return null/undefined if a selection invalid but no error should be reported.
		computeSelection: function(span0, span1) {
			var span = this.computeSelectionSpan(span0, span1);

			if (span && !this.view.calendar.isSelectionSpanAllowed(span)) {
				return false;
			}

			return span;
		},


		// Given two spans, must return the combination of the two.
		// TODO: do this separation of concerns (combining VS validation) for event dnd/resize too.
		computeSelectionSpan: function(span0, span1) {
			var dates = [ span0.start, span0.end, span1.start, span1.end ];

			dates.sort(compareNumbers); // sorts chronologically. works with Moments

			return { start: dates[0].clone(), end: dates[3].clone() };
		},


		/* Highlight
		------------------------------------------------------------------------------------------------------------------*/


		// Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data)
		renderHighlight: function(span) {
			this.renderFill('highlight', this.spanToSegs(span));
		},


		// Unrenders the emphasis on a date range
		unrenderHighlight: function() {
			this.unrenderFill('highlight');
		},


		// Generates an array of classNames for rendering the highlight. Used by the fill system.
		highlightSegClasses: function() {
			return [ 'fc-highlight' ];
		},


		/* Business Hours
		------------------------------------------------------------------------------------------------------------------*/


		renderBusinessHours: function() {
		},


		unrenderBusinessHours: function() {
		},


		/* Now Indicator
		------------------------------------------------------------------------------------------------------------------*/


		getNowIndicatorUnit: function() {
		},


		renderNowIndicator: function(date) {
		},


		unrenderNowIndicator: function() {
		},


		/* Fill System (highlight, background events, business hours)
		--------------------------------------------------------------------------------------------------------------------
		TODO: remove this system. like we did in TimeGrid
		*/


		// Renders a set of rectangles over the given segments of time.
		// MUST RETURN a subset of segs, the segs that were actually rendered.
		// Responsible for populating this.elsByFill. TODO: better API for expressing this requirement
		renderFill: function(type, segs) {
			// subclasses must implement
		},


		// Unrenders a specific type of fill that is currently rendered on the grid
		unrenderFill: function(type) {
			var el = this.elsByFill[type];

			if (el) {
				el.remove();
				delete this.elsByFill[type];
			}
		},


		// Renders and assigns an `el` property for each fill segment. Generic enough to work with different types.
		// Only returns segments that successfully rendered.
		// To be harnessed by renderFill (implemented by subclasses).
		// Analagous to renderFgSegEls.
		renderFillSegEls: function(type, segs) {
			var _this = this;
			var segElMethod = this[type + 'SegEl'];
			var html = '';
			var renderedSegs = [];
			var i;

			if (segs.length) {

				// build a large concatenation of segment HTML
				for (i = 0; i < segs.length; i++) {
					html += this.fillSegHtml(type, segs[i]);
				}

				// Grab individual elements from the combined HTML string. Use each as the default rendering.
				// Then, compute the 'el' for each segment.
				$(html).each(function(i, node) {
					var seg = segs[i];
					var el = $(node);

					// allow custom filter methods per-type
					if (segElMethod) {
						el = segElMethod.call(_this, seg, el);
					}

					if (el) { // custom filters did not cancel the render
						el = $(el); // allow custom filter to return raw DOM node

						// correct element type? (would be bad if a non-TD were inserted into a table for example)
						if (el.is(_this.fillSegTag)) {
							seg.el = el;
							renderedSegs.push(seg);
						}
					}
				});
			}

			return renderedSegs;
		},


		fillSegTag: 'div', // subclasses can override


		// Builds the HTML needed for one fill segment. Generic enough to work with different types.
		fillSegHtml: function(type, seg) {

			// custom hooks per-type
			var classesMethod = this[type + 'SegClasses'];
			var cssMethod = this[type + 'SegCss'];

			var classes = classesMethod ? classesMethod.call(this, seg) : [];
			var css = cssToStr(cssMethod ? cssMethod.call(this, seg) : {});

			return '<' + this.fillSegTag +
				(classes.length ? ' class="' + classes.join(' ') + '"' : '') +
				(css ? ' style="' + css + '"' : '') +
				' />';
		},



		/* Generic rendering utilities for subclasses
		------------------------------------------------------------------------------------------------------------------*/


		// Computes HTML classNames for a single-day element
		getDayClasses: function(date) {
			var view = this.view;
			var today = view.calendar.getNow();
			var classes = [ 'fc-' + dayIDs[date.day()] ];

			if (
				view.intervalDuration.as('months') == 1 &&
				date.month() != view.intervalStart.month()
			) {
				classes.push('fc-other-month');
			}

			if (date.isSame(today, 'day')) {
				classes.push(
					'fc-today',
					view.highlightStateClass
				);
			}
			else if (date < today) {
				classes.push('fc-past');
			}
			else {
				classes.push('fc-future');
			}

			return classes;
		}

	});

	;;

	/* Event-rendering and event-interaction methods for the abstract Grid class
	----------------------------------------------------------------------------------------------------------------------*/

	Grid.mixin({

		// self-config, overridable by subclasses
		segSelector: '.fc-event-container > *', // what constitutes an event element?

		mousedOverSeg: null, // the segment object the user's mouse is over. null if over nothing
		isDraggingSeg: false, // is a segment being dragged? boolean
		isResizingSeg: false, // is a segment being resized? boolean
		isDraggingExternal: false, // jqui-dragging an external element? boolean
		segs: null, // the *event* segments currently rendered in the grid. TODO: rename to `eventSegs`


		// Renders the given events onto the grid
		renderEvents: function(events) {
			var bgEvents = [];
			var fgEvents = [];
			var i;

			for (i = 0; i < events.length; i++) {
				(isBgEvent(events[i]) ? bgEvents : fgEvents).push(events[i]);
			}

			this.segs = [].concat( // record all segs
				this.renderBgEvents(bgEvents),
				this.renderFgEvents(fgEvents)
			);
		},


		renderBgEvents: function(events) {
			var segs = this.eventsToSegs(events);

			// renderBgSegs might return a subset of segs, segs that were actually rendered
			return this.renderBgSegs(segs) || segs;
		},


		renderFgEvents: function(events) {
			var segs = this.eventsToSegs(events);

			// renderFgSegs might return a subset of segs, segs that were actually rendered
			return this.renderFgSegs(segs) || segs;
		},


		// Unrenders all events currently rendered on the grid
		unrenderEvents: function() {
			this.handleSegMouseout(); // trigger an eventMouseout if user's mouse is over an event
			this.clearDragListeners();

			this.unrenderFgSegs();
			this.unrenderBgSegs();

			this.segs = null;
		},


		// Retrieves all rendered segment objects currently rendered on the grid
		getEventSegs: function() {
			return this.segs || [];
		},


		/* Foreground Segment Rendering
		------------------------------------------------------------------------------------------------------------------*/


		// Renders foreground event segments onto the grid. May return a subset of segs that were rendered.
		renderFgSegs: function(segs) {
			// subclasses must implement
		},


		// Unrenders all currently rendered foreground segments
		unrenderFgSegs: function() {
			// subclasses must implement
		},


		// Renders and assigns an `el` property for each foreground event segment.
		// Only returns segments that successfully rendered.
		// A utility that subclasses may use.
		renderFgSegEls: function(segs, disableResizing) {
			var view = this.view;
			var html = '';
			var renderedSegs = [];
			var i;

			if (segs.length) { // don't build an empty html string

				// build a large concatenation of event segment HTML
				for (i = 0; i < segs.length; i++) {
					html += this.fgSegHtml(segs[i], disableResizing);
				}

				// Grab individual elements from the combined HTML string. Use each as the default rendering.
				// Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.
				$(html).each(function(i, node) {
					var seg = segs[i];
					var el = view.resolveEventEl(seg.event, $(node));

					if (el) {
						el.data('fc-seg', seg); // used by handlers
						seg.el = el;
						renderedSegs.push(seg);
					}
				});
			}

			return renderedSegs;
		},


		// Generates the HTML for the default rendering of a foreground event segment. Used by renderFgSegEls()
		fgSegHtml: function(seg, disableResizing) {
			// subclasses should implement
		},


		/* Background Segment Rendering
		------------------------------------------------------------------------------------------------------------------*/


		// Renders the given background event segments onto the grid.
		// Returns a subset of the segs that were actually rendered.
		renderBgSegs: function(segs) {
			return this.renderFill('bgEvent', segs);
		},


		// Unrenders all the currently rendered background event segments
		unrenderBgSegs: function() {
			this.unrenderFill('bgEvent');
		},


		// Renders a background event element, given the default rendering. Called by the fill system.
		bgEventSegEl: function(seg, el) {
			return this.view.resolveEventEl(seg.event, el); // will filter through eventRender
		},


		// Generates an array of classNames to be used for the default rendering of a background event.
		// Called by fillSegHtml.
		bgEventSegClasses: function(seg) {
			var event = seg.event;
			var source = event.source || {};

			return [ 'fc-bgevent' ].concat(
				event.className,
				source.className || []
			);
		},


		// Generates a semicolon-separated CSS string to be used for the default rendering of a background event.
		// Called by fillSegHtml.
		bgEventSegCss: function(seg) {
			return {
				'background-color': this.getSegSkinCss(seg)['background-color']
			};
		},


		// Generates an array of classNames to be used for the rendering business hours overlay. Called by the fill system.
		// Called by fillSegHtml.
		businessHoursSegClasses: function(seg) {
			return [ 'fc-nonbusiness', 'fc-bgevent' ];
		},


		/* Business Hours
		------------------------------------------------------------------------------------------------------------------*/


		// Compute business hour segs for the grid's current date range.
		// Caller must ask if whole-day business hours are needed.
		buildBusinessHourSegs: function(wholeDay) {
			var events = this.view.calendar.getCurrentBusinessHourEvents(wholeDay);

			// HACK. Eventually refactor business hours "events" system.
			// If no events are given, but businessHours is activated, this means the entire visible range should be
			// marked as *not* business-hours, via inverse-background rendering.
			if (
				!events.length &&
				this.view.calendar.options.businessHours // don't access view option. doesn't update with dynamic options
			) {
				events = [
					$.extend({}, BUSINESS_HOUR_EVENT_DEFAULTS, {
						start: this.view.end, // guaranteed out-of-range
						end: this.view.end,   // "
						dow: null
					})
				];
			}

			return this.eventsToSegs(events);
		},


		/* Handlers
		------------------------------------------------------------------------------------------------------------------*/


		// Attaches event-element-related handlers for *all* rendered event segments of the view.
		bindSegHandlers: function() {
			this.bindSegHandlersToEl(this.el);
		},


		// Attaches event-element-related handlers to an arbitrary container element. leverages bubbling.
		bindSegHandlersToEl: function(el) {
			this.bindSegHandlerToEl(el, 'touchstart', this.handleSegTouchStart);
			this.bindSegHandlerToEl(el, 'touchend', this.handleSegTouchEnd);
			this.bindSegHandlerToEl(el, 'mouseenter', this.handleSegMouseover);
			this.bindSegHandlerToEl(el, 'mouseleave', this.handleSegMouseout);
			this.bindSegHandlerToEl(el, 'mousedown', this.handleSegMousedown);
			this.bindSegHandlerToEl(el, 'click', this.handleSegClick);
		},


		// Executes a handler for any a user-interaction on a segment.
		// Handler gets called with (seg, ev), and with the `this` context of the Grid
		bindSegHandlerToEl: function(el, name, handler) {
			var _this = this;

			el.on(name, this.segSelector, function(ev) {
				var seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents

				// only call the handlers if there is not a drag/resize in progress
				if (seg && !_this.isDraggingSeg && !_this.isResizingSeg) {
					return handler.call(_this, seg, ev); // context will be the Grid
				}
			});
		},


		handleSegClick: function(seg, ev) {
			var res = this.view.trigger('eventClick', seg.el[0], seg.event, ev); // can return `false` to cancel
			if (res === false) {
				ev.preventDefault();
			}
		},


		// Updates internal state and triggers handlers for when an event element is moused over
		handleSegMouseover: function(seg, ev) {
			if (
				!this.isIgnoringMouse &&
				!this.mousedOverSeg
			) {
				this.mousedOverSeg = seg;
				if (this.view.isEventResizable(seg.event)) {
					seg.el.addClass('fc-allow-mouse-resize');
				}
				this.view.trigger('eventMouseover', seg.el[0], seg.event, ev);
			}
		},


		// Updates internal state and triggers handlers for when an event element is moused out.
		// Can be given no arguments, in which case it will mouseout the segment that was previously moused over.
		handleSegMouseout: function(seg, ev) {
			ev = ev || {}; // if given no args, make a mock mouse event

			if (this.mousedOverSeg) {
				seg = seg || this.mousedOverSeg; // if given no args, use the currently moused-over segment
				this.mousedOverSeg = null;
				if (this.view.isEventResizable(seg.event)) {
					seg.el.removeClass('fc-allow-mouse-resize');
				}
				this.view.trigger('eventMouseout', seg.el[0], seg.event, ev);
			}
		},


		handleSegMousedown: function(seg, ev) {
			var isResizing = this.startSegResize(seg, ev, { distance: 5 });

			if (!isResizing && this.view.isEventDraggable(seg.event)) {
				this.buildSegDragListener(seg)
					.startInteraction(ev, {
						distance: 5
					});
			}
		},


		handleSegTouchStart: function(seg, ev) {
			var view = this.view;
			var event = seg.event;
			var isSelected = view.isEventSelected(event);
			var isDraggable = view.isEventDraggable(event);
			var isResizable = view.isEventResizable(event);
			var isResizing = false;
			var dragListener;

			if (isSelected && isResizable) {
				// only allow resizing of the event is selected
				isResizing = this.startSegResize(seg, ev);
			}

			if (!isResizing && (isDraggable || isResizable)) { // allowed to be selected?

				dragListener = isDraggable ?
					this.buildSegDragListener(seg) :
					this.buildSegSelectListener(seg); // seg isn't draggable, but still needs to be selected

				dragListener.startInteraction(ev, { // won't start if already started
					delay: isSelected ? 0 : this.view.opt('longPressDelay') // do delay if not already selected
				});
			}

			// a long tap simulates a mouseover. ignore this bogus mouseover.
			this.tempIgnoreMouse();
		},


		handleSegTouchEnd: function(seg, ev) {
			// touchstart+touchend = click, which simulates a mouseover.
			// ignore this bogus mouseover.
			this.tempIgnoreMouse();
		},


		// returns boolean whether resizing actually started or not.
		// assumes the seg allows resizing.
		// `dragOptions` are optional.
		startSegResize: function(seg, ev, dragOptions) {
			if ($(ev.target).is('.fc-resizer')) {
				this.buildSegResizeListener(seg, $(ev.target).is('.fc-start-resizer'))
					.startInteraction(ev, dragOptions);
				return true;
			}
			return false;
		},



		/* Event Dragging
		------------------------------------------------------------------------------------------------------------------*/


		// Builds a listener that will track user-dragging on an event segment.
		// Generic enough to work with any type of Grid.
		// Has side effect of setting/unsetting `segDragListener`
		buildSegDragListener: function(seg) {
			var _this = this;
			var view = this.view;
			var calendar = view.calendar;
			var el = seg.el;
			var event = seg.event;
			var isDragging;
			var mouseFollower; // A clone of the original element that will move with the mouse
			var dropLocation; // zoned event date properties

			if (this.segDragListener) {
				return this.segDragListener;
			}

			// Tracks mouse movement over the *view's* coordinate map. Allows dragging and dropping between subcomponents
			// of the view.
			var dragListener = this.segDragListener = new HitDragListener(view, {
				scroll: view.opt('dragScroll'),
				subjectEl: el,
				subjectCenter: true,
				interactionStart: function(ev) {
					seg.component = _this; // for renderDrag
					isDragging = false;
					mouseFollower = new MouseFollower(seg.el, {
						additionalClass: 'fc-dragging',
						parentEl: view.el,
						opacity: dragListener.isTouch ? null : view.opt('dragOpacity'),
						revertDuration: view.opt('dragRevertDuration'),
						zIndex: 2 // one above the .fc-view
					});
					mouseFollower.hide(); // don't show until we know this is a real drag
					mouseFollower.start(ev);
				},
				dragStart: function(ev) {
					if (dragListener.isTouch && !view.isEventSelected(event)) {
						// if not previously selected, will fire after a delay. then, select the event
						view.selectEvent(event);
					}
					isDragging = true;
					_this.handleSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
					_this.segDragStart(seg, ev);
					view.hideEvent(event); // hide all event segments. our mouseFollower will take over
				},
				hitOver: function(hit, isOrig, origHit) {
					var dragHelperEls;

					// starting hit could be forced (DayGrid.limit)
					if (seg.hit) {
						origHit = seg.hit;
					}

					// since we are querying the parent view, might not belong to this grid
					dropLocation = _this.computeEventDrop(
						origHit.component.getHitSpan(origHit),
						hit.component.getHitSpan(hit),
						event
					);

					if (dropLocation && !calendar.isEventSpanAllowed(_this.eventToSpan(dropLocation), event)) {
						disableCursor();
						dropLocation = null;
					}

					// if a valid drop location, have the subclass render a visual indication
					if (dropLocation && (dragHelperEls = view.renderDrag(dropLocation, seg))) {

						dragHelperEls.addClass('fc-dragging');
						if (!dragListener.isTouch) {
							_this.applyDragOpacity(dragHelperEls);
						}

						mouseFollower.hide(); // if the subclass is already using a mock event "helper", hide our own
					}
					else {
						mouseFollower.show(); // otherwise, have the helper follow the mouse (no snapping)
					}

					if (isOrig) {
						dropLocation = null; // needs to have moved hits to be a valid drop
					}
				},
				hitOut: function() { // called before mouse moves to a different hit OR moved out of all hits
					view.unrenderDrag(); // unrender whatever was done in renderDrag
					mouseFollower.show(); // show in case we are moving out of all hits
					dropLocation = null;
				},
				hitDone: function() { // Called after a hitOut OR before a dragEnd
					enableCursor();
				},
				interactionEnd: function(ev) {
					delete seg.component; // prevent side effects

					// do revert animation if hasn't changed. calls a callback when finished (whether animation or not)
					mouseFollower.stop(!dropLocation, function() {
						if (isDragging) {
							view.unrenderDrag();
							view.showEvent(event);
							_this.segDragStop(seg, ev);
						}
						if (dropLocation) {
							view.reportEventDrop(event, dropLocation, this.largeUnit, el, ev);
						}
					});
					_this.segDragListener = null;
				}
			});

			return dragListener;
		},


		// seg isn't draggable, but let's use a generic DragListener
		// simply for the delay, so it can be selected.
		// Has side effect of setting/unsetting `segDragListener`
		buildSegSelectListener: function(seg) {
			var _this = this;
			var view = this.view;
			var event = seg.event;

			if (this.segDragListener) {
				return this.segDragListener;
			}

			var dragListener = this.segDragListener = new DragListener({
				dragStart: function(ev) {
					if (dragListener.isTouch && !view.isEventSelected(event)) {
						// if not previously selected, will fire after a delay. then, select the event
						view.selectEvent(event);
					}
				},
				interactionEnd: function(ev) {
					_this.segDragListener = null;
				}
			});

			return dragListener;
		},


		// Called before event segment dragging starts
		segDragStart: function(seg, ev) {
			this.isDraggingSeg = true;
			this.view.trigger('eventDragStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
		},


		// Called after event segment dragging stops
		segDragStop: function(seg, ev) {
			this.isDraggingSeg = false;
			this.view.trigger('eventDragStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
		},


		// Given the spans an event drag began, and the span event was dropped, calculates the new zoned start/end/allDay
		// values for the event. Subclasses may override and set additional properties to be used by renderDrag.
		// A falsy returned value indicates an invalid drop.
		// DOES NOT consider overlap/constraint.
		computeEventDrop: function(startSpan, endSpan, event) {
			var calendar = this.view.calendar;
			var dragStart = startSpan.start;
			var dragEnd = endSpan.start;
			var delta;
			var dropLocation; // zoned event date properties

			if (dragStart.hasTime() === dragEnd.hasTime()) {
				delta = this.diffDates(dragEnd, dragStart);

				// if an all-day event was in a timed area and it was dragged to a different time,
				// guarantee an end and adjust start/end to have times
				if (event.allDay && durationHasTime(delta)) {
					dropLocation = {
						start: event.start.clone(),
						end: calendar.getEventEnd(event), // will be an ambig day
						allDay: false // for normalizeEventTimes
					};
					calendar.normalizeEventTimes(dropLocation);
				}
				// othewise, work off existing values
				else {
					dropLocation = {
						start: event.start.clone(),
						end: event.end ? event.end.clone() : null,
						allDay: event.allDay // keep it the same
					};
				}

				dropLocation.start.add(delta);
				if (dropLocation.end) {
					dropLocation.end.add(delta);
				}
			}
			else {
				// if switching from day <-> timed, start should be reset to the dropped date, and the end cleared
				dropLocation = {
					start: dragEnd.clone(),
					end: null, // end should be cleared
					allDay: !dragEnd.hasTime()
				};
			}

			return dropLocation;
		},


		// Utility for apply dragOpacity to a jQuery set
		applyDragOpacity: function(els) {
			var opacity = this.view.opt('dragOpacity');

			if (opacity != null) {
				els.css('opacity', opacity);
			}
		},


		/* External Element Dragging
		------------------------------------------------------------------------------------------------------------------*/


		// Called when a jQuery UI drag is initiated anywhere in the DOM
		externalDragStart: function(ev, ui) {
			var view = this.view;
			var el;
			var accept;

			if (view.opt('droppable')) { // only listen if this setting is on
				el = $((ui ? ui.item : null) || ev.target);

				// Test that the dragged element passes the dropAccept selector or filter function.
				// FYI, the default is "*" (matches all)
				accept = view.opt('dropAccept');
				if ($.isFunction(accept) ? accept.call(el[0], el) : el.is(accept)) {
					if (!this.isDraggingExternal) { // prevent double-listening if fired twice
						this.listenToExternalDrag(el, ev, ui);
					}
				}
			}
		},


		// Called when a jQuery UI drag starts and it needs to be monitored for dropping
		listenToExternalDrag: function(el, ev, ui) {
			var _this = this;
			var calendar = this.view.calendar;
			var meta = getDraggedElMeta(el); // extra data about event drop, including possible event to create
			var dropLocation; // a null value signals an unsuccessful drag

			// listener that tracks mouse movement over date-associated pixel regions
			var dragListener = _this.externalDragListener = new HitDragListener(this, {
				interactionStart: function() {
					_this.isDraggingExternal = true;
				},
				hitOver: function(hit) {
					dropLocation = _this.computeExternalDrop(
						hit.component.getHitSpan(hit), // since we are querying the parent view, might not belong to this grid
						meta
					);

					if ( // invalid hit?
						dropLocation &&
						!calendar.isExternalSpanAllowed(_this.eventToSpan(dropLocation), dropLocation, meta.eventProps)
					) {
						disableCursor();
						dropLocation = null;
					}

					if (dropLocation) {
						_this.renderDrag(dropLocation); // called without a seg parameter
					}
				},
				hitOut: function() {
					dropLocation = null; // signal unsuccessful
				},
				hitDone: function() { // Called after a hitOut OR before a dragEnd
					enableCursor();
					_this.unrenderDrag();
				},
				interactionEnd: function(ev) {
					if (dropLocation) { // element was dropped on a valid hit
						_this.view.reportExternalDrop(meta, dropLocation, el, ev, ui);
					}
					_this.isDraggingExternal = false;
					_this.externalDragListener = null;
				}
			});

			dragListener.startDrag(ev); // start listening immediately
		},


		// Given a hit to be dropped upon, and misc data associated with the jqui drag (guaranteed to be a plain object),
		// returns the zoned start/end dates for the event that would result from the hypothetical drop. end might be null.
		// Returning a null value signals an invalid drop hit.
		// DOES NOT consider overlap/constraint.
		computeExternalDrop: function(span, meta) {
			var calendar = this.view.calendar;
			var dropLocation = {
				start: calendar.applyTimezone(span.start), // simulate a zoned event start date
				end: null
			};

			// if dropped on an all-day span, and element's metadata specified a time, set it
			if (meta.startTime && !dropLocation.start.hasTime()) {
				dropLocation.start.time(meta.startTime);
			}

			if (meta.duration) {
				dropLocation.end = dropLocation.start.clone().add(meta.duration);
			}

			return dropLocation;
		},



		/* Drag Rendering (for both events and an external elements)
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of an event or external element being dragged.
		// `dropLocation` contains hypothetical start/end/allDay values the event would have if dropped. end can be null.
		// `seg` is the internal segment object that is being dragged. If dragging an external element, `seg` is null.
		// A truthy returned value indicates this method has rendered a helper element.
		// Must return elements used for any mock events.
		renderDrag: function(dropLocation, seg) {
			// subclasses must implement
		},


		// Unrenders a visual indication of an event or external element being dragged
		unrenderDrag: function() {
			// subclasses must implement
		},


		/* Resizing
		------------------------------------------------------------------------------------------------------------------*/


		// Creates a listener that tracks the user as they resize an event segment.
		// Generic enough to work with any type of Grid.
		buildSegResizeListener: function(seg, isStart) {
			var _this = this;
			var view = this.view;
			var calendar = view.calendar;
			var el = seg.el;
			var event = seg.event;
			var eventEnd = calendar.getEventEnd(event);
			var isDragging;
			var resizeLocation; // zoned event date properties. falsy if invalid resize

			// Tracks mouse movement over the *grid's* coordinate map
			var dragListener = this.segResizeListener = new HitDragListener(this, {
				scroll: view.opt('dragScroll'),
				subjectEl: el,
				interactionStart: function() {
					isDragging = false;
				},
				dragStart: function(ev) {
					isDragging = true;
					_this.handleSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
					_this.segResizeStart(seg, ev);
				},
				hitOver: function(hit, isOrig, origHit) {
					var origHitSpan = _this.getHitSpan(origHit);
					var hitSpan = _this.getHitSpan(hit);

					resizeLocation = isStart ?
						_this.computeEventStartResize(origHitSpan, hitSpan, event) :
						_this.computeEventEndResize(origHitSpan, hitSpan, event);

					if (resizeLocation) {
						if (!calendar.isEventSpanAllowed(_this.eventToSpan(resizeLocation), event)) {
							disableCursor();
							resizeLocation = null;
						}
						// no change? (FYI, event dates might have zones)
						else if (
							resizeLocation.start.isSame(event.start.clone().stripZone()) &&
							resizeLocation.end.isSame(eventEnd.clone().stripZone())
						) {
							resizeLocation = null;
						}
					}

					if (resizeLocation) {
						view.hideEvent(event);
						_this.renderEventResize(resizeLocation, seg);
					}
				},
				hitOut: function() { // called before mouse moves to a different hit OR moved out of all hits
					resizeLocation = null;
				},
				hitDone: function() { // resets the rendering to show the original event
					_this.unrenderEventResize();
					view.showEvent(event);
					enableCursor();
				},
				interactionEnd: function(ev) {
					if (isDragging) {
						_this.segResizeStop(seg, ev);
					}
					if (resizeLocation) { // valid date to resize to?
						view.reportEventResize(event, resizeLocation, this.largeUnit, el, ev);
					}
					_this.segResizeListener = null;
				}
			});

			return dragListener;
		},


		// Called before event segment resizing starts
		segResizeStart: function(seg, ev) {
			this.isResizingSeg = true;
			this.view.trigger('eventResizeStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
		},


		// Called after event segment resizing stops
		segResizeStop: function(seg, ev) {
			this.isResizingSeg = false;
			this.view.trigger('eventResizeStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy
		},


		// Returns new date-information for an event segment being resized from its start
		computeEventStartResize: function(startSpan, endSpan, event) {
			return this.computeEventResize('start', startSpan, endSpan, event);
		},


		// Returns new date-information for an event segment being resized from its end
		computeEventEndResize: function(startSpan, endSpan, event) {
			return this.computeEventResize('end', startSpan, endSpan, event);
		},


		// Returns new zoned date information for an event segment being resized from its start OR end
		// `type` is either 'start' or 'end'.
		// DOES NOT consider overlap/constraint.
		computeEventResize: function(type, startSpan, endSpan, event) {
			var calendar = this.view.calendar;
			var delta = this.diffDates(endSpan[type], startSpan[type]);
			var resizeLocation; // zoned event date properties
			var defaultDuration;

			// build original values to work from, guaranteeing a start and end
			resizeLocation = {
				start: event.start.clone(),
				end: calendar.getEventEnd(event),
				allDay: event.allDay
			};

			// if an all-day event was in a timed area and was resized to a time, adjust start/end to have times
			if (resizeLocation.allDay && durationHasTime(delta)) {
				resizeLocation.allDay = false;
				calendar.normalizeEventTimes(resizeLocation);
			}

			resizeLocation[type].add(delta); // apply delta to start or end

			// if the event was compressed too small, find a new reasonable duration for it
			if (!resizeLocation.start.isBefore(resizeLocation.end)) {

				defaultDuration =
					this.minResizeDuration || // TODO: hack
					(event.allDay ?
						calendar.defaultAllDayEventDuration :
						calendar.defaultTimedEventDuration);

				if (type == 'start') { // resizing the start?
					resizeLocation.start = resizeLocation.end.clone().subtract(defaultDuration);
				}
				else { // resizing the end?
					resizeLocation.end = resizeLocation.start.clone().add(defaultDuration);
				}
			}

			return resizeLocation;
		},


		// Renders a visual indication of an event being resized.
		// `range` has the updated dates of the event. `seg` is the original segment object involved in the drag.
		// Must return elements used for any mock events.
		renderEventResize: function(range, seg) {
			// subclasses must implement
		},


		// Unrenders a visual indication of an event being resized.
		unrenderEventResize: function() {
			// subclasses must implement
		},


		/* Rendering Utils
		------------------------------------------------------------------------------------------------------------------*/


		// Compute the text that should be displayed on an event's element.
		// `range` can be the Event object itself, or something range-like, with at least a `start`.
		// If event times are disabled, or the event has no time, will return a blank string.
		// If not specified, formatStr will default to the eventTimeFormat setting,
		// and displayEnd will default to the displayEventEnd setting.
		getEventTimeText: function(range, formatStr, displayEnd) {

			if (formatStr == null) {
				formatStr = this.eventTimeFormat;
			}

			if (displayEnd == null) {
				displayEnd = this.displayEventEnd;
			}

			if (this.displayEventTime && range.start.hasTime()) {
				if (displayEnd && range.end) {
					return this.view.formatRange(range, formatStr);
				}
				else {
					return range.start.format(formatStr);
				}
			}

			return '';
		},


		// Generic utility for generating the HTML classNames for an event segment's element
		getSegClasses: function(seg, isDraggable, isResizable) {
			var view = this.view;
			var classes = [
				'fc-event',
				seg.isStart ? 'fc-start' : 'fc-not-start',
				seg.isEnd ? 'fc-end' : 'fc-not-end'
			].concat(this.getSegCustomClasses(seg));

			if (isDraggable) {
				classes.push('fc-draggable');
			}
			if (isResizable) {
				classes.push('fc-resizable');
			}

			// event is currently selected? attach a className.
			if (view.isEventSelected(seg.event)) {
				classes.push('fc-selected');
			}

			return classes;
		},


		// List of classes that were defined by the caller of the API in some way
		getSegCustomClasses: function(seg) {
			var event = seg.event;

			return [].concat(
				event.className, // guaranteed to be an array
				event.source ? event.source.className : []
			);
		},


		// Utility for generating event skin-related CSS properties
		getSegSkinCss: function(seg) {
			return {
				'background-color': this.getSegBackgroundColor(seg),
				'border-color': this.getSegBorderColor(seg),
				color: this.getSegTextColor(seg)
			};
		},


		// Queries for caller-specified color, then falls back to default
		getSegBackgroundColor: function(seg) {
			return seg.event.backgroundColor ||
				seg.event.color ||
				this.getSegDefaultBackgroundColor(seg);
		},


		getSegDefaultBackgroundColor: function(seg) {
			var source = seg.event.source || {};

			return source.backgroundColor ||
				source.color ||
				this.view.opt('eventBackgroundColor') ||
				this.view.opt('eventColor');
		},


		// Queries for caller-specified color, then falls back to default
		getSegBorderColor: function(seg) {
			return seg.event.borderColor ||
				seg.event.color ||
				this.getSegDefaultBorderColor(seg);
		},


		getSegDefaultBorderColor: function(seg) {
			var source = seg.event.source || {};

			return source.borderColor ||
				source.color ||
				this.view.opt('eventBorderColor') ||
				this.view.opt('eventColor');
		},


		// Queries for caller-specified color, then falls back to default
		getSegTextColor: function(seg) {
			return seg.event.textColor ||
				this.getSegDefaultTextColor(seg);
		},


		getSegDefaultTextColor: function(seg) {
			var source = seg.event.source || {};

			return source.textColor ||
				this.view.opt('eventTextColor');
		},


		/* Converting events -> eventRange -> eventSpan -> eventSegs
		------------------------------------------------------------------------------------------------------------------*/


		// Generates an array of segments for the given single event
		// Can accept an event "location" as well (which only has start/end and no allDay)
		eventToSegs: function(event) {
			return this.eventsToSegs([ event ]);
		},


		eventToSpan: function(event) {
			return this.eventToSpans(event)[0];
		},


		// Generates spans (always unzoned) for the given event.
		// Does not do any inverting for inverse-background events.
		// Can accept an event "location" as well (which only has start/end and no allDay)
		eventToSpans: function(event) {
			var range = this.eventToRange(event);
			return this.eventRangeToSpans(range, event);
		},



		// Converts an array of event objects into an array of event segment objects.
		// A custom `segSliceFunc` may be given for arbitrarily slicing up events.
		// Doesn't guarantee an order for the resulting array.
		eventsToSegs: function(allEvents, segSliceFunc) {
			var _this = this;
			var eventsById = groupEventsById(allEvents);
			var segs = [];

			$.each(eventsById, function(id, events) {
				var ranges = [];
				var i;

				for (i = 0; i < events.length; i++) {
					ranges.push(_this.eventToRange(events[i]));
				}

				// inverse-background events (utilize only the first event in calculations)
				if (isInverseBgEvent(events[0])) {
					ranges = _this.invertRanges(ranges);

					for (i = 0; i < ranges.length; i++) {
						segs.push.apply(segs, // append to
							_this.eventRangeToSegs(ranges[i], events[0], segSliceFunc));
					}
				}
				// normal event ranges
				else {
					for (i = 0; i < ranges.length; i++) {
						segs.push.apply(segs, // append to
							_this.eventRangeToSegs(ranges[i], events[i], segSliceFunc));
					}
				}
			});

			return segs;
		},


		// Generates the unzoned start/end dates an event appears to occupy
		// Can accept an event "location" as well (which only has start/end and no allDay)
		eventToRange: function(event) {
			var calendar = this.view.calendar;
			var start = event.start.clone().stripZone();
			var end = (
					event.end ?
						event.end.clone() :
						// derive the end from the start and allDay. compute allDay if necessary
						calendar.getDefaultEventEnd(
							event.allDay != null ?
								event.allDay :
								!event.start.hasTime(),
							event.start
						)
				).stripZone();

			// hack: dynamic locale change forgets to upate stored event localed
			calendar.localizeMoment(start);
			calendar.localizeMoment(end);

			return { start: start, end: end };
		},


		// Given an event's range (unzoned start/end), and the event itself,
		// slice into segments (using the segSliceFunc function if specified)
		eventRangeToSegs: function(range, event, segSliceFunc) {
			var spans = this.eventRangeToSpans(range, event);
			var segs = [];
			var i;

			for (i = 0; i < spans.length; i++) {
				segs.push.apply(segs, // append to
					this.eventSpanToSegs(spans[i], event, segSliceFunc));
			}

			return segs;
		},


		// Given an event's unzoned date range, return an array of "span" objects.
		// Subclasses can override.
		eventRangeToSpans: function(range, event) {
			return [ $.extend({}, range) ]; // copy into a single-item array
		},


		// Given an event's span (unzoned start/end and other misc data), and the event itself,
		// slices into segments and attaches event-derived properties to them.
		eventSpanToSegs: function(span, event, segSliceFunc) {
			var segs = segSliceFunc ? segSliceFunc(span) : this.spanToSegs(span);
			var i, seg;

			for (i = 0; i < segs.length; i++) {
				seg = segs[i];
				seg.event = event;
				seg.eventStartMS = +span.start; // TODO: not the best name after making spans unzoned
				seg.eventDurationMS = span.end - span.start;
			}

			return segs;
		},


		// Produces a new array of range objects that will cover all the time NOT covered by the given ranges.
		// SIDE EFFECT: will mutate the given array and will use its date references.
		invertRanges: function(ranges) {
			var view = this.view;
			var viewStart = view.start.clone(); // need a copy
			var viewEnd = view.end.clone(); // need a copy
			var inverseRanges = [];
			var start = viewStart; // the end of the previous range. the start of the new range
			var i, range;

			// ranges need to be in order. required for our date-walking algorithm
			ranges.sort(compareRanges);

			for (i = 0; i < ranges.length; i++) {
				range = ranges[i];

				// add the span of time before the event (if there is any)
				if (range.start > start) { // compare millisecond time (skip any ambig logic)
					inverseRanges.push({
						start: start,
						end: range.start
					});
				}

				start = range.end;
			}

			// add the span of time after the last event (if there is any)
			if (start < viewEnd) { // compare millisecond time (skip any ambig logic)
				inverseRanges.push({
					start: start,
					end: viewEnd
				});
			}

			return inverseRanges;
		},


		sortEventSegs: function(segs) {
			segs.sort(proxy(this, 'compareEventSegs'));
		},


		// A cmp function for determining which segments should take visual priority
		compareEventSegs: function(seg1, seg2) {
			return seg1.eventStartMS - seg2.eventStartMS || // earlier events go first
				seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first
				seg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1)
				compareByFieldSpecs(seg1.event, seg2.event, this.view.eventOrderSpecs);
		}

	});


	/* Utilities
	----------------------------------------------------------------------------------------------------------------------*/


	function isBgEvent(event) { // returns true if background OR inverse-background
		var rendering = getEventRendering(event);
		return rendering === 'background' || rendering === 'inverse-background';
	}
	FC.isBgEvent = isBgEvent; // export


	function isInverseBgEvent(event) {
		return getEventRendering(event) === 'inverse-background';
	}


	function getEventRendering(event) {
		return firstDefined((event.source || {}).rendering, event.rendering);
	}


	function groupEventsById(events) {
		var eventsById = {};
		var i, event;

		for (i = 0; i < events.length; i++) {
			event = events[i];
			(eventsById[event._id] || (eventsById[event._id] = [])).push(event);
		}

		return eventsById;
	}


	// A cmp function for determining which non-inverted "ranges" (see above) happen earlier
	function compareRanges(range1, range2) {
		return range1.start - range2.start; // earlier ranges go first
	}


	/* External-Dragging-Element Data
	----------------------------------------------------------------------------------------------------------------------*/

	// Require all HTML5 data-* attributes used by FullCalendar to have this prefix.
	// A value of '' will query attributes like data-event. A value of 'fc' will query attributes like data-fc-event.
	FC.dataAttrPrefix = '';

	// Given a jQuery element that might represent a dragged FullCalendar event, returns an intermediate data structure
	// to be used for Event Object creation.
	// A defined `.eventProps`, even when empty, indicates that an event should be created.
	function getDraggedElMeta(el) {
		var prefix = FC.dataAttrPrefix;
		var eventProps; // properties for creating the event, not related to date/time
		var startTime; // a Duration
		var duration;
		var stick;

		if (prefix) { prefix += '-'; }
		eventProps = el.data(prefix + 'event') || null;

		if (eventProps) {
			if (typeof eventProps === 'object') {
				eventProps = $.extend({}, eventProps); // make a copy
			}
			else { // something like 1 or true. still signal event creation
				eventProps = {};
			}

			// pluck special-cased date/time properties
			startTime = eventProps.start;
			if (startTime == null) { startTime = eventProps.time; } // accept 'time' as well
			duration = eventProps.duration;
			stick = eventProps.stick;
			delete eventProps.start;
			delete eventProps.time;
			delete eventProps.duration;
			delete eventProps.stick;
		}

		// fallback to standalone attribute values for each of the date/time properties
		if (startTime == null) { startTime = el.data(prefix + 'start'); }
		if (startTime == null) { startTime = el.data(prefix + 'time'); } // accept 'time' as well
		if (duration == null) { duration = el.data(prefix + 'duration'); }
		if (stick == null) { stick = el.data(prefix + 'stick'); }

		// massage into correct data types
		startTime = startTime != null ? moment.duration(startTime) : null;
		duration = duration != null ? moment.duration(duration) : null;
		stick = Boolean(stick);

		return { eventProps: eventProps, startTime: startTime, duration: duration, stick: stick };
	}


	;;

	/*
	A set of rendering and date-related methods for a visual component comprised of one or more rows of day columns.
	Prerequisite: the object being mixed into needs to be a *Grid*
	*/
	var DayTableMixin = FC.DayTableMixin = {

		breakOnWeeks: false, // should create a new row for each week?
		dayDates: null, // whole-day dates for each column. left to right
		dayIndices: null, // for each day from start, the offset
		daysPerRow: null,
		rowCnt: null,
		colCnt: null,
		colHeadFormat: null,


		// Populates internal variables used for date calculation and rendering
		updateDayTable: function() {
			var view = this.view;
			var date = this.start.clone();
			var dayIndex = -1;
			var dayIndices = [];
			var dayDates = [];
			var daysPerRow;
			var firstDay;
			var rowCnt;

			while (date.isBefore(this.end)) { // loop each day from start to end
				if (view.isHiddenDay(date)) {
					dayIndices.push(dayIndex + 0.5); // mark that it's between indices
				}
				else {
					dayIndex++;
					dayIndices.push(dayIndex);
					dayDates.push(date.clone());
				}
				date.add(1, 'days');
			}

			if (this.breakOnWeeks) {
				// count columns until the day-of-week repeats
				firstDay = dayDates[0].day();
				for (daysPerRow = 1; daysPerRow < dayDates.length; daysPerRow++) {
					if (dayDates[daysPerRow].day() == firstDay) {
						break;
					}
				}
				rowCnt = Math.ceil(dayDates.length / daysPerRow);
			}
			else {
				rowCnt = 1;
				daysPerRow = dayDates.length;
			}

			this.dayDates = dayDates;
			this.dayIndices = dayIndices;
			this.daysPerRow = daysPerRow;
			this.rowCnt = rowCnt;
			
			this.updateDayTableCols();
		},


		// Computes and assigned the colCnt property and updates any options that may be computed from it
		updateDayTableCols: function() {
			this.colCnt = this.computeColCnt();
			this.colHeadFormat = this.view.opt('columnFormat') || this.computeColHeadFormat();
		},


		// Determines how many columns there should be in the table
		computeColCnt: function() {
			return this.daysPerRow;
		},


		// Computes the ambiguously-timed moment for the given cell
		getCellDate: function(row, col) {
			return this.dayDates[
					this.getCellDayIndex(row, col)
				].clone();
		},


		// Computes the ambiguously-timed date range for the given cell
		getCellRange: function(row, col) {
			var start = this.getCellDate(row, col);
			var end = start.clone().add(1, 'days');

			return { start: start, end: end };
		},


		// Returns the number of day cells, chronologically, from the first of the grid (0-based)
		getCellDayIndex: function(row, col) {
			return row * this.daysPerRow + this.getColDayIndex(col);
		},


		// Returns the numner of day cells, chronologically, from the first cell in *any given row*
		getColDayIndex: function(col) {
			if (this.isRTL) {
				return this.colCnt - 1 - col;
			}
			else {
				return col;
			}
		},


		// Given a date, returns its chronolocial cell-index from the first cell of the grid.
		// If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
		// If before the first offset, returns a negative number.
		// If after the last offset, returns an offset past the last cell offset.
		// Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
		getDateDayIndex: function(date) {
			var dayIndices = this.dayIndices;
			var dayOffset = date.diff(this.start, 'days');

			if (dayOffset < 0) {
				return dayIndices[0] - 1;
			}
			else if (dayOffset >= dayIndices.length) {
				return dayIndices[dayIndices.length - 1] + 1;
			}
			else {
				return dayIndices[dayOffset];
			}
		},


		/* Options
		------------------------------------------------------------------------------------------------------------------*/


		// Computes a default column header formatting string if `colFormat` is not explicitly defined
		computeColHeadFormat: function() {
			// if more than one week row, or if there are a lot of columns with not much space,
			// put just the day numbers will be in each cell
			if (this.rowCnt > 1 || this.colCnt > 10) {
				return 'ddd'; // "Sat"
			}
			// multiple days, so full single date string WON'T be in title text
			else if (this.colCnt > 1) {
				return this.view.opt('dayOfMonthFormat'); // "Sat 12/10"
			}
			// single day, so full single date string will probably be in title text
			else {
				return 'dddd'; // "Saturday"
			}
		},


		/* Slicing
		------------------------------------------------------------------------------------------------------------------*/


		// Slices up a date range into a segment for every week-row it intersects with
		sliceRangeByRow: function(range) {
			var daysPerRow = this.daysPerRow;
			var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold
			var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
			var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
			var segs = [];
			var row;
			var rowFirst, rowLast; // inclusive day-index range for current row
			var segFirst, segLast; // inclusive day-index range for segment

			for (row = 0; row < this.rowCnt; row++) {
				rowFirst = row * daysPerRow;
				rowLast = rowFirst + daysPerRow - 1;

				// intersect segment's offset range with the row's
				segFirst = Math.max(rangeFirst, rowFirst);
				segLast = Math.min(rangeLast, rowLast);

				// deal with in-between indices
				segFirst = Math.ceil(segFirst); // in-between starts round to next cell
				segLast = Math.floor(segLast); // in-between ends round to prev cell

				if (segFirst <= segLast) { // was there any intersection with the current row?
					segs.push({
						row: row,

						// normalize to start of row
						firstRowDayIndex: segFirst - rowFirst,
						lastRowDayIndex: segLast - rowFirst,

						// must be matching integers to be the segment's start/end
						isStart: segFirst === rangeFirst,
						isEnd: segLast === rangeLast
					});
				}
			}

			return segs;
		},


		// Slices up a date range into a segment for every day-cell it intersects with.
		// TODO: make more DRY with sliceRangeByRow somehow.
		sliceRangeByDay: function(range) {
			var daysPerRow = this.daysPerRow;
			var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold
			var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index
			var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index
			var segs = [];
			var row;
			var rowFirst, rowLast; // inclusive day-index range for current row
			var i;
			var segFirst, segLast; // inclusive day-index range for segment

			for (row = 0; row < this.rowCnt; row++) {
				rowFirst = row * daysPerRow;
				rowLast = rowFirst + daysPerRow - 1;

				for (i = rowFirst; i <= rowLast; i++) {

					// intersect segment's offset range with the row's
					segFirst = Math.max(rangeFirst, i);
					segLast = Math.min(rangeLast, i);

					// deal with in-between indices
					segFirst = Math.ceil(segFirst); // in-between starts round to next cell
					segLast = Math.floor(segLast); // in-between ends round to prev cell

					if (segFirst <= segLast) { // was there any intersection with the current row?
						segs.push({
							row: row,

							// normalize to start of row
							firstRowDayIndex: segFirst - rowFirst,
							lastRowDayIndex: segLast - rowFirst,

							// must be matching integers to be the segment's start/end
							isStart: segFirst === rangeFirst,
							isEnd: segLast === rangeLast
						});
					}
				}
			}

			return segs;
		},


		/* Header Rendering
		------------------------------------------------------------------------------------------------------------------*/


		renderHeadHtml: function() {
			var view = this.view;

			return '' +
				'<div class="fc-row ' + view.widgetHeaderClass + '">' +
					'<table>' +
						'<thead>' +
							this.renderHeadTrHtml() +
						'</thead>' +
					'</table>' +
				'</div>';
		},


		renderHeadIntroHtml: function() {
			return this.renderIntroHtml(); // fall back to generic
		},


		renderHeadTrHtml: function() {
			return '' +
				'<tr>' +
					(this.isRTL ? '' : this.renderHeadIntroHtml()) +
					this.renderHeadDateCellsHtml() +
					(this.isRTL ? this.renderHeadIntroHtml() : '') +
				'</tr>';
		},


		renderHeadDateCellsHtml: function() {
			var htmls = [];
			var col, date;

			for (col = 0; col < this.colCnt; col++) {
				date = this.getCellDate(0, col);
				htmls.push(this.renderHeadDateCellHtml(date));
			}

			return htmls.join('');
		},


		// TODO: when internalApiVersion, accept an object for HTML attributes
		// (colspan should be no different)
		renderHeadDateCellHtml: function(date, colspan, otherAttrs) {
			var view = this.view;

			return '' +
				'<th class="fc-day-header ' + view.widgetHeaderClass + ' fc-' + dayIDs[date.day()] + '"' +
					(this.rowCnt == 1 ?
						' data-date="' + date.format('YYYY-MM-DD') + '"' :
						'') +
					(colspan > 1 ?
						' colspan="' + colspan + '"' :
						'') +
					(otherAttrs ?
						' ' + otherAttrs :
						'') +
				'>' +
					htmlEscape(date.format(this.colHeadFormat)) +
				'</th>';
		},


		/* Background Rendering
		------------------------------------------------------------------------------------------------------------------*/


		renderBgTrHtml: function(row) {
			return '' +
				'<tr>' +
					(this.isRTL ? '' : this.renderBgIntroHtml(row)) +
					this.renderBgCellsHtml(row) +
					(this.isRTL ? this.renderBgIntroHtml(row) : '') +
				'</tr>';
		},


		renderBgIntroHtml: function(row) {
			return this.renderIntroHtml(); // fall back to generic
		},


		renderBgCellsHtml: function(row) {
			var htmls = [];
			var col, date;

			for (col = 0; col < this.colCnt; col++) {
				date = this.getCellDate(row, col);
				htmls.push(this.renderBgCellHtml(date));
			}

			return htmls.join('');
		},


		renderBgCellHtml: function(date, otherAttrs) {
			var view = this.view;
			var classes = this.getDayClasses(date);

			classes.unshift('fc-day', view.widgetContentClass);

			return '<td class="' + classes.join(' ') + '"' +
				' data-date="' + date.format('YYYY-MM-DD') + '"' + // if date has a time, won't format it
				(otherAttrs ?
					' ' + otherAttrs :
					'') +
				'></td>';
		},


		/* Generic
		------------------------------------------------------------------------------------------------------------------*/


		// Generates the default HTML intro for any row. User classes should override
		renderIntroHtml: function() {
		},


		// TODO: a generic method for dealing with <tr>, RTL, intro
		// when increment internalApiVersion
		// wrapTr (scheduler)


		/* Utils
		------------------------------------------------------------------------------------------------------------------*/


		// Applies the generic "intro" and "outro" HTML to the given cells.
		// Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro.
		bookendCells: function(trEl) {
			var introHtml = this.renderIntroHtml();

			if (introHtml) {
				if (this.isRTL) {
					trEl.append(introHtml);
				}
				else {
					trEl.prepend(introHtml);
				}
			}
		}

	};

	;;

	/* A component that renders a grid of whole-days that runs horizontally. There can be multiple rows, one per week.
	----------------------------------------------------------------------------------------------------------------------*/

	var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {

		numbersVisible: false, // should render a row for day/week numbers? set by outside view. TODO: make internal
		bottomCoordPadding: 0, // hack for extending the hit area for the last row of the coordinate grid

		rowEls: null, // set of fake row elements
		cellEls: null, // set of whole-day elements comprising the row's background
		helperEls: null, // set of cell skeleton elements for rendering the mock event "helper"

		rowCoordCache: null,
		colCoordCache: null,


		// Renders the rows and columns into the component's `this.el`, which should already be assigned.
		// isRigid determins whether the individual rows should ignore the contents and be a constant height.
		// Relies on the view's colCnt and rowCnt. In the future, this component should probably be self-sufficient.
		renderDates: function(isRigid) {
			var view = this.view;
			var rowCnt = this.rowCnt;
			var colCnt = this.colCnt;
			var html = '';
			var row;
			var col;

			for (row = 0; row < rowCnt; row++) {
				html += this.renderDayRowHtml(row, isRigid);
			}
			this.el.html(html);

			this.rowEls = this.el.find('.fc-row');
			this.cellEls = this.el.find('.fc-day');

			this.rowCoordCache = new CoordCache({
				els: this.rowEls,
				isVertical: true
			});
			this.colCoordCache = new CoordCache({
				els: this.cellEls.slice(0, this.colCnt), // only the first row
				isHorizontal: true
			});

			// trigger dayRender with each cell's element
			for (row = 0; row < rowCnt; row++) {
				for (col = 0; col < colCnt; col++) {
					view.trigger(
						'dayRender',
						null,
						this.getCellDate(row, col),
						this.getCellEl(row, col)
					);
				}
			}
		},


		unrenderDates: function() {
			this.removeSegPopover();
		},


		renderBusinessHours: function() {
			var segs = this.buildBusinessHourSegs(true); // wholeDay=true
			this.renderFill('businessHours', segs, 'bgevent');
		},


		unrenderBusinessHours: function() {
			this.unrenderFill('businessHours');
		},


		// Generates the HTML for a single row, which is a div that wraps a table.
		// `row` is the row number.
		renderDayRowHtml: function(row, isRigid) {
			var view = this.view;
			var classes = [ 'fc-row', 'fc-week', view.widgetContentClass ];

			if (isRigid) {
				classes.push('fc-rigid');
			}

			return '' +
				'<div class="' + classes.join(' ') + '">' +
					'<div class="fc-bg">' +
						'<table>' +
							this.renderBgTrHtml(row) +
						'</table>' +
					'</div>' +
					'<div class="fc-content-skeleton">' +
						'<table>' +
							(this.numbersVisible ?
								'<thead>' +
									this.renderNumberTrHtml(row) +
								'</thead>' :
								''
								) +
						'</table>' +
					'</div>' +
				'</div>';
		},


		/* Grid Number Rendering
		------------------------------------------------------------------------------------------------------------------*/


		renderNumberTrHtml: function(row) {
			return '' +
				'<tr>' +
					(this.isRTL ? '' : this.renderNumberIntroHtml(row)) +
					this.renderNumberCellsHtml(row) +
					(this.isRTL ? this.renderNumberIntroHtml(row) : '') +
				'</tr>';
		},


		renderNumberIntroHtml: function(row) {
			return this.renderIntroHtml();
		},


		renderNumberCellsHtml: function(row) {
			var htmls = [];
			var col, date;

			for (col = 0; col < this.colCnt; col++) {
				date = this.getCellDate(row, col);
				htmls.push(this.renderNumberCellHtml(date));
			}

			return htmls.join('');
		},


		// Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton.
		// The number row will only exist if either day numbers or week numbers are turned on.
		renderNumberCellHtml: function(date) {
			var classes;
			var weekCalcFirstDoW;

			if (!this.view.dayNumbersVisible && !this.view.cellWeekNumbersVisible) {
				// no numbers in day cell (week number must be along the side)
				return '<td/>'; //  will create an empty space above events :(
			}

			classes = this.getDayClasses(date);
			classes.unshift('fc-day-top');

			if (this.view.cellWeekNumbersVisible) {
				// To determine the day of week number change under ISO, we cannot
				// rely on moment.js methods such as firstDayOfWeek() or weekday(),
				// because they rely on the locale's dow (possibly overridden by
				// our firstDay option), which may not be Monday. We cannot change
				// dow, because that would affect the calendar start day as well.
				if ((date._locale || date._lang)._fullCalendar_weekCalc === 'ISO') {
					weekCalcFirstDoW = 1;  // Monday by ISO 8601 definition
				}
				else {
					weekCalcFirstDoW = (date._locale || date._lang).firstDayOfWeek();
				}
			}

			return '' +
				'<td class="' + classes.join(' ') + '" data-date="' + date.format() + '">' +
					((this.view.cellWeekNumbersVisible && (date.day() == weekCalcFirstDoW)) ?
						'<span class="fc-week-number">' +
							date.format('w') +
						'</span>' :
						''
						) +
					(this.view.dayNumbersVisible ?
						'<span class="fc-day-number">' +
							date.date() +
						'</span>' :
						''
						) +
				'</td>';
		},


		/* Options
		------------------------------------------------------------------------------------------------------------------*/


		// Computes a default event time formatting string if `timeFormat` is not explicitly defined
		computeEventTimeFormat: function() {
			return this.view.opt('extraSmallTimeFormat'); // like "6p" or "6:30p"
		},


		// Computes a default `displayEventEnd` value if one is not expliclty defined
		computeDisplayEventEnd: function() {
			return this.colCnt == 1; // we'll likely have space if there's only one day
		},


		/* Dates
		------------------------------------------------------------------------------------------------------------------*/


		rangeUpdated: function() {
			this.updateDayTable();
		},


		// Slices up the given span (unzoned start/end with other misc data) into an array of segments
		spanToSegs: function(span) {
			var segs = this.sliceRangeByRow(span);
			var i, seg;

			for (i = 0; i < segs.length; i++) {
				seg = segs[i];
				if (this.isRTL) {
					seg.leftCol = this.daysPerRow - 1 - seg.lastRowDayIndex;
					seg.rightCol = this.daysPerRow - 1 - seg.firstRowDayIndex;
				}
				else {
					seg.leftCol = seg.firstRowDayIndex;
					seg.rightCol = seg.lastRowDayIndex;
				}
			}

			return segs;
		},


		/* Hit System
		------------------------------------------------------------------------------------------------------------------*/


		prepareHits: function() {
			this.colCoordCache.build();
			this.rowCoordCache.build();
			this.rowCoordCache.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack
		},


		releaseHits: function() {
			this.colCoordCache.clear();
			this.rowCoordCache.clear();
		},


		queryHit: function(leftOffset, topOffset) {
			if (this.colCoordCache.isLeftInBounds(leftOffset) && this.rowCoordCache.isTopInBounds(topOffset)) {
				var col = this.colCoordCache.getHorizontalIndex(leftOffset);
				var row = this.rowCoordCache.getVerticalIndex(topOffset);

				if (row != null && col != null) {
					return this.getCellHit(row, col);
				}
			}
		},


		getHitSpan: function(hit) {
			return this.getCellRange(hit.row, hit.col);
		},


		getHitEl: function(hit) {
			return this.getCellEl(hit.row, hit.col);
		},


		/* Cell System
		------------------------------------------------------------------------------------------------------------------*/
		// FYI: the first column is the leftmost column, regardless of date


		getCellHit: function(row, col) {
			return {
				row: row,
				col: col,
				component: this, // needed unfortunately :(
				left: this.colCoordCache.getLeftOffset(col),
				right: this.colCoordCache.getRightOffset(col),
				top: this.rowCoordCache.getTopOffset(row),
				bottom: this.rowCoordCache.getBottomOffset(row)
			};
		},


		getCellEl: function(row, col) {
			return this.cellEls.eq(row * this.colCnt + col);
		},


		/* Event Drag Visualization
		------------------------------------------------------------------------------------------------------------------*/
		// TODO: move to DayGrid.event, similar to what we did with Grid's drag methods


		// Renders a visual indication of an event or external element being dragged.
		// `eventLocation` has zoned start and end (optional)
		renderDrag: function(eventLocation, seg) {

			// always render a highlight underneath
			this.renderHighlight(this.eventToSpan(eventLocation));

			// if a segment from the same calendar but another component is being dragged, render a helper event
			if (seg && seg.component !== this) {
				return this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements
			}
		},


		// Unrenders any visual indication of a hovering event
		unrenderDrag: function() {
			this.unrenderHighlight();
			this.unrenderHelper();
		},


		/* Event Resize Visualization
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of an event being resized
		renderEventResize: function(eventLocation, seg) {
			this.renderHighlight(this.eventToSpan(eventLocation));
			return this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements
		},


		// Unrenders a visual indication of an event being resized
		unrenderEventResize: function() {
			this.unrenderHighlight();
			this.unrenderHelper();
		},


		/* Event Helper
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a mock "helper" event. `sourceSeg` is the associated internal segment object. It can be null.
		renderHelper: function(event, sourceSeg) {
			var helperNodes = [];
			var segs = this.eventToSegs(event);
			var rowStructs;

			segs = this.renderFgSegEls(segs); // assigns each seg's el and returns a subset of segs that were rendered
			rowStructs = this.renderSegRows(segs);

			// inject each new event skeleton into each associated row
			this.rowEls.each(function(row, rowNode) {
				var rowEl = $(rowNode); // the .fc-row
				var skeletonEl = $('<div class="fc-helper-skeleton"><table/></div>'); // will be absolutely positioned
				var skeletonTop;

				// If there is an original segment, match the top position. Otherwise, put it at the row's top level
				if (sourceSeg && sourceSeg.row === row) {
					skeletonTop = sourceSeg.el.position().top;
				}
				else {
					skeletonTop = rowEl.find('.fc-content-skeleton tbody').position().top;
				}

				skeletonEl.css('top', skeletonTop)
					.find('table')
						.append(rowStructs[row].tbodyEl);

				rowEl.append(skeletonEl);
				helperNodes.push(skeletonEl[0]);
			});

			return ( // must return the elements rendered
				this.helperEls = $(helperNodes) // array -> jQuery set
			);
		},


		// Unrenders any visual indication of a mock helper event
		unrenderHelper: function() {
			if (this.helperEls) {
				this.helperEls.remove();
				this.helperEls = null;
			}
		},


		/* Fill System (highlight, background events, business hours)
		------------------------------------------------------------------------------------------------------------------*/


		fillSegTag: 'td', // override the default tag name


		// Renders a set of rectangles over the given segments of days.
		// Only returns segments that successfully rendered.
		renderFill: function(type, segs, className) {
			var nodes = [];
			var i, seg;
			var skeletonEl;

			segs = this.renderFillSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs

			for (i = 0; i < segs.length; i++) {
				seg = segs[i];
				skeletonEl = this.renderFillRow(type, seg, className);
				this.rowEls.eq(seg.row).append(skeletonEl);
				nodes.push(skeletonEl[0]);
			}

			this.elsByFill[type] = $(nodes);

			return segs;
		},


		// Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.
		renderFillRow: function(type, seg, className) {
			var colCnt = this.colCnt;
			var startCol = seg.leftCol;
			var endCol = seg.rightCol + 1;
			var skeletonEl;
			var trEl;

			className = className || type.toLowerCase();

			skeletonEl = $(
				'<div class="fc-' + className + '-skeleton">' +
					'<table><tr/></table>' +
				'</div>'
			);
			trEl = skeletonEl.find('tr');

			if (startCol > 0) {
				trEl.append('<td colspan="' + startCol + '"/>');
			}

			trEl.append(
				seg.el.attr('colspan', endCol - startCol)
			);

			if (endCol < colCnt) {
				trEl.append('<td colspan="' + (colCnt - endCol) + '"/>');
			}

			this.bookendCells(trEl);

			return skeletonEl;
		}

	});

	;;

	/* Event-rendering methods for the DayGrid class
	----------------------------------------------------------------------------------------------------------------------*/

	DayGrid.mixin({

		rowStructs: null, // an array of objects, each holding information about a row's foreground event-rendering


		// Unrenders all events currently rendered on the grid
		unrenderEvents: function() {
			this.removeSegPopover(); // removes the "more.." events popover
			Grid.prototype.unrenderEvents.apply(this, arguments); // calls the super-method
		},


		// Retrieves all rendered segment objects currently rendered on the grid
		getEventSegs: function() {
			return Grid.prototype.getEventSegs.call(this) // get the segments from the super-method
				.concat(this.popoverSegs || []); // append the segments from the "more..." popover
		},


		// Renders the given background event segments onto the grid
		renderBgSegs: function(segs) {

			// don't render timed background events
			var allDaySegs = $.grep(segs, function(seg) {
				return seg.event.allDay;
			});

			return Grid.prototype.renderBgSegs.call(this, allDaySegs); // call the super-method
		},


		// Renders the given foreground event segments onto the grid
		renderFgSegs: function(segs) {
			var rowStructs;

			// render an `.el` on each seg
			// returns a subset of the segs. segs that were actually rendered
			segs = this.renderFgSegEls(segs);

			rowStructs = this.rowStructs = this.renderSegRows(segs);

			// append to each row's content skeleton
			this.rowEls.each(function(i, rowNode) {
				$(rowNode).find('.fc-content-skeleton > table').append(
					rowStructs[i].tbodyEl
				);
			});

			return segs; // return only the segs that were actually rendered
		},


		// Unrenders all currently rendered foreground event segments
		unrenderFgSegs: function() {
			var rowStructs = this.rowStructs || [];
			var rowStruct;

			while ((rowStruct = rowStructs.pop())) {
				rowStruct.tbodyEl.remove();
			}

			this.rowStructs = null;
		},


		// Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton.
		// Returns an array of rowStruct objects (see the bottom of `renderSegRow`).
		// PRECONDITION: each segment shoud already have a rendered and assigned `.el`
		renderSegRows: function(segs) {
			var rowStructs = [];
			var segRows;
			var row;

			segRows = this.groupSegRows(segs); // group into nested arrays

			// iterate each row of segment groupings
			for (row = 0; row < segRows.length; row++) {
				rowStructs.push(
					this.renderSegRow(row, segRows[row])
				);
			}

			return rowStructs;
		},


		// Builds the HTML to be used for the default element for an individual segment
		fgSegHtml: function(seg, disableResizing) {
			var view = this.view;
			var event = seg.event;
			var isDraggable = view.isEventDraggable(event);
			var isResizableFromStart = !disableResizing && event.allDay &&
				seg.isStart && view.isEventResizableFromStart(event);
			var isResizableFromEnd = !disableResizing && event.allDay &&
				seg.isEnd && view.isEventResizableFromEnd(event);
			var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);
			var skinCss = cssToStr(this.getSegSkinCss(seg));
			var timeHtml = '';
			var timeText;
			var titleHtml;

			classes.unshift('fc-day-grid-event', 'fc-h-event');

			// Only display a timed events time if it is the starting segment
			if (seg.isStart) {
				timeText = this.getEventTimeText(event);
				if (timeText) {
					timeHtml = '<span class="fc-time">' + htmlEscape(timeText) + '</span>';
				}
			}

			titleHtml =
				'<span class="fc-title">' +
					(htmlEscape(event.title || '') || '&nbsp;') + // we always want one line of height
				'</span>';
			
			return '<a class="' + classes.join(' ') + '"' +
					(event.url ?
						' href="' + htmlEscape(event.url) + '"' :
						''
						) +
					(skinCss ?
						' style="' + skinCss + '"' :
						''
						) +
				'>' +
					'<div class="fc-content">' +
						(this.isRTL ?
							titleHtml + ' ' + timeHtml : // put a natural space in between
							timeHtml + ' ' + titleHtml   //
							) +
					'</div>' +
					(isResizableFromStart ?
						'<div class="fc-resizer fc-start-resizer" />' :
						''
						) +
					(isResizableFromEnd ?
						'<div class="fc-resizer fc-end-resizer" />' :
						''
						) +
				'</a>';
		},


		// Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains
		// the segments. Returns object with a bunch of internal data about how the render was calculated.
		// NOTE: modifies rowSegs
		renderSegRow: function(row, rowSegs) {
			var colCnt = this.colCnt;
			var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels
			var levelCnt = Math.max(1, segLevels.length); // ensure at least one level
			var tbody = $('<tbody/>');
			var segMatrix = []; // lookup for which segments are rendered into which level+col cells
			var cellMatrix = []; // lookup for all <td> elements of the level+col matrix
			var loneCellMatrix = []; // lookup for <td> elements that only take up a single column
			var i, levelSegs;
			var col;
			var tr;
			var j, seg;
			var td;

			// populates empty cells from the current column (`col`) to `endCol`
			function emptyCellsUntil(endCol) {
				while (col < endCol) {
					// try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell
					td = (loneCellMatrix[i - 1] || [])[col];
					if (td) {
						td.attr(
							'rowspan',
							parseInt(td.attr('rowspan') || 1, 10) + 1
						);
					}
					else {
						td = $('<td/>');
						tr.append(td);
					}
					cellMatrix[i][col] = td;
					loneCellMatrix[i][col] = td;
					col++;
				}
			}

			for (i = 0; i < levelCnt; i++) { // iterate through all levels
				levelSegs = segLevels[i];
				col = 0;
				tr = $('<tr/>');

				segMatrix.push([]);
				cellMatrix.push([]);
				loneCellMatrix.push([]);

				// levelCnt might be 1 even though there are no actual levels. protect against this.
				// this single empty row is useful for styling.
				if (levelSegs) {
					for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level
						seg = levelSegs[j];

						emptyCellsUntil(seg.leftCol);

						// create a container that occupies or more columns. append the event element.
						td = $('<td class="fc-event-container"/>').append(seg.el);
						if (seg.leftCol != seg.rightCol) {
							td.attr('colspan', seg.rightCol - seg.leftCol + 1);
						}
						else { // a single-column segment
							loneCellMatrix[i][col] = td;
						}

						while (col <= seg.rightCol) {
							cellMatrix[i][col] = td;
							segMatrix[i][col] = seg;
							col++;
						}

						tr.append(td);
					}
				}

				emptyCellsUntil(colCnt); // finish off the row
				this.bookendCells(tr);
				tbody.append(tr);
			}

			return { // a "rowStruct"
				row: row, // the row number
				tbodyEl: tbody,
				cellMatrix: cellMatrix,
				segMatrix: segMatrix,
				segLevels: segLevels,
				segs: rowSegs
			};
		},


		// Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels.
		// NOTE: modifies segs
		buildSegLevels: function(segs) {
			var levels = [];
			var i, seg;
			var j;

			// Give preference to elements with certain criteria, so they have
			// a chance to be closer to the top.
			this.sortEventSegs(segs);
			
			for (i = 0; i < segs.length; i++) {
				seg = segs[i];

				// loop through levels, starting with the topmost, until the segment doesn't collide with other segments
				for (j = 0; j < levels.length; j++) {
					if (!isDaySegCollision(seg, levels[j])) {
						break;
					}
				}
				// `j` now holds the desired subrow index
				seg.level = j;

				// create new level array if needed and append segment
				(levels[j] || (levels[j] = [])).push(seg);
			}

			// order segments left-to-right. very important if calendar is RTL
			for (j = 0; j < levels.length; j++) {
				levels[j].sort(compareDaySegCols);
			}

			return levels;
		},


		// Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row
		groupSegRows: function(segs) {
			var segRows = [];
			var i;

			for (i = 0; i < this.rowCnt; i++) {
				segRows.push([]);
			}

			for (i = 0; i < segs.length; i++) {
				segRows[segs[i].row].push(segs[i]);
			}

			return segRows;
		}

	});


	// Computes whether two segments' columns collide. They are assumed to be in the same row.
	function isDaySegCollision(seg, otherSegs) {
		var i, otherSeg;

		for (i = 0; i < otherSegs.length; i++) {
			otherSeg = otherSegs[i];

			if (
				otherSeg.leftCol <= seg.rightCol &&
				otherSeg.rightCol >= seg.leftCol
			) {
				return true;
			}
		}

		return false;
	}


	// A cmp function for determining the leftmost event
	function compareDaySegCols(a, b) {
		return a.leftCol - b.leftCol;
	}

	;;

	/* Methods relate to limiting the number events for a given day on a DayGrid
	----------------------------------------------------------------------------------------------------------------------*/
	// NOTE: all the segs being passed around in here are foreground segs

	DayGrid.mixin({

		segPopover: null, // the Popover that holds events that can't fit in a cell. null when not visible
		popoverSegs: null, // an array of segment objects that the segPopover holds. null when not visible


		removeSegPopover: function() {
			if (this.segPopover) {
				this.segPopover.hide(); // in handler, will call segPopover's removeElement
			}
		},


		// Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
		// `levelLimit` can be false (don't limit), a number, or true (should be computed).
		limitRows: function(levelLimit) {
			var rowStructs = this.rowStructs || [];
			var row; // row #
			var rowLevelLimit;

			for (row = 0; row < rowStructs.length; row++) {
				this.unlimitRow(row);

				if (!levelLimit) {
					rowLevelLimit = false;
				}
				else if (typeof levelLimit === 'number') {
					rowLevelLimit = levelLimit;
				}
				else {
					rowLevelLimit = this.computeRowLevelLimit(row);
				}

				if (rowLevelLimit !== false) {
					this.limitRow(row, rowLevelLimit);
				}
			}
		},


		// Computes the number of levels a row will accomodate without going outside its bounds.
		// Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
		// `row` is the row number.
		computeRowLevelLimit: function(row) {
			var rowEl = this.rowEls.eq(row); // the containing "fake" row div
			var rowHeight = rowEl.height(); // TODO: cache somehow?
			var trEls = this.rowStructs[row].tbodyEl.children();
			var i, trEl;
			var trHeight;

			function iterInnerHeights(i, childNode) {
				trHeight = Math.max(trHeight, $(childNode).outerHeight());
			}

			// Reveal one level <tr> at a time and stop when we find one out of bounds
			for (i = 0; i < trEls.length; i++) {
				trEl = trEls.eq(i).removeClass('fc-limited'); // reset to original state (reveal)

				// with rowspans>1 and IE8, trEl.outerHeight() would return the height of the largest cell,
				// so instead, find the tallest inner content element.
				trHeight = 0;
				trEl.find('> td > :first-child').each(iterInnerHeights);

				if (trEl.position().top + trHeight > rowHeight) {
					return i;
				}
			}

			return false; // should not limit at all
		},


		// Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
		// `row` is the row number.
		// `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
		limitRow: function(row, levelLimit) {
			var _this = this;
			var rowStruct = this.rowStructs[row];
			var moreNodes = []; // array of "more" <a> links and <td> DOM nodes
			var col = 0; // col #, left-to-right (not chronologically)
			var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
			var cellMatrix; // a matrix (by level, then column) of all <td> jQuery elements in the row
			var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes
			var i, seg;
			var segsBelow; // array of segment objects below `seg` in the current `col`
			var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
			var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
			var td, rowspan;
			var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell
			var j;
			var moreTd, moreWrap, moreLink;

			// Iterates through empty level cells and places "more" links inside if need be
			function emptyCellsUntil(endCol) { // goes from current `col` to `endCol`
				while (col < endCol) {
					segsBelow = _this.getCellSegs(row, col, levelLimit);
					if (segsBelow.length) {
						td = cellMatrix[levelLimit - 1][col];
						moreLink = _this.renderMoreLink(row, col, segsBelow);
						moreWrap = $('<div/>').append(moreLink);
						td.append(moreWrap);
						moreNodes.push(moreWrap[0]);
					}
					col++;
				}
			}

			if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
				levelSegs = rowStruct.segLevels[levelLimit - 1];
				cellMatrix = rowStruct.cellMatrix;

				limitedNodes = rowStruct.tbodyEl.children().slice(levelLimit) // get level <tr> elements past the limit
					.addClass('fc-limited').get(); // hide elements and get a simple DOM-nodes array

				// iterate though segments in the last allowable level
				for (i = 0; i < levelSegs.length; i++) {
					seg = levelSegs[i];
					emptyCellsUntil(seg.leftCol); // process empty cells before the segment

					// determine *all* segments below `seg` that occupy the same columns
					colSegsBelow = [];
					totalSegsBelow = 0;
					while (col <= seg.rightCol) {
						segsBelow = this.getCellSegs(row, col, levelLimit);
						colSegsBelow.push(segsBelow);
						totalSegsBelow += segsBelow.length;
						col++;
					}

					if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
						td = cellMatrix[levelLimit - 1][seg.leftCol]; // the segment's parent cell
						rowspan = td.attr('rowspan') || 1;
						segMoreNodes = [];

						// make a replacement <td> for each column the segment occupies. will be one for each colspan
						for (j = 0; j < colSegsBelow.length; j++) {
							moreTd = $('<td class="fc-more-cell"/>').attr('rowspan', rowspan);
							segsBelow = colSegsBelow[j];
							moreLink = this.renderMoreLink(
								row,
								seg.leftCol + j,
								[ seg ].concat(segsBelow) // count seg as hidden too
							);
							moreWrap = $('<div/>').append(moreLink);
							moreTd.append(moreWrap);
							segMoreNodes.push(moreTd[0]);
							moreNodes.push(moreTd[0]);
						}

						td.addClass('fc-limited').after($(segMoreNodes)); // hide original <td> and inject replacements
						limitedNodes.push(td[0]);
					}
				}

				emptyCellsUntil(this.colCnt); // finish off the level
				rowStruct.moreEls = $(moreNodes); // for easy undoing later
				rowStruct.limitedEls = $(limitedNodes); // for easy undoing later
			}
		},


		// Reveals all levels and removes all "more"-related elements for a grid's row.
		// `row` is a row number.
		unlimitRow: function(row) {
			var rowStruct = this.rowStructs[row];

			if (rowStruct.moreEls) {
				rowStruct.moreEls.remove();
				rowStruct.moreEls = null;
			}

			if (rowStruct.limitedEls) {
				rowStruct.limitedEls.removeClass('fc-limited');
				rowStruct.limitedEls = null;
			}
		},


		// Renders an <a> element that represents hidden event element for a cell.
		// Responsible for attaching click handler as well.
		renderMoreLink: function(row, col, hiddenSegs) {
			var _this = this;
			var view = this.view;

			return $('<a class="fc-more"/>')
				.text(
					this.getMoreLinkText(hiddenSegs.length)
				)
				.on('click', function(ev) {
					var clickOption = view.opt('eventLimitClick');
					var date = _this.getCellDate(row, col);
					var moreEl = $(this);
					var dayEl = _this.getCellEl(row, col);
					var allSegs = _this.getCellSegs(row, col);

					// rescope the segments to be within the cell's date
					var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
					var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);

					if (typeof clickOption === 'function') {
						// the returned value can be an atomic option
						clickOption = view.trigger('eventLimitClick', null, {
							date: date,
							dayEl: dayEl,
							moreEl: moreEl,
							segs: reslicedAllSegs,
							hiddenSegs: reslicedHiddenSegs
						}, ev);
					}

					if (clickOption === 'popover') {
						_this.showSegPopover(row, col, moreEl, reslicedAllSegs);
					}
					else if (typeof clickOption === 'string') { // a view name
						view.calendar.zoomTo(date, clickOption);
					}
				});
		},


		// Reveals the popover that displays all events within a cell
		showSegPopover: function(row, col, moreLink, segs) {
			var _this = this;
			var view = this.view;
			var moreWrap = moreLink.parent(); // the <div> wrapper around the <a>
			var topEl; // the element we want to match the top coordinate of
			var options;

			if (this.rowCnt == 1) {
				topEl = view.el; // will cause the popover to cover any sort of header
			}
			else {
				topEl = this.rowEls.eq(row); // will align with top of row
			}

			options = {
				className: 'fc-more-popover',
				content: this.renderSegPopoverContent(row, col, segs),
				parentEl: this.view.el, // attach to root of view. guarantees outside of scrollbars.
				top: topEl.offset().top,
				autoHide: true, // when the user clicks elsewhere, hide the popover
				viewportConstrain: view.opt('popoverViewportConstrain'),
				hide: function() {
					// kill everything when the popover is hidden
					_this.segPopover.removeElement();
					_this.segPopover = null;
					_this.popoverSegs = null;
				}
			};

			// Determine horizontal coordinate.
			// We use the moreWrap instead of the <td> to avoid border confusion.
			if (this.isRTL) {
				options.right = moreWrap.offset().left + moreWrap.outerWidth() + 1; // +1 to be over cell border
			}
			else {
				options.left = moreWrap.offset().left - 1; // -1 to be over cell border
			}

			this.segPopover = new Popover(options);
			this.segPopover.show();

			// the popover doesn't live within the grid's container element, and thus won't get the event
			// delegated-handlers for free. attach event-related handlers to the popover.
			this.bindSegHandlersToEl(this.segPopover.el);
		},


		// Builds the inner DOM contents of the segment popover
		renderSegPopoverContent: function(row, col, segs) {
			var view = this.view;
			var isTheme = view.opt('theme');
			var title = this.getCellDate(row, col).format(view.opt('dayPopoverFormat'));
			var content = $(
				'<div class="fc-header ' + view.widgetHeaderClass + '">' +
					'<span class="fc-close ' +
						(isTheme ? 'ui-icon ui-icon-closethick' : 'fc-icon fc-icon-x') +
					'"></span>' +
					'<span class="fc-title">' +
						htmlEscape(title) +
					'</span>' +
					'<div class="fc-clear"/>' +
				'</div>' +
				'<div class="fc-body ' + view.widgetContentClass + '">' +
					'<div class="fc-event-container"></div>' +
				'</div>'
			);
			var segContainer = content.find('.fc-event-container');
			var i;

			// render each seg's `el` and only return the visible segs
			segs = this.renderFgSegEls(segs, true); // disableResizing=true
			this.popoverSegs = segs;

			for (i = 0; i < segs.length; i++) {

				// because segments in the popover are not part of a grid coordinate system, provide a hint to any
				// grids that want to do drag-n-drop about which cell it came from
				this.prepareHits();
				segs[i].hit = this.getCellHit(row, col);
				this.releaseHits();

				segContainer.append(segs[i].el);
			}

			return content;
		},


		// Given the events within an array of segment objects, reslice them to be in a single day
		resliceDaySegs: function(segs, dayDate) {

			// build an array of the original events
			var events = $.map(segs, function(seg) {
				return seg.event;
			});

			var dayStart = dayDate.clone();
			var dayEnd = dayStart.clone().add(1, 'days');
			var dayRange = { start: dayStart, end: dayEnd };

			// slice the events with a custom slicing function
			segs = this.eventsToSegs(
				events,
				function(range) {
					var seg = intersectRanges(range, dayRange); // undefind if no intersection
					return seg ? [ seg ] : []; // must return an array of segments
				}
			);

			// force an order because eventsToSegs doesn't guarantee one
			this.sortEventSegs(segs);

			return segs;
		},


		// Generates the text that should be inside a "more" link, given the number of events it represents
		getMoreLinkText: function(num) {
			var opt = this.view.opt('eventLimitText');

			if (typeof opt === 'function') {
				return opt(num);
			}
			else {
				return '+' + num + ' ' + opt;
			}
		},


		// Returns segments within a given cell.
		// If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
		getCellSegs: function(row, col, startLevel) {
			var segMatrix = this.rowStructs[row].segMatrix;
			var level = startLevel || 0;
			var segs = [];
			var seg;

			while (level < segMatrix.length) {
				seg = segMatrix[level][col];
				if (seg) {
					segs.push(seg);
				}
				level++;
			}

			return segs;
		}

	});

	;;

	/* A component that renders one or more columns of vertical time slots
	----------------------------------------------------------------------------------------------------------------------*/
	// We mixin DayTable, even though there is only a single row of days

	var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {

		slotDuration: null, // duration of a "slot", a distinct time segment on given day, visualized by lines
		snapDuration: null, // granularity of time for dragging and selecting
		snapsPerSlot: null,
		minTime: null, // Duration object that denotes the first visible time of any given day
		maxTime: null, // Duration object that denotes the exclusive visible end time of any given day
		labelFormat: null, // formatting string for times running along vertical axis
		labelInterval: null, // duration of how often a label should be displayed for a slot

		colEls: null, // cells elements in the day-row background
		slatContainerEl: null, // div that wraps all the slat rows
		slatEls: null, // elements running horizontally across all columns
		nowIndicatorEls: null,

		colCoordCache: null,
		slatCoordCache: null,


		constructor: function() {
			Grid.apply(this, arguments); // call the super-constructor

			this.processOptions();
		},


		// Renders the time grid into `this.el`, which should already be assigned.
		// Relies on the view's colCnt. In the future, this component should probably be self-sufficient.
		renderDates: function() {
			this.el.html(this.renderHtml());
			this.colEls = this.el.find('.fc-day');
			this.slatContainerEl = this.el.find('.fc-slats');
			this.slatEls = this.slatContainerEl.find('tr');

			this.colCoordCache = new CoordCache({
				els: this.colEls,
				isHorizontal: true
			});
			this.slatCoordCache = new CoordCache({
				els: this.slatEls,
				isVertical: true
			});

			this.renderContentSkeleton();
		},


		// Renders the basic HTML skeleton for the grid
		renderHtml: function() {
			return '' +
				'<div class="fc-bg">' +
					'<table>' +
						this.renderBgTrHtml(0) + // row=0
					'</table>' +
				'</div>' +
				'<div class="fc-slats">' +
					'<table>' +
						this.renderSlatRowHtml() +
					'</table>' +
				'</div>';
		},


		// Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
		renderSlatRowHtml: function() {
			var view = this.view;
			var isRTL = this.isRTL;
			var html = '';
			var slotTime = moment.duration(+this.minTime); // wish there was .clone() for durations
			var slotDate; // will be on the view's first day, but we only care about its time
			var isLabeled;
			var axisHtml;

			// Calculate the time for each slot
			while (slotTime < this.maxTime) {
				slotDate = this.start.clone().time(slotTime);
				isLabeled = isInt(divideDurationByDuration(slotTime, this.labelInterval));

				axisHtml =
					'<td class="fc-axis fc-time ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '>' +
						(isLabeled ?
							'<span>' + // for matchCellWidths
								htmlEscape(slotDate.format(this.labelFormat)) +
							'</span>' :
							''
							) +
					'</td>';

				html +=
					'<tr data-time="' + slotDate.format('HH:mm:ss') + '"' +
						(isLabeled ? '' : ' class="fc-minor"') +
						'>' +
						(!isRTL ? axisHtml : '') +
						'<td class="' + view.widgetContentClass + '"/>' +
						(isRTL ? axisHtml : '') +
					"</tr>";

				slotTime.add(this.slotDuration);
			}

			return html;
		},


		/* Options
		------------------------------------------------------------------------------------------------------------------*/


		// Parses various options into properties of this object
		processOptions: function() {
			var view = this.view;
			var slotDuration = view.opt('slotDuration');
			var snapDuration = view.opt('snapDuration');
			var input;

			slotDuration = moment.duration(slotDuration);
			snapDuration = snapDuration ? moment.duration(snapDuration) : slotDuration;

			this.slotDuration = slotDuration;
			this.snapDuration = snapDuration;
			this.snapsPerSlot = slotDuration / snapDuration; // TODO: ensure an integer multiple?

			this.minResizeDuration = snapDuration; // hack

			this.minTime = moment.duration(view.opt('minTime'));
			this.maxTime = moment.duration(view.opt('maxTime'));

			// might be an array value (for TimelineView).
			// if so, getting the most granular entry (the last one probably).
			input = view.opt('slotLabelFormat');
			if ($.isArray(input)) {
				input = input[input.length - 1];
			}

			this.labelFormat =
				input ||
				view.opt('axisFormat') || // deprecated
				view.opt('smallTimeFormat'); // the computed default

			input = view.opt('slotLabelInterval');
			this.labelInterval = input ?
				moment.duration(input) :
				this.computeLabelInterval(slotDuration);
		},


		// Computes an automatic value for slotLabelInterval
		computeLabelInterval: function(slotDuration) {
			var i;
			var labelInterval;
			var slotsPerLabel;

			// find the smallest stock label interval that results in more than one slots-per-label
			for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
				labelInterval = moment.duration(AGENDA_STOCK_SUB_DURATIONS[i]);
				slotsPerLabel = divideDurationByDuration(labelInterval, slotDuration);
				if (isInt(slotsPerLabel) && slotsPerLabel > 1) {
					return labelInterval;
				}
			}

			return moment.duration(slotDuration); // fall back. clone
		},


		// Computes a default event time formatting string if `timeFormat` is not explicitly defined
		computeEventTimeFormat: function() {
			return this.view.opt('noMeridiemTimeFormat'); // like "6:30" (no AM/PM)
		},


		// Computes a default `displayEventEnd` value if one is not expliclty defined
		computeDisplayEventEnd: function() {
			return true;
		},


		/* Hit System
		------------------------------------------------------------------------------------------------------------------*/


		prepareHits: function() {
			this.colCoordCache.build();
			this.slatCoordCache.build();
		},


		releaseHits: function() {
			this.colCoordCache.clear();
			// NOTE: don't clear slatCoordCache because we rely on it for computeTimeTop
		},


		queryHit: function(leftOffset, topOffset) {
			var snapsPerSlot = this.snapsPerSlot;
			var colCoordCache = this.colCoordCache;
			var slatCoordCache = this.slatCoordCache;

			if (colCoordCache.isLeftInBounds(leftOffset) && slatCoordCache.isTopInBounds(topOffset)) {
				var colIndex = colCoordCache.getHorizontalIndex(leftOffset);
				var slatIndex = slatCoordCache.getVerticalIndex(topOffset);

				if (colIndex != null && slatIndex != null) {
					var slatTop = slatCoordCache.getTopOffset(slatIndex);
					var slatHeight = slatCoordCache.getHeight(slatIndex);
					var partial = (topOffset - slatTop) / slatHeight; // floating point number between 0 and 1
					var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
					var snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
					var snapTop = slatTop + (localSnapIndex / snapsPerSlot) * slatHeight;
					var snapBottom = slatTop + ((localSnapIndex + 1) / snapsPerSlot) * slatHeight;

					return {
						col: colIndex,
						snap: snapIndex,
						component: this, // needed unfortunately :(
						left: colCoordCache.getLeftOffset(colIndex),
						right: colCoordCache.getRightOffset(colIndex),
						top: snapTop,
						bottom: snapBottom
					};
				}
			}
		},


		getHitSpan: function(hit) {
			var start = this.getCellDate(0, hit.col); // row=0
			var time = this.computeSnapTime(hit.snap); // pass in the snap-index
			var end;

			start.time(time);
			end = start.clone().add(this.snapDuration);

			return { start: start, end: end };
		},


		getHitEl: function(hit) {
			return this.colEls.eq(hit.col);
		},


		/* Dates
		------------------------------------------------------------------------------------------------------------------*/


		rangeUpdated: function() {
			this.updateDayTable();
		},


		// Given a row number of the grid, representing a "snap", returns a time (Duration) from its start-of-day
		computeSnapTime: function(snapIndex) {
			return moment.duration(this.minTime + this.snapDuration * snapIndex);
		},


		// Slices up the given span (unzoned start/end with other misc data) into an array of segments
		spanToSegs: function(span) {
			var segs = this.sliceRangeByTimes(span);
			var i;

			for (i = 0; i < segs.length; i++) {
				if (this.isRTL) {
					segs[i].col = this.daysPerRow - 1 - segs[i].dayIndex;
				}
				else {
					segs[i].col = segs[i].dayIndex;
				}
			}

			return segs;
		},


		sliceRangeByTimes: function(range) {
			var segs = [];
			var seg;
			var dayIndex;
			var dayDate;
			var dayRange;

			for (dayIndex = 0; dayIndex < this.daysPerRow; dayIndex++) {
				dayDate = this.dayDates[dayIndex].clone(); // TODO: better API for this?
				dayRange = {
					start: dayDate.clone().time(this.minTime),
					end: dayDate.clone().time(this.maxTime)
				};
				seg = intersectRanges(range, dayRange); // both will be ambig timezone
				if (seg) {
					seg.dayIndex = dayIndex;
					segs.push(seg);
				}
			}

			return segs;
		},


		/* Coordinates
		------------------------------------------------------------------------------------------------------------------*/


		updateSize: function(isResize) { // NOT a standard Grid method
			this.slatCoordCache.build();

			if (isResize) {
				this.updateSegVerticals(
					[].concat(this.fgSegs || [], this.bgSegs || [], this.businessSegs || [])
				);
			}
		},


		getTotalSlatHeight: function() {
			return this.slatContainerEl.outerHeight();
		},


		// Computes the top coordinate, relative to the bounds of the grid, of the given date.
		// A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
		computeDateTop: function(date, startOfDayDate) {
			return this.computeTimeTop(
				moment.duration(
					date - startOfDayDate.clone().stripTime()
				)
			);
		},


		// Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
		computeTimeTop: function(time) {
			var len = this.slatEls.length;
			var slatCoverage = (time - this.minTime) / this.slotDuration; // floating-point value of # of slots covered
			var slatIndex;
			var slatRemainder;

			// compute a floating-point number for how many slats should be progressed through.
			// from 0 to number of slats (inclusive)
			// constrained because minTime/maxTime might be customized.
			slatCoverage = Math.max(0, slatCoverage);
			slatCoverage = Math.min(len, slatCoverage);

			// an integer index of the furthest whole slat
			// from 0 to number slats (*exclusive*, so len-1)
			slatIndex = Math.floor(slatCoverage);
			slatIndex = Math.min(slatIndex, len - 1);

			// how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
			// could be 1.0 if slatCoverage is covering *all* the slots
			slatRemainder = slatCoverage - slatIndex;

			return this.slatCoordCache.getTopPosition(slatIndex) +
				this.slatCoordCache.getHeight(slatIndex) * slatRemainder;
		},



		/* Event Drag Visualization
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of an event being dragged over the specified date(s).
		// A returned value of `true` signals that a mock "helper" event has been rendered.
		renderDrag: function(eventLocation, seg) {

			if (seg) { // if there is event information for this drag, render a helper event

				// returns mock event elements
				// signal that a helper has been rendered
				return this.renderEventLocationHelper(eventLocation, seg);
			}
			else {
				// otherwise, just render a highlight
				this.renderHighlight(this.eventToSpan(eventLocation));
			}
		},


		// Unrenders any visual indication of an event being dragged
		unrenderDrag: function() {
			this.unrenderHelper();
			this.unrenderHighlight();
		},


		/* Event Resize Visualization
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of an event being resized
		renderEventResize: function(eventLocation, seg) {
			return this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements
		},


		// Unrenders any visual indication of an event being resized
		unrenderEventResize: function() {
			this.unrenderHelper();
		},


		/* Event Helper
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a mock "helper" event. `sourceSeg` is the original segment object and might be null (an external drag)
		renderHelper: function(event, sourceSeg) {
			return this.renderHelperSegs(this.eventToSegs(event), sourceSeg); // returns mock event elements
		},


		// Unrenders any mock helper event
		unrenderHelper: function() {
			this.unrenderHelperSegs();
		},


		/* Business Hours
		------------------------------------------------------------------------------------------------------------------*/


		renderBusinessHours: function() {
			this.renderBusinessSegs(
				this.buildBusinessHourSegs()
			);
		},


		unrenderBusinessHours: function() {
			this.unrenderBusinessSegs();
		},


		/* Now Indicator
		------------------------------------------------------------------------------------------------------------------*/


		getNowIndicatorUnit: function() {
			return 'minute'; // will refresh on the minute
		},


		renderNowIndicator: function(date) {
			// seg system might be overkill, but it handles scenario where line needs to be rendered
			//  more than once because of columns with the same date (resources columns for example)
			var segs = this.spanToSegs({ start: date, end: date });
			var top = this.computeDateTop(date, date);
			var nodes = [];
			var i;

			// render lines within the columns
			for (i = 0; i < segs.length; i++) {
				nodes.push($('<div class="fc-now-indicator fc-now-indicator-line"></div>')
					.css('top', top)
					.appendTo(this.colContainerEls.eq(segs[i].col))[0]);
			}

			// render an arrow over the axis
			if (segs.length > 0) { // is the current time in view?
				nodes.push($('<div class="fc-now-indicator fc-now-indicator-arrow"></div>')
					.css('top', top)
					.appendTo(this.el.find('.fc-content-skeleton'))[0]);
			}

			this.nowIndicatorEls = $(nodes);
		},


		unrenderNowIndicator: function() {
			if (this.nowIndicatorEls) {
				this.nowIndicatorEls.remove();
				this.nowIndicatorEls = null;
			}
		},


		/* Selection
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
		renderSelection: function(span) {
			if (this.view.opt('selectHelper')) { // this setting signals that a mock helper event should be rendered

				// normally acceps an eventLocation, span has a start/end, which is good enough
				this.renderEventLocationHelper(span);
			}
			else {
				this.renderHighlight(span);
			}
		},


		// Unrenders any visual indication of a selection
		unrenderSelection: function() {
			this.unrenderHelper();
			this.unrenderHighlight();
		},


		/* Highlight
		------------------------------------------------------------------------------------------------------------------*/


		renderHighlight: function(span) {
			this.renderHighlightSegs(this.spanToSegs(span));
		},


		unrenderHighlight: function() {
			this.unrenderHighlightSegs();
		}

	});

	;;

	/* Methods for rendering SEGMENTS, pieces of content that live on the view
	 ( this file is no longer just for events )
	----------------------------------------------------------------------------------------------------------------------*/

	TimeGrid.mixin({

		colContainerEls: null, // containers for each column

		// inner-containers for each column where different types of segs live
		fgContainerEls: null,
		bgContainerEls: null,
		helperContainerEls: null,
		highlightContainerEls: null,
		businessContainerEls: null,

		// arrays of different types of displayed segments
		fgSegs: null,
		bgSegs: null,
		helperSegs: null,
		highlightSegs: null,
		businessSegs: null,


		// Renders the DOM that the view's content will live in
		renderContentSkeleton: function() {
			var cellHtml = '';
			var i;
			var skeletonEl;

			for (i = 0; i < this.colCnt; i++) {
				cellHtml +=
					'<td>' +
						'<div class="fc-content-col">' +
							'<div class="fc-event-container fc-helper-container"></div>' +
							'<div class="fc-event-container"></div>' +
							'<div class="fc-highlight-container"></div>' +
							'<div class="fc-bgevent-container"></div>' +
							'<div class="fc-business-container"></div>' +
						'</div>' +
					'</td>';
			}

			skeletonEl = $(
				'<div class="fc-content-skeleton">' +
					'<table>' +
						'<tr>' + cellHtml + '</tr>' +
					'</table>' +
				'</div>'
			);

			this.colContainerEls = skeletonEl.find('.fc-content-col');
			this.helperContainerEls = skeletonEl.find('.fc-helper-container');
			this.fgContainerEls = skeletonEl.find('.fc-event-container:not(.fc-helper-container)');
			this.bgContainerEls = skeletonEl.find('.fc-bgevent-container');
			this.highlightContainerEls = skeletonEl.find('.fc-highlight-container');
			this.businessContainerEls = skeletonEl.find('.fc-business-container');

			this.bookendCells(skeletonEl.find('tr')); // TODO: do this on string level
			this.el.append(skeletonEl);
		},


		/* Foreground Events
		------------------------------------------------------------------------------------------------------------------*/


		renderFgSegs: function(segs) {
			segs = this.renderFgSegsIntoContainers(segs, this.fgContainerEls);
			this.fgSegs = segs;
			return segs; // needed for Grid::renderEvents
		},


		unrenderFgSegs: function() {
			this.unrenderNamedSegs('fgSegs');
		},


		/* Foreground Helper Events
		------------------------------------------------------------------------------------------------------------------*/


		renderHelperSegs: function(segs, sourceSeg) {
			var helperEls = [];
			var i, seg;
			var sourceEl;

			segs = this.renderFgSegsIntoContainers(segs, this.helperContainerEls);

			// Try to make the segment that is in the same row as sourceSeg look the same
			for (i = 0; i < segs.length; i++) {
				seg = segs[i];
				if (sourceSeg && sourceSeg.col === seg.col) {
					sourceEl = sourceSeg.el;
					seg.el.css({
						left: sourceEl.css('left'),
						right: sourceEl.css('right'),
						'margin-left': sourceEl.css('margin-left'),
						'margin-right': sourceEl.css('margin-right')
					});
				}
				helperEls.push(seg.el[0]);
			}

			this.helperSegs = segs;

			return $(helperEls); // must return rendered helpers
		},


		unrenderHelperSegs: function() {
			this.unrenderNamedSegs('helperSegs');
		},


		/* Background Events
		------------------------------------------------------------------------------------------------------------------*/


		renderBgSegs: function(segs) {
			segs = this.renderFillSegEls('bgEvent', segs); // TODO: old fill system
			this.updateSegVerticals(segs);
			this.attachSegsByCol(this.groupSegsByCol(segs), this.bgContainerEls);
			this.bgSegs = segs;
			return segs; // needed for Grid::renderEvents
		},


		unrenderBgSegs: function() {
			this.unrenderNamedSegs('bgSegs');
		},


		/* Highlight
		------------------------------------------------------------------------------------------------------------------*/


		renderHighlightSegs: function(segs) {
			segs = this.renderFillSegEls('highlight', segs); // TODO: old fill system
			this.updateSegVerticals(segs);
			this.attachSegsByCol(this.groupSegsByCol(segs), this.highlightContainerEls);
			this.highlightSegs = segs;
		},


		unrenderHighlightSegs: function() {
			this.unrenderNamedSegs('highlightSegs');
		},


		/* Business Hours
		------------------------------------------------------------------------------------------------------------------*/


		renderBusinessSegs: function(segs) {
			segs = this.renderFillSegEls('businessHours', segs); // TODO: old fill system
			this.updateSegVerticals(segs);
			this.attachSegsByCol(this.groupSegsByCol(segs), this.businessContainerEls);
			this.businessSegs = segs;
		},


		unrenderBusinessSegs: function() {
			this.unrenderNamedSegs('businessSegs');
		},


		/* Seg Rendering Utils
		------------------------------------------------------------------------------------------------------------------*/


		// Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col
		groupSegsByCol: function(segs) {
			var segsByCol = [];
			var i;

			for (i = 0; i < this.colCnt; i++) {
				segsByCol.push([]);
			}

			for (i = 0; i < segs.length; i++) {
				segsByCol[segs[i].col].push(segs[i]);
			}

			return segsByCol;
		},


		// Given segments grouped by column, insert the segments' elements into a parallel array of container
		// elements, each living within a column.
		attachSegsByCol: function(segsByCol, containerEls) {
			var col;
			var segs;
			var i;

			for (col = 0; col < this.colCnt; col++) { // iterate each column grouping
				segs = segsByCol[col];

				for (i = 0; i < segs.length; i++) {
					containerEls.eq(col).append(segs[i].el);
				}
			}
		},


		// Given the name of a property of `this` object, assumed to be an array of segments,
		// loops through each segment and removes from DOM. Will null-out the property afterwards.
		unrenderNamedSegs: function(propName) {
			var segs = this[propName];
			var i;

			if (segs) {
				for (i = 0; i < segs.length; i++) {
					segs[i].el.remove();
				}
				this[propName] = null;
			}
		},



		/* Foreground Event Rendering Utils
		------------------------------------------------------------------------------------------------------------------*/


		// Given an array of foreground segments, render a DOM element for each, computes position,
		// and attaches to the column inner-container elements.
		renderFgSegsIntoContainers: function(segs, containerEls) {
			var segsByCol;
			var col;

			segs = this.renderFgSegEls(segs); // will call fgSegHtml
			segsByCol = this.groupSegsByCol(segs);

			for (col = 0; col < this.colCnt; col++) {
				this.updateFgSegCoords(segsByCol[col]);
			}

			this.attachSegsByCol(segsByCol, containerEls);

			return segs;
		},


		// Renders the HTML for a single event segment's default rendering
		fgSegHtml: function(seg, disableResizing) {
			var view = this.view;
			var event = seg.event;
			var isDraggable = view.isEventDraggable(event);
			var isResizableFromStart = !disableResizing && seg.isStart && view.isEventResizableFromStart(event);
			var isResizableFromEnd = !disableResizing && seg.isEnd && view.isEventResizableFromEnd(event);
			var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);
			var skinCss = cssToStr(this.getSegSkinCss(seg));
			var timeText;
			var fullTimeText; // more verbose time text. for the print stylesheet
			var startTimeText; // just the start time text

			classes.unshift('fc-time-grid-event', 'fc-v-event');

			if (view.isMultiDayEvent(event)) { // if the event appears to span more than one day...
				// Don't display time text on segments that run entirely through a day.
				// That would appear as midnight-midnight and would look dumb.
				// Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am)
				if (seg.isStart || seg.isEnd) {
					timeText = this.getEventTimeText(seg);
					fullTimeText = this.getEventTimeText(seg, 'LT');
					startTimeText = this.getEventTimeText(seg, null, false); // displayEnd=false
				}
			} else {
				// Display the normal time text for the *event's* times
				timeText = this.getEventTimeText(event);
				fullTimeText = this.getEventTimeText(event, 'LT');
				startTimeText = this.getEventTimeText(event, null, false); // displayEnd=false
			}

			return '<a class="' + classes.join(' ') + '"' +
				(event.url ?
					' href="' + htmlEscape(event.url) + '"' :
					''
					) +
				(skinCss ?
					' style="' + skinCss + '"' :
					''
					) +
				'>' +
					'<div class="fc-content">' +
						(timeText ?
							'<div class="fc-time"' +
							' data-start="' + htmlEscape(startTimeText) + '"' +
							' data-full="' + htmlEscape(fullTimeText) + '"' +
							'>' +
								'<span>' + htmlEscape(timeText) + '</span>' +
							'</div>' :
							''
							) +
						(event.title ?
							'<div class="fc-title">' +
								htmlEscape(event.title) +
							'</div>' :
							''
							) +
					'</div>' +
					'<div class="fc-bg"/>' +
					/* TODO: write CSS for this
					(isResizableFromStart ?
						'<div class="fc-resizer fc-start-resizer" />' :
						''
						) +
					*/
					(isResizableFromEnd ?
						'<div class="fc-resizer fc-end-resizer" />' :
						''
						) +
				'</a>';
		},


		/* Seg Position Utils
		------------------------------------------------------------------------------------------------------------------*/


		// Refreshes the CSS top/bottom coordinates for each segment element.
		// Works when called after initial render, after a window resize/zoom for example.
		updateSegVerticals: function(segs) {
			this.computeSegVerticals(segs);
			this.assignSegVerticals(segs);
		},


		// For each segment in an array, computes and assigns its top and bottom properties
		computeSegVerticals: function(segs) {
			var i, seg;

			for (i = 0; i < segs.length; i++) {
				seg = segs[i];
				seg.top = this.computeDateTop(seg.start, seg.start);
				seg.bottom = this.computeDateTop(seg.end, seg.start);
			}
		},


		// Given segments that already have their top/bottom properties computed, applies those values to
		// the segments' elements.
		assignSegVerticals: function(segs) {
			var i, seg;

			for (i = 0; i < segs.length; i++) {
				seg = segs[i];
				seg.el.css(this.generateSegVerticalCss(seg));
			}
		},


		// Generates an object with CSS properties for the top/bottom coordinates of a segment element
		generateSegVerticalCss: function(seg) {
			return {
				top: seg.top,
				bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container
			};
		},


		/* Foreground Event Positioning Utils
		------------------------------------------------------------------------------------------------------------------*/


		// Given segments that are assumed to all live in the *same column*,
		// compute their verical/horizontal coordinates and assign to their elements.
		updateFgSegCoords: function(segs) {
			this.computeSegVerticals(segs); // horizontals relies on this
			this.computeFgSegHorizontals(segs); // compute horizontal coordinates, z-index's, and reorder the array
			this.assignSegVerticals(segs);
			this.assignFgSegHorizontals(segs);
		},


		// Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
		// NOTE: Also reorders the given array by date!
		computeFgSegHorizontals: function(segs) {
			var levels;
			var level0;
			var i;

			this.sortEventSegs(segs); // order by certain criteria
			levels = buildSlotSegLevels(segs);
			computeForwardSlotSegs(levels);

			if ((level0 = levels[0])) {

				for (i = 0; i < level0.length; i++) {
					computeSlotSegPressures(level0[i]);
				}

				for (i = 0; i < level0.length; i++) {
					this.computeFgSegForwardBack(level0[i], 0, 0);
				}
			}
		},


		// Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
		// from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
		// seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
		//
		// The segment might be part of a "series", which means consecutive segments with the same pressure
		// who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
		// segments behind this one in the current series, and `seriesBackwardCoord` is the starting
		// coordinate of the first segment in the series.
		computeFgSegForwardBack: function(seg, seriesBackwardPressure, seriesBackwardCoord) {
			var forwardSegs = seg.forwardSegs;
			var i;

			if (seg.forwardCoord === undefined) { // not already computed

				if (!forwardSegs.length) {

					// if there are no forward segments, this segment should butt up against the edge
					seg.forwardCoord = 1;
				}
				else {

					// sort highest pressure first
					this.sortForwardSegs(forwardSegs);

					// this segment's forwardCoord will be calculated from the backwardCoord of the
					// highest-pressure forward segment.
					this.computeFgSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
					seg.forwardCoord = forwardSegs[0].backwardCoord;
				}

				// calculate the backwardCoord from the forwardCoord. consider the series
				seg.backwardCoord = seg.forwardCoord -
					(seg.forwardCoord - seriesBackwardCoord) / // available width for series
					(seriesBackwardPressure + 1); // # of segments in the series

				// use this segment's coordinates to computed the coordinates of the less-pressurized
				// forward segments
				for (i=0; i<forwardSegs.length; i++) {
					this.computeFgSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
				}
			}
		},


		sortForwardSegs: function(forwardSegs) {
			forwardSegs.sort(proxy(this, 'compareForwardSegs'));
		},


		// A cmp function for determining which forward segment to rely on more when computing coordinates.
		compareForwardSegs: function(seg1, seg2) {
			// put higher-pressure first
			return seg2.forwardPressure - seg1.forwardPressure ||
				// put segments that are closer to initial edge first (and favor ones with no coords yet)
				(seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
				// do normal sorting...
				this.compareEventSegs(seg1, seg2);
		},


		// Given foreground event segments that have already had their position coordinates computed,
		// assigns position-related CSS values to their elements.
		assignFgSegHorizontals: function(segs) {
			var i, seg;

			for (i = 0; i < segs.length; i++) {
				seg = segs[i];
				seg.el.css(this.generateFgSegHorizontalCss(seg));

				// if the height is short, add a className for alternate styling
				if (seg.bottom - seg.top < 30) {
					seg.el.addClass('fc-short');
				}
			}
		},


		// Generates an object with CSS properties/values that should be applied to an event segment element.
		// Contains important positioning-related properties that should be applied to any event element, customized or not.
		generateFgSegHorizontalCss: function(seg) {
			var shouldOverlap = this.view.opt('slotEventOverlap');
			var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
			var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
			var props = this.generateSegVerticalCss(seg); // get top/bottom first
			var left; // amount of space from left edge, a fraction of the total width
			var right; // amount of space from right edge, a fraction of the total width

			if (shouldOverlap) {
				// double the width, but don't go beyond the maximum forward coordinate (1.0)
				forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
			}

			if (this.isRTL) {
				left = 1 - forwardCoord;
				right = backwardCoord;
			}
			else {
				left = backwardCoord;
				right = 1 - forwardCoord;
			}

			props.zIndex = seg.level + 1; // convert from 0-base to 1-based
			props.left = left * 100 + '%';
			props.right = right * 100 + '%';

			if (shouldOverlap && seg.forwardPressure) {
				// add padding to the edge so that forward stacked events don't cover the resizer's icon
				props[this.isRTL ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
			}

			return props;
		}

	});


	// Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is
	// left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date.
	function buildSlotSegLevels(segs) {
		var levels = [];
		var i, seg;
		var j;

		for (i=0; i<segs.length; i++) {
			seg = segs[i];

			// go through all the levels and stop on the first level where there are no collisions
			for (j=0; j<levels.length; j++) {
				if (!computeSlotSegCollisions(seg, levels[j]).length) {
					break;
				}
			}

			seg.level = j;

			(levels[j] || (levels[j] = [])).push(seg);
		}

		return levels;
	}


	// For every segment, figure out the other segments that are in subsequent
	// levels that also occupy the same vertical space. Accumulate in seg.forwardSegs
	function computeForwardSlotSegs(levels) {
		var i, level;
		var j, seg;
		var k;

		for (i=0; i<levels.length; i++) {
			level = levels[i];

			for (j=0; j<level.length; j++) {
				seg = level[j];

				seg.forwardSegs = [];
				for (k=i+1; k<levels.length; k++) {
					computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
				}
			}
		}
	}


	// Figure out which path forward (via seg.forwardSegs) results in the longest path until
	// the furthest edge is reached. The number of segments in this path will be seg.forwardPressure
	function computeSlotSegPressures(seg) {
		var forwardSegs = seg.forwardSegs;
		var forwardPressure = 0;
		var i, forwardSeg;

		if (seg.forwardPressure === undefined) { // not already computed

			for (i=0; i<forwardSegs.length; i++) {
				forwardSeg = forwardSegs[i];

				// figure out the child's maximum forward path
				computeSlotSegPressures(forwardSeg);

				// either use the existing maximum, or use the child's forward pressure
				// plus one (for the forwardSeg itself)
				forwardPressure = Math.max(
					forwardPressure,
					1 + forwardSeg.forwardPressure
				);
			}

			seg.forwardPressure = forwardPressure;
		}
	}


	// Find all the segments in `otherSegs` that vertically collide with `seg`.
	// Append into an optionally-supplied `results` array and return.
	function computeSlotSegCollisions(seg, otherSegs, results) {
		results = results || [];

		for (var i=0; i<otherSegs.length; i++) {
			if (isSlotSegCollision(seg, otherSegs[i])) {
				results.push(otherSegs[i]);
			}
		}

		return results;
	}


	// Do these segments occupy the same vertical space?
	function isSlotSegCollision(seg1, seg2) {
		return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
	}

	;;

	/* An abstract class from which other views inherit from
	----------------------------------------------------------------------------------------------------------------------*/

	var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {

		type: null, // subclass' view name (string)
		name: null, // deprecated. use `type` instead
		title: null, // the text that will be displayed in the header's title

		calendar: null, // owner Calendar object
		options: null, // hash containing all options. already merged with view-specific-options
		el: null, // the view's containing element. set by Calendar

		displaying: null, // a promise representing the state of rendering. null if no render requested
		isSkeletonRendered: false,
		isEventsRendered: false,

		// range the view is actually displaying (moments)
		start: null,
		end: null, // exclusive

		// range the view is formally responsible for (moments)
		// may be different from start/end. for example, a month view might have 1st-31st, excluding padded dates
		intervalStart: null,
		intervalEnd: null, // exclusive
		intervalDuration: null,
		intervalUnit: null, // name of largest unit being displayed, like "month" or "week"

		isRTL: false,
		isSelected: false, // boolean whether a range of time is user-selected or not
		selectedEvent: null,

		eventOrderSpecs: null, // criteria for ordering events when they have same date/time

		// classNames styled by jqui themes
		widgetHeaderClass: null,
		widgetContentClass: null,
		highlightStateClass: null,

		// for date utils, computed from options
		nextDayThreshold: null,
		isHiddenDayHash: null,

		// now indicator
		isNowIndicatorRendered: null,
		initialNowDate: null, // result first getNow call
		initialNowQueriedMs: null, // ms time the getNow was called
		nowIndicatorTimeoutID: null, // for refresh timing of now indicator
		nowIndicatorIntervalID: null, // "


		constructor: function(calendar, type, options, intervalDuration) {

			this.calendar = calendar;
			this.type = this.name = type; // .name is deprecated
			this.options = options;
			this.intervalDuration = intervalDuration || moment.duration(1, 'day');

			this.nextDayThreshold = moment.duration(this.opt('nextDayThreshold'));
			this.initThemingProps();
			this.initHiddenDays();
			this.isRTL = this.opt('isRTL');

			this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));

			this.initialize();
		},


		// A good place for subclasses to initialize member variables
		initialize: function() {
			// subclasses can implement
		},


		// Retrieves an option with the given name
		opt: function(name) {
			return this.options[name];
		},


		// Triggers handlers that are view-related. Modifies args before passing to calendar.
		trigger: function(name, thisObj) { // arguments beyond thisObj are passed along
			var calendar = this.calendar;

			return calendar.trigger.apply(
				calendar,
				[name, thisObj || this].concat(
					Array.prototype.slice.call(arguments, 2), // arguments beyond thisObj
					[ this ] // always make the last argument a reference to the view. TODO: deprecate
				)
			);
		},


		/* Dates
		------------------------------------------------------------------------------------------------------------------*/


		// Updates all internal dates to center around the given current unzoned date.
		setDate: function(date) {
			this.setRange(this.computeRange(date));
		},


		// Updates all internal dates for displaying the given unzoned range.
		setRange: function(range) {
			$.extend(this, range); // assigns every property to this object's member variables
			this.updateTitle();
		},


		// Given a single current unzoned date, produce information about what range to display.
		// Subclasses can override. Must return all properties.
		computeRange: function(date) {
			var intervalUnit = computeIntervalUnit(this.intervalDuration);
			var intervalStart = date.clone().startOf(intervalUnit);
			var intervalEnd = intervalStart.clone().add(this.intervalDuration);
			var start, end;

			// normalize the range's time-ambiguity
			if (/year|month|week|day/.test(intervalUnit)) { // whole-days?
				intervalStart.stripTime();
				intervalEnd.stripTime();
			}
			else { // needs to have a time?
				if (!intervalStart.hasTime()) {
					intervalStart = this.calendar.time(0); // give 00:00 time
				}
				if (!intervalEnd.hasTime()) {
					intervalEnd = this.calendar.time(0); // give 00:00 time
				}
			}

			start = intervalStart.clone();
			start = this.skipHiddenDays(start);
			end = intervalEnd.clone();
			end = this.skipHiddenDays(end, -1, true); // exclusively move backwards

			return {
				intervalUnit: intervalUnit,
				intervalStart: intervalStart,
				intervalEnd: intervalEnd,
				start: start,
				end: end
			};
		},


		// Computes the new date when the user hits the prev button, given the current date
		computePrevDate: function(date) {
			return this.massageCurrentDate(
				date.clone().startOf(this.intervalUnit).subtract(this.intervalDuration), -1
			);
		},


		// Computes the new date when the user hits the next button, given the current date
		computeNextDate: function(date) {
			return this.massageCurrentDate(
				date.clone().startOf(this.intervalUnit).add(this.intervalDuration)
			);
		},


		// Given an arbitrarily calculated current date of the calendar, returns a date that is ensured to be completely
		// visible. `direction` is optional and indicates which direction the current date was being
		// incremented or decremented (1 or -1).
		massageCurrentDate: function(date, direction) {
			if (this.intervalDuration.as('days') <= 1) { // if the view displays a single day or smaller
				if (this.isHiddenDay(date)) {
					date = this.skipHiddenDays(date, direction);
					date.startOf('day');
				}
			}

			return date;
		},


		/* Title and Date Formatting
		------------------------------------------------------------------------------------------------------------------*/


		// Sets the view's title property to the most updated computed value
		updateTitle: function() {
			this.title = this.computeTitle();
		},


		// Computes what the title at the top of the calendar should be for this view
		computeTitle: function() {
			return this.formatRange(
				{
					// in case intervalStart/End has a time, make sure timezone is correct
					start: this.calendar.applyTimezone(this.intervalStart),
					end: this.calendar.applyTimezone(this.intervalEnd)
				},
				this.opt('titleFormat') || this.computeTitleFormat(),
				this.opt('titleRangeSeparator')
			);
		},


		// Generates the format string that should be used to generate the title for the current date range.
		// Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
		computeTitleFormat: function() {
			if (this.intervalUnit == 'year') {
				return 'YYYY';
			}
			else if (this.intervalUnit == 'month') {
				return this.opt('monthYearFormat'); // like "September 2014"
			}
			else if (this.intervalDuration.as('days') > 1) {
				return 'll'; // multi-day range. shorter, like "Sep 9 - 10 2014"
			}
			else {
				return 'LL'; // one day. longer, like "September 9 2014"
			}
		},


		// Utility for formatting a range. Accepts a range object, formatting string, and optional separator.
		// Displays all-day ranges naturally, with an inclusive end. Takes the current isRTL into account.
		// The timezones of the dates within `range` will be respected.
		formatRange: function(range, formatStr, separator) {
			var end = range.end;

			if (!end.hasTime()) { // all-day?
				end = end.clone().subtract(1); // convert to inclusive. last ms of previous day
			}

			return formatRange(range.start, end, formatStr, separator, this.opt('isRTL'));
		},


		getAllDayHtml: function() {
			return this.opt('allDayHtml') || htmlEscape(this.opt('allDayText'));
		},


		/* Rendering
		------------------------------------------------------------------------------------------------------------------*/


		// Sets the container element that the view should render inside of.
		// Does other DOM-related initializations.
		setElement: function(el) {
			this.el = el;
			this.bindGlobalHandlers();
		},


		// Removes the view's container element from the DOM, clearing any content beforehand.
		// Undoes any other DOM-related attachments.
		removeElement: function() {
			this.clear(); // clears all content

			// clean up the skeleton
			if (this.isSkeletonRendered) {
				this.unrenderSkeleton();
				this.isSkeletonRendered = false;
			}

			this.unbindGlobalHandlers();

			this.el.remove();

			// NOTE: don't null-out this.el in case the View was destroyed within an API callback.
			// We don't null-out the View's other jQuery element references upon destroy,
			//  so we shouldn't kill this.el either.
		},


		// Does everything necessary to display the view centered around the given unzoned date.
		// Does every type of rendering EXCEPT rendering events.
		// Is asychronous and returns a promise.
		display: function(date, explicitScrollState) {
			var _this = this;
			var prevScrollState = null;

			if (explicitScrollState != null && this.displaying) { // don't need prevScrollState if explicitScrollState
				prevScrollState = this.queryScroll();
			}

			this.calendar.freezeContentHeight();

			return syncThen(this.clear(), function() { // clear the content first
				return (
					_this.displaying =
						syncThen(_this.displayView(date), function() { // displayView might return a promise

							// caller of display() wants a specific scroll state?
							if (explicitScrollState != null) {
								// we make an assumption that this is NOT the initial render,
								// and thus don't need forceScroll (is inconveniently asynchronous)
								_this.setScroll(explicitScrollState);
							}
							else {
								_this.forceScroll(_this.computeInitialScroll(prevScrollState));
							}

							_this.calendar.unfreezeContentHeight();
							_this.triggerRender();
						})
				);
			});
		},


		// Does everything necessary to clear the content of the view.
		// Clears dates and events. Does not clear the skeleton.
		// Is asychronous and returns a promise.
		clear: function() {
			var _this = this;
			var displaying = this.displaying;

			if (displaying) { // previously displayed, or in the process of being displayed?
				return syncThen(displaying, function() { // wait for the display to finish
					_this.displaying = null;
					_this.clearEvents();
					return _this.clearView(); // might return a promise. chain it
				});
			}
			else {
				return $.when(); // an immediately-resolved promise
			}
		},


		// Displays the view's non-event content, such as date-related content or anything required by events.
		// Renders the view's non-content skeleton if necessary.
		// Can be asynchronous and return a promise.
		displayView: function(date) {
			if (!this.isSkeletonRendered) {
				this.renderSkeleton();
				this.isSkeletonRendered = true;
			}
			if (date) {
				this.setDate(date);
			}
			if (this.render) {
				this.render(); // TODO: deprecate
			}
			this.renderDates();
			this.updateSize();
			this.renderBusinessHours(); // might need coordinates, so should go after updateSize()
			this.startNowIndicator();
		},


		// Unrenders the view content that was rendered in displayView.
		// Can be asynchronous and return a promise.
		clearView: function() {
			this.unselect();
			this.stopNowIndicator();
			this.triggerUnrender();
			this.unrenderBusinessHours();
			this.unrenderDates();
			if (this.destroy) {
				this.destroy(); // TODO: deprecate
			}
		},


		// Renders the basic structure of the view before any content is rendered
		renderSkeleton: function() {
			// subclasses should implement
		},


		// Unrenders the basic structure of the view
		unrenderSkeleton: function() {
			// subclasses should implement
		},


		// Renders the view's date-related content.
		// Assumes setRange has already been called and the skeleton has already been rendered.
		renderDates: function() {
			// subclasses should implement
		},


		// Unrenders the view's date-related content
		unrenderDates: function() {
			// subclasses should override
		},


		// Signals that the view's content has been rendered
		triggerRender: function() {
			this.trigger('viewRender', this, this, this.el);
		},


		// Signals that the view's content is about to be unrendered
		triggerUnrender: function() {
			this.trigger('viewDestroy', this, this, this.el);
		},


		// Binds DOM handlers to elements that reside outside the view container, such as the document
		bindGlobalHandlers: function() {
			this.listenTo($(document), 'mousedown', this.handleDocumentMousedown);
			this.listenTo($(document), 'touchstart', this.processUnselect);
		},


		// Unbinds DOM handlers from elements that reside outside the view container
		unbindGlobalHandlers: function() {
			this.stopListeningTo($(document));
		},


		// Initializes internal variables related to theming
		initThemingProps: function() {
			var tm = this.opt('theme') ? 'ui' : 'fc';

			this.widgetHeaderClass = tm + '-widget-header';
			this.widgetContentClass = tm + '-widget-content';
			this.highlightStateClass = tm + '-state-highlight';
		},


		/* Business Hours
		------------------------------------------------------------------------------------------------------------------*/


		// Renders business-hours onto the view. Assumes updateSize has already been called.
		renderBusinessHours: function() {
			// subclasses should implement
		},


		// Unrenders previously-rendered business-hours
		unrenderBusinessHours: function() {
			// subclasses should implement
		},


		/* Now Indicator
		------------------------------------------------------------------------------------------------------------------*/


		// Immediately render the current time indicator and begins re-rendering it at an interval,
		// which is defined by this.getNowIndicatorUnit().
		// TODO: somehow do this for the current whole day's background too
		startNowIndicator: function() {
			var _this = this;
			var unit;
			var update;
			var delay; // ms wait value

			if (this.opt('nowIndicator')) {
				unit = this.getNowIndicatorUnit();
				if (unit) {
					update = proxy(this, 'updateNowIndicator'); // bind to `this`

					this.initialNowDate = this.calendar.getNow();
					this.initialNowQueriedMs = +new Date();
					this.renderNowIndicator(this.initialNowDate);
					this.isNowIndicatorRendered = true;

					// wait until the beginning of the next interval
					delay = this.initialNowDate.clone().startOf(unit).add(1, unit) - this.initialNowDate;
					this.nowIndicatorTimeoutID = setTimeout(function() {
						_this.nowIndicatorTimeoutID = null;
						update();
						delay = +moment.duration(1, unit);
						delay = Math.max(100, delay); // prevent too frequent
						_this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval
					}, delay);
				}
			}
		},


		// rerenders the now indicator, computing the new current time from the amount of time that has passed
		// since the initial getNow call.
		updateNowIndicator: function() {
			if (this.isNowIndicatorRendered) {
				this.unrenderNowIndicator();
				this.renderNowIndicator(
					this.initialNowDate.clone().add(new Date() - this.initialNowQueriedMs) // add ms
				);
			}
		},


		// Immediately unrenders the view's current time indicator and stops any re-rendering timers.
		// Won't cause side effects if indicator isn't rendered.
		stopNowIndicator: function() {
			if (this.isNowIndicatorRendered) {

				if (this.nowIndicatorTimeoutID) {
					clearTimeout(this.nowIndicatorTimeoutID);
					this.nowIndicatorTimeoutID = null;
				}
				if (this.nowIndicatorIntervalID) {
					clearTimeout(this.nowIndicatorIntervalID);
					this.nowIndicatorIntervalID = null;
				}

				this.unrenderNowIndicator();
				this.isNowIndicatorRendered = false;
			}
		},


		// Returns a string unit, like 'second' or 'minute' that defined how often the current time indicator
		// should be refreshed. If something falsy is returned, no time indicator is rendered at all.
		getNowIndicatorUnit: function() {
			// subclasses should implement
		},


		// Renders a current time indicator at the given datetime
		renderNowIndicator: function(date) {
			// subclasses should implement
		},


		// Undoes the rendering actions from renderNowIndicator
		unrenderNowIndicator: function() {
			// subclasses should implement
		},


		/* Dimensions
		------------------------------------------------------------------------------------------------------------------*/


		// Refreshes anything dependant upon sizing of the container element of the grid
		updateSize: function(isResize) {
			var scrollState;

			if (isResize) {
				scrollState = this.queryScroll();
			}

			this.updateHeight(isResize);
			this.updateWidth(isResize);
			this.updateNowIndicator();

			if (isResize) {
				this.setScroll(scrollState);
			}
		},


		// Refreshes the horizontal dimensions of the calendar
		updateWidth: function(isResize) {
			// subclasses should implement
		},


		// Refreshes the vertical dimensions of the calendar
		updateHeight: function(isResize) {
			var calendar = this.calendar; // we poll the calendar for height information

			this.setHeight(
				calendar.getSuggestedViewHeight(),
				calendar.isHeightAuto()
			);
		},


		// Updates the vertical dimensions of the calendar to the specified height.
		// if `isAuto` is set to true, height becomes merely a suggestion and the view should use its "natural" height.
		setHeight: function(height, isAuto) {
			// subclasses should implement
		},


		/* Scroller
		------------------------------------------------------------------------------------------------------------------*/


		// Computes the initial pre-configured scroll state prior to allowing the user to change it.
		// Given the scroll state from the previous rendering. If first time rendering, given null.
		computeInitialScroll: function(previousScrollState) {
			return 0;
		},


		// Retrieves the view's current natural scroll state. Can return an arbitrary format.
		queryScroll: function() {
			// subclasses must implement
		},


		// Sets the view's scroll state. Will accept the same format computeInitialScroll and queryScroll produce.
		setScroll: function(scrollState) {
			// subclasses must implement
		},


		// Sets the scroll state, making sure to overcome any predefined scroll value the browser has in mind
		forceScroll: function(scrollState) {
			var _this = this;

			this.setScroll(scrollState);
			setTimeout(function() {
				_this.setScroll(scrollState);
			}, 0);
		},


		/* Event Elements / Segments
		------------------------------------------------------------------------------------------------------------------*/


		// Does everything necessary to display the given events onto the current view
		displayEvents: function(events) {
			var scrollState = this.queryScroll();

			this.clearEvents();
			this.renderEvents(events);
			this.isEventsRendered = true;
			this.setScroll(scrollState);
			this.triggerEventRender();
		},


		// Does everything necessary to clear the view's currently-rendered events
		clearEvents: function() {
			var scrollState;

			if (this.isEventsRendered) {

				// TODO: optimize: if we know this is part of a displayEvents call, don't queryScroll/setScroll
				scrollState = this.queryScroll();

				this.triggerEventUnrender();
				if (this.destroyEvents) {
					this.destroyEvents(); // TODO: deprecate
				}
				this.unrenderEvents();
				this.setScroll(scrollState);
				this.isEventsRendered = false;
			}
		},


		// Renders the events onto the view.
		renderEvents: function(events) {
			// subclasses should implement
		},


		// Removes event elements from the view.
		unrenderEvents: function() {
			// subclasses should implement
		},


		// Signals that all events have been rendered
		triggerEventRender: function() {
			this.renderedEventSegEach(function(seg) {
				this.trigger('eventAfterRender', seg.event, seg.event, seg.el);
			});
			this.trigger('eventAfterAllRender');
		},


		// Signals that all event elements are about to be removed
		triggerEventUnrender: function() {
			this.renderedEventSegEach(function(seg) {
				this.trigger('eventDestroy', seg.event, seg.event, seg.el);
			});
		},


		// Given an event and the default element used for rendering, returns the element that should actually be used.
		// Basically runs events and elements through the eventRender hook.
		resolveEventEl: function(event, el) {
			var custom = this.trigger('eventRender', event, event, el);

			if (custom === false) { // means don't render at all
				el = null;
			}
			else if (custom && custom !== true) {
				el = $(custom);
			}

			return el;
		},


		// Hides all rendered event segments linked to the given event
		showEvent: function(event) {
			this.renderedEventSegEach(function(seg) {
				seg.el.css('visibility', '');
			}, event);
		},


		// Shows all rendered event segments linked to the given event
		hideEvent: function(event) {
			this.renderedEventSegEach(function(seg) {
				seg.el.css('visibility', 'hidden');
			}, event);
		},


		// Iterates through event segments that have been rendered (have an el). Goes through all by default.
		// If the optional `event` argument is specified, only iterates through segments linked to that event.
		// The `this` value of the callback function will be the view.
		renderedEventSegEach: function(func, event) {
			var segs = this.getEventSegs();
			var i;

			for (i = 0; i < segs.length; i++) {
				if (!event || segs[i].event._id === event._id) {
					if (segs[i].el) {
						func.call(this, segs[i]);
					}
				}
			}
		},


		// Retrieves all the rendered segment objects for the view
		getEventSegs: function() {
			// subclasses must implement
			return [];
		},


		/* Event Drag-n-Drop
		------------------------------------------------------------------------------------------------------------------*/


		// Computes if the given event is allowed to be dragged by the user
		isEventDraggable: function(event) {
			var source = event.source || {};

			return firstDefined(
				event.startEditable,
				source.startEditable,
				this.opt('eventStartEditable'),
				event.editable,
				source.editable,
				this.opt('editable')
			);
		},


		// Must be called when an event in the view is dropped onto new location.
		// `dropLocation` is an object that contains the new zoned start/end/allDay values for the event.
		reportEventDrop: function(event, dropLocation, largeUnit, el, ev) {
			var calendar = this.calendar;
			var mutateResult = calendar.mutateEvent(event, dropLocation, largeUnit);
			var undoFunc = function() {
				mutateResult.undo();
				calendar.reportEventChange();
			};

			this.triggerEventDrop(event, mutateResult.dateDelta, undoFunc, el, ev);
			calendar.reportEventChange(); // will rerender events
		},


		// Triggers event-drop handlers that have subscribed via the API
		triggerEventDrop: function(event, dateDelta, undoFunc, el, ev) {
			this.trigger('eventDrop', el[0], event, dateDelta, undoFunc, ev, {}); // {} = jqui dummy
		},


		/* External Element Drag-n-Drop
		------------------------------------------------------------------------------------------------------------------*/


		// Must be called when an external element, via jQuery UI, has been dropped onto the calendar.
		// `meta` is the parsed data that has been embedded into the dragging event.
		// `dropLocation` is an object that contains the new zoned start/end/allDay values for the event.
		reportExternalDrop: function(meta, dropLocation, el, ev, ui) {
			var eventProps = meta.eventProps;
			var eventInput;
			var event;

			// Try to build an event object and render it. TODO: decouple the two
			if (eventProps) {
				eventInput = $.extend({}, eventProps, dropLocation);
				event = this.calendar.renderEvent(eventInput, meta.stick)[0]; // renderEvent returns an array
			}

			this.triggerExternalDrop(event, dropLocation, el, ev, ui);
		},


		// Triggers external-drop handlers that have subscribed via the API
		triggerExternalDrop: function(event, dropLocation, el, ev, ui) {

			// trigger 'drop' regardless of whether element represents an event
			this.trigger('drop', el[0], dropLocation.start, ev, ui);

			if (event) {
				this.trigger('eventReceive', null, event); // signal an external event landed
			}
		},


		/* Drag-n-Drop Rendering (for both events and external elements)
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of a event or external-element drag over the given drop zone.
		// If an external-element, seg will be `null`.
		// Must return elements used for any mock events.
		renderDrag: function(dropLocation, seg) {
			// subclasses must implement
		},


		// Unrenders a visual indication of an event or external-element being dragged.
		unrenderDrag: function() {
			// subclasses must implement
		},


		/* Event Resizing
		------------------------------------------------------------------------------------------------------------------*/


		// Computes if the given event is allowed to be resized from its starting edge
		isEventResizableFromStart: function(event) {
			return this.opt('eventResizableFromStart') && this.isEventResizable(event);
		},


		// Computes if the given event is allowed to be resized from its ending edge
		isEventResizableFromEnd: function(event) {
			return this.isEventResizable(event);
		},


		// Computes if the given event is allowed to be resized by the user at all
		isEventResizable: function(event) {
			var source = event.source || {};

			return firstDefined(
				event.durationEditable,
				source.durationEditable,
				this.opt('eventDurationEditable'),
				event.editable,
				source.editable,
				this.opt('editable')
			);
		},


		// Must be called when an event in the view has been resized to a new length
		reportEventResize: function(event, resizeLocation, largeUnit, el, ev) {
			var calendar = this.calendar;
			var mutateResult = calendar.mutateEvent(event, resizeLocation, largeUnit);
			var undoFunc = function() {
				mutateResult.undo();
				calendar.reportEventChange();
			};

			this.triggerEventResize(event, mutateResult.durationDelta, undoFunc, el, ev);
			calendar.reportEventChange(); // will rerender events
		},


		// Triggers event-resize handlers that have subscribed via the API
		triggerEventResize: function(event, durationDelta, undoFunc, el, ev) {
			this.trigger('eventResize', el[0], event, durationDelta, undoFunc, ev, {}); // {} = jqui dummy
		},


		/* Selection (time range)
		------------------------------------------------------------------------------------------------------------------*/


		// Selects a date span on the view. `start` and `end` are both Moments.
		// `ev` is the native mouse event that begin the interaction.
		select: function(span, ev) {
			this.unselect(ev);
			this.renderSelection(span);
			this.reportSelection(span, ev);
		},


		// Renders a visual indication of the selection
		renderSelection: function(span) {
			// subclasses should implement
		},


		// Called when a new selection is made. Updates internal state and triggers handlers.
		reportSelection: function(span, ev) {
			this.isSelected = true;
			this.triggerSelect(span, ev);
		},


		// Triggers handlers to 'select'
		triggerSelect: function(span, ev) {
			this.trigger(
				'select',
				null,
				this.calendar.applyTimezone(span.start), // convert to calendar's tz for external API
				this.calendar.applyTimezone(span.end), // "
				ev
			);
		},


		// Undoes a selection. updates in the internal state and triggers handlers.
		// `ev` is the native mouse event that began the interaction.
		unselect: function(ev) {
			if (this.isSelected) {
				this.isSelected = false;
				if (this.destroySelection) {
					this.destroySelection(); // TODO: deprecate
				}
				this.unrenderSelection();
				this.trigger('unselect', null, ev);
			}
		},


		// Unrenders a visual indication of selection
		unrenderSelection: function() {
			// subclasses should implement
		},


		/* Event Selection
		------------------------------------------------------------------------------------------------------------------*/


		selectEvent: function(event) {
			if (!this.selectedEvent || this.selectedEvent !== event) {
				this.unselectEvent();
				this.renderedEventSegEach(function(seg) {
					seg.el.addClass('fc-selected');
				}, event);
				this.selectedEvent = event;
			}
		},


		unselectEvent: function() {
			if (this.selectedEvent) {
				this.renderedEventSegEach(function(seg) {
					seg.el.removeClass('fc-selected');
				}, this.selectedEvent);
				this.selectedEvent = null;
			}
		},


		isEventSelected: function(event) {
			// event references might change on refetchEvents(), while selectedEvent doesn't,
			// so compare IDs
			return this.selectedEvent && this.selectedEvent._id === event._id;
		},


		/* Mouse / Touch Unselecting (time range & event unselection)
		------------------------------------------------------------------------------------------------------------------*/
		// TODO: move consistently to down/start or up/end?
		// TODO: don't kill previous selection if touch scrolling


		handleDocumentMousedown: function(ev) {
			if (isPrimaryMouseButton(ev)) {
				this.processUnselect(ev);
			}
		},


		processUnselect: function(ev) {
			this.processRangeUnselect(ev);
			this.processEventUnselect(ev);
		},


		processRangeUnselect: function(ev) {
			var ignore;

			// is there a time-range selection?
			if (this.isSelected && this.opt('unselectAuto')) {
				// only unselect if the clicked element is not identical to or inside of an 'unselectCancel' element
				ignore = this.opt('unselectCancel');
				if (!ignore || !$(ev.target).closest(ignore).length) {
					this.unselect(ev);
				}
			}
		},


		processEventUnselect: function(ev) {
			if (this.selectedEvent) {
				if (!$(ev.target).closest('.fc-selected').length) {
					this.unselectEvent();
				}
			}
		},


		/* Day Click
		------------------------------------------------------------------------------------------------------------------*/


		// Triggers handlers to 'dayClick'
		// Span has start/end of the clicked area. Only the start is useful.
		triggerDayClick: function(span, dayEl, ev) {
			this.trigger(
				'dayClick',
				dayEl,
				this.calendar.applyTimezone(span.start), // convert to calendar's timezone for external API
				ev
			);
		},


		/* Date Utils
		------------------------------------------------------------------------------------------------------------------*/


		// Initializes internal variables related to calculating hidden days-of-week
		initHiddenDays: function() {
			var hiddenDays = this.opt('hiddenDays') || []; // array of day-of-week indices that are hidden
			var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
			var dayCnt = 0;
			var i;

			if (this.opt('weekends') === false) {
				hiddenDays.push(0, 6); // 0=sunday, 6=saturday
			}

			for (i = 0; i < 7; i++) {
				if (
					!(isHiddenDayHash[i] = $.inArray(i, hiddenDays) !== -1)
				) {
					dayCnt++;
				}
			}

			if (!dayCnt) {
				throw 'invalid hiddenDays'; // all days were hidden? bad.
			}

			this.isHiddenDayHash = isHiddenDayHash;
		},


		// Is the current day hidden?
		// `day` is a day-of-week index (0-6), or a Moment
		isHiddenDay: function(day) {
			if (moment.isMoment(day)) {
				day = day.day();
			}
			return this.isHiddenDayHash[day];
		},


		// Incrementing the current day until it is no longer a hidden day, returning a copy.
		// If the initial value of `date` is not a hidden day, don't do anything.
		// Pass `isExclusive` as `true` if you are dealing with an end date.
		// `inc` defaults to `1` (increment one day forward each time)
		skipHiddenDays: function(date, inc, isExclusive) {
			var out = date.clone();
			inc = inc || 1;
			while (
				this.isHiddenDayHash[(out.day() + (isExclusive ? inc : 0) + 7) % 7]
			) {
				out.add(inc, 'days');
			}
			return out;
		},


		// Returns the date range of the full days the given range visually appears to occupy.
		// Returns a new range object.
		computeDayRange: function(range) {
			var startDay = range.start.clone().stripTime(); // the beginning of the day the range starts
			var end = range.end;
			var endDay = null;
			var endTimeMS;

			if (end) {
				endDay = end.clone().stripTime(); // the beginning of the day the range exclusively ends
				endTimeMS = +end.time(); // # of milliseconds into `endDay`

				// If the end time is actually inclusively part of the next day and is equal to or
				// beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
				// Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
				if (endTimeMS && endTimeMS >= this.nextDayThreshold) {
					endDay.add(1, 'days');
				}
			}

			// If no end was specified, or if it is within `startDay` but not past nextDayThreshold,
			// assign the default duration of one day.
			if (!end || endDay <= startDay) {
				endDay = startDay.clone().add(1, 'days');
			}

			return { start: startDay, end: endDay };
		},


		// Does the given event visually appear to occupy more than one day?
		isMultiDayEvent: function(event) {
			var range = this.computeDayRange(event); // event is range-ish

			return range.end.diff(range.start, 'days') > 1;
		}

	});

	;;

	/*
	Embodies a div that has potential scrollbars
	*/
	var Scroller = FC.Scroller = Class.extend({

		el: null, // the guaranteed outer element
		scrollEl: null, // the element with the scrollbars
		overflowX: null,
		overflowY: null,


		constructor: function(options) {
			options = options || {};
			this.overflowX = options.overflowX || options.overflow || 'auto';
			this.overflowY = options.overflowY || options.overflow || 'auto';
		},


		render: function() {
			this.el = this.renderEl();
			this.applyOverflow();
		},


		renderEl: function() {
			return (this.scrollEl = $('<div class="fc-scroller"></div>'));
		},


		// sets to natural height, unlocks overflow
		clear: function() {
			this.setHeight('auto');
			this.applyOverflow();
		},


		destroy: function() {
			this.el.remove();
		},


		// Overflow
		// -----------------------------------------------------------------------------------------------------------------


		applyOverflow: function() {
			this.scrollEl.css({
				'overflow-x': this.overflowX,
				'overflow-y': this.overflowY
			});
		},


		// Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'.
		// Useful for preserving scrollbar widths regardless of future resizes.
		// Can pass in scrollbarWidths for optimization.
		lockOverflow: function(scrollbarWidths) {
			var overflowX = this.overflowX;
			var overflowY = this.overflowY;

			scrollbarWidths = scrollbarWidths || this.getScrollbarWidths();

			if (overflowX === 'auto') {
				overflowX = (
						scrollbarWidths.top || scrollbarWidths.bottom || // horizontal scrollbars?
						// OR scrolling pane with massless scrollbars?
						this.scrollEl[0].scrollWidth - 1 > this.scrollEl[0].clientWidth
							// subtract 1 because of IE off-by-one issue
					) ? 'scroll' : 'hidden';
			}

			if (overflowY === 'auto') {
				overflowY = (
						scrollbarWidths.left || scrollbarWidths.right || // vertical scrollbars?
						// OR scrolling pane with massless scrollbars?
						this.scrollEl[0].scrollHeight - 1 > this.scrollEl[0].clientHeight
							// subtract 1 because of IE off-by-one issue
					) ? 'scroll' : 'hidden';
			}

			this.scrollEl.css({ 'overflow-x': overflowX, 'overflow-y': overflowY });
		},


		// Getters / Setters
		// -----------------------------------------------------------------------------------------------------------------


		setHeight: function(height) {
			this.scrollEl.height(height);
		},


		getScrollTop: function() {
			return this.scrollEl.scrollTop();
		},


		setScrollTop: function(top) {
			this.scrollEl.scrollTop(top);
		},


		getClientWidth: function() {
			return this.scrollEl[0].clientWidth;
		},


		getClientHeight: function() {
			return this.scrollEl[0].clientHeight;
		},


		getScrollbarWidths: function() {
			return getScrollbarWidths(this.scrollEl);
		}

	});

	;;

	var Calendar = FC.Calendar = Class.extend({

		dirDefaults: null, // option defaults related to LTR or RTL
		localeDefaults: null, // option defaults related to current locale
		overrides: null, // option overrides given to the fullCalendar constructor
		dynamicOverrides: null, // options set with dynamic setter method. higher precedence than view overrides.
		options: null, // all defaults combined with overrides
		viewSpecCache: null, // cache of view definitions
		view: null, // current View object
		header: null,
		loadingLevel: 0, // number of simultaneous loading tasks


		// a lot of this class' OOP logic is scoped within this constructor function,
		// but in the future, write individual methods on the prototype.
		constructor: Calendar_constructor,


		// Subclasses can override this for initialization logic after the constructor has been called
		initialize: function() {
		},


		// Computes the flattened options hash for the calendar and assigns to `this.options`.
		// Assumes this.overrides and this.dynamicOverrides have already been initialized.
		populateOptionsHash: function() {
			var locale, localeDefaults;
			var isRTL, dirDefaults;

			locale = firstDefined( // explicit locale option given?
				this.dynamicOverrides.locale,
				this.overrides.locale
			);
			localeDefaults = localeOptionHash[locale];
			if (!localeDefaults) { // explicit locale option not given or invalid?
				locale = Calendar.defaults.locale;
				localeDefaults = localeOptionHash[locale] || {};
			}

			isRTL = firstDefined( // based on options computed so far, is direction RTL?
				this.dynamicOverrides.isRTL,
				this.overrides.isRTL,
				localeDefaults.isRTL,
				Calendar.defaults.isRTL
			);
			dirDefaults = isRTL ? Calendar.rtlDefaults : {};

			this.dirDefaults = dirDefaults;
			this.localeDefaults = localeDefaults;
			this.options = mergeOptions([ // merge defaults and overrides. lowest to highest precedence
				Calendar.defaults, // global defaults
				dirDefaults,
				localeDefaults,
				this.overrides,
				this.dynamicOverrides
			]);
			populateInstanceComputableOptions(this.options); // fill in gaps with computed options
		},


		// Gets information about how to create a view. Will use a cache.
		getViewSpec: function(viewType) {
			var cache = this.viewSpecCache;

			return cache[viewType] || (cache[viewType] = this.buildViewSpec(viewType));
		},


		// Given a duration singular unit, like "week" or "day", finds a matching view spec.
		// Preference is given to views that have corresponding buttons.
		getUnitViewSpec: function(unit) {
			var viewTypes;
			var i;
			var spec;

			if ($.inArray(unit, intervalUnits) != -1) {

				// put views that have buttons first. there will be duplicates, but oh well
				viewTypes = this.header.getViewsWithButtons();
				$.each(FC.views, function(viewType) { // all views
					viewTypes.push(viewType);
				});

				for (i = 0; i < viewTypes.length; i++) {
					spec = this.getViewSpec(viewTypes[i]);
					if (spec) {
						if (spec.singleUnit == unit) {
							return spec;
						}
					}
				}
			}
		},


		// Builds an object with information on how to create a given view
		buildViewSpec: function(requestedViewType) {
			var viewOverrides = this.overrides.views || {};
			var specChain = []; // for the view. lowest to highest priority
			var defaultsChain = []; // for the view. lowest to highest priority
			var overridesChain = []; // for the view. lowest to highest priority
			var viewType = requestedViewType;
			var spec; // for the view
			var overrides; // for the view
			var duration;
			var unit;

			// iterate from the specific view definition to a more general one until we hit an actual View class
			while (viewType) {
				spec = fcViews[viewType];
				overrides = viewOverrides[viewType];
				viewType = null; // clear. might repopulate for another iteration

				if (typeof spec === 'function') { // TODO: deprecate
					spec = { 'class': spec };
				}

				if (spec) {
					specChain.unshift(spec);
					defaultsChain.unshift(spec.defaults || {});
					duration = duration || spec.duration;
					viewType = viewType || spec.type;
				}

				if (overrides) {
					overridesChain.unshift(overrides); // view-specific option hashes have options at zero-level
					duration = duration || overrides.duration;
					viewType = viewType || overrides.type;
				}
			}

			spec = mergeProps(specChain);
			spec.type = requestedViewType;
			if (!spec['class']) {
				return false;
			}

			if (duration) {
				duration = moment.duration(duration);
				if (duration.valueOf()) { // valid?
					spec.duration = duration;
					unit = computeIntervalUnit(duration);

					// view is a single-unit duration, like "week" or "day"
					// incorporate options for this. lowest priority
					if (duration.as(unit) === 1) {
						spec.singleUnit = unit;
						overridesChain.unshift(viewOverrides[unit] || {});
					}
				}
			}

			spec.defaults = mergeOptions(defaultsChain);
			spec.overrides = mergeOptions(overridesChain);

			this.buildViewSpecOptions(spec);
			this.buildViewSpecButtonText(spec, requestedViewType);

			return spec;
		},


		// Builds and assigns a view spec's options object from its already-assigned defaults and overrides
		buildViewSpecOptions: function(spec) {
			spec.options = mergeOptions([ // lowest to highest priority
				Calendar.defaults, // global defaults
				spec.defaults, // view's defaults (from ViewSubclass.defaults)
				this.dirDefaults,
				this.localeDefaults, // locale and dir take precedence over view's defaults!
				this.overrides, // calendar's overrides (options given to constructor)
				spec.overrides, // view's overrides (view-specific options)
				this.dynamicOverrides // dynamically set via setter. highest precedence
			]);
			populateInstanceComputableOptions(spec.options);
		},


		// Computes and assigns a view spec's buttonText-related options
		buildViewSpecButtonText: function(spec, requestedViewType) {

			// given an options object with a possible `buttonText` hash, lookup the buttonText for the
			// requested view, falling back to a generic unit entry like "week" or "day"
			function queryButtonText(options) {
				var buttonText = options.buttonText || {};
				return buttonText[requestedViewType] ||
					// view can decide to look up a certain key
					(spec.buttonTextKey ? buttonText[spec.buttonTextKey] : null) ||
					// a key like "month"
					(spec.singleUnit ? buttonText[spec.singleUnit] : null);
			}

			// highest to lowest priority
			spec.buttonTextOverride =
				queryButtonText(this.dynamicOverrides) ||
				queryButtonText(this.overrides) || // constructor-specified buttonText lookup hash takes precedence
				spec.overrides.buttonText; // `buttonText` for view-specific options is a string

			// highest to lowest priority. mirrors buildViewSpecOptions
			spec.buttonTextDefault =
				queryButtonText(this.localeDefaults) ||
				queryButtonText(this.dirDefaults) ||
				spec.defaults.buttonText || // a single string. from ViewSubclass.defaults
				queryButtonText(Calendar.defaults) ||
				(spec.duration ? this.humanizeDuration(spec.duration) : null) || // like "3 days"
				requestedViewType; // fall back to given view name
		},


		// Given a view name for a custom view or a standard view, creates a ready-to-go View object
		instantiateView: function(viewType) {
			var spec = this.getViewSpec(viewType);

			return new spec['class'](this, viewType, spec.options, spec.duration);
		},


		// Returns a boolean about whether the view is okay to instantiate at some point
		isValidViewType: function(viewType) {
			return Boolean(this.getViewSpec(viewType));
		},


		// Should be called when any type of async data fetching begins
		pushLoading: function() {
			if (!(this.loadingLevel++)) {
				this.trigger('loading', null, true, this.view);
			}
		},


		// Should be called when any type of async data fetching completes
		popLoading: function() {
			if (!(--this.loadingLevel)) {
				this.trigger('loading', null, false, this.view);
			}
		},


		// Given arguments to the select method in the API, returns a span (unzoned start/end and other info)
		buildSelectSpan: function(zonedStartInput, zonedEndInput) {
			var start = this.moment(zonedStartInput).stripZone();
			var end;

			if (zonedEndInput) {
				end = this.moment(zonedEndInput).stripZone();
			}
			else if (start.hasTime()) {
				end = start.clone().add(this.defaultTimedEventDuration);
			}
			else {
				end = start.clone().add(this.defaultAllDayEventDuration);
			}

			return { start: start, end: end };
		}

	});


	Calendar.mixin(EmitterMixin);


	function Calendar_constructor(element, overrides) {
		var t = this;


		// Exports
		// -----------------------------------------------------------------------------------

		t.render = render;
		t.destroy = destroy;
		t.refetchEvents = refetchEvents;
		t.refetchEventSources = refetchEventSources;
		t.reportEvents = reportEvents;
		t.reportEventChange = reportEventChange;
		t.rerenderEvents = renderEvents; // `renderEvents` serves as a rerender. an API method
		t.changeView = renderView; // `renderView` will switch to another view
		t.select = select;
		t.unselect = unselect;
		t.prev = prev;
		t.next = next;
		t.prevYear = prevYear;
		t.nextYear = nextYear;
		t.today = today;
		t.gotoDate = gotoDate;
		t.incrementDate = incrementDate;
		t.zoomTo = zoomTo;
		t.getDate = getDate;
		t.getCalendar = getCalendar;
		t.getView = getView;
		t.option = option; // getter/setter method
		t.trigger = trigger;


		// Options
		// -----------------------------------------------------------------------------------

		t.dynamicOverrides = {};
		t.viewSpecCache = {};
		t.optionHandlers = {}; // for Calendar.options.js

		// convert legacy options into non-legacy ones.
		// in the future, when this is removed, don't use `overrides` reference. make a copy.
		t.overrides = massageOverrides(overrides || {});

		t.populateOptionsHash(); // sets this.options



		// Locale-data Internals
		// -----------------------------------------------------------------------------------
		// Apply overrides to the current locale's data

		var localeData;

		// Called immediately, and when any of the options change.
		// Happens before any internal objects rebuild or rerender, because this is very core.
		t.bindOptions([
			'locale', 'monthNames', 'monthNamesShort', 'dayNames', 'dayNamesShort', 'firstDay', 'weekNumberCalculation'
		], function(locale, monthNames, monthNamesShort, dayNames, dayNamesShort, firstDay, weekNumberCalculation) {

			// normalize
			if (weekNumberCalculation === 'iso') {
				weekNumberCalculation = 'ISO'; // normalize
			}

			localeData = createObject( // make a cheap copy
				getMomentLocaleData(locale) // will fall back to en
			);

			if (monthNames) {
				localeData._months = monthNames;
			}
			if (monthNamesShort) {
				localeData._monthsShort = monthNamesShort;
			}
			if (dayNames) {
				localeData._weekdays = dayNames;
			}
			if (dayNamesShort) {
				localeData._weekdaysShort = dayNamesShort;
			}

			if (firstDay == null && weekNumberCalculation === 'ISO') {
				firstDay = 1;
			}
			if (firstDay != null) {
				var _week = createObject(localeData._week); // _week: { dow: # }
				_week.dow = firstDay;
				localeData._week = _week;
			}

			if ( // whitelist certain kinds of input
				weekNumberCalculation === 'ISO' ||
				weekNumberCalculation === 'local' ||
				typeof weekNumberCalculation === 'function'
			) {
				localeData._fullCalendar_weekCalc = weekNumberCalculation; // moment-ext will know what to do with it
			}

			// If the internal current date object already exists, move to new locale.
			// We do NOT need to do this technique for event dates, because this happens when converting to "segments".
			if (date) {
				localizeMoment(date); // sets to localeData
			}
		});


		// Calendar-specific Date Utilities
		// -----------------------------------------------------------------------------------


		t.defaultAllDayEventDuration = moment.duration(t.options.defaultAllDayEventDuration);
		t.defaultTimedEventDuration = moment.duration(t.options.defaultTimedEventDuration);


		// Builds a moment using the settings of the current calendar: timezone and locale.
		// Accepts anything the vanilla moment() constructor accepts.
		t.moment = function() {
			var mom;

			if (t.options.timezone === 'local') {
				mom = FC.moment.apply(null, arguments);

				// Force the moment to be local, because FC.moment doesn't guarantee it.
				if (mom.hasTime()) { // don't give ambiguously-timed moments a local zone
					mom.local();
				}
			}
			else if (t.options.timezone === 'UTC') {
				mom = FC.moment.utc.apply(null, arguments); // process as UTC
			}
			else {
				mom = FC.moment.parseZone.apply(null, arguments); // let the input decide the zone
			}

			localizeMoment(mom);

			return mom;
		};


		// Updates the given moment's locale settings to the current calendar locale settings.
		function localizeMoment(mom) {
			mom._locale = localeData;
		}
		t.localizeMoment = localizeMoment;


		// Returns a boolean about whether or not the calendar knows how to calculate
		// the timezone offset of arbitrary dates in the current timezone.
		t.getIsAmbigTimezone = function() {
			return t.options.timezone !== 'local' && t.options.timezone !== 'UTC';
		};


		// Returns a copy of the given date in the current timezone. Has no effect on dates without times.
		t.applyTimezone = function(date) {
			if (!date.hasTime()) {
				return date.clone();
			}

			var zonedDate = t.moment(date.toArray());
			var timeAdjust = date.time() - zonedDate.time();
			var adjustedZonedDate;

			// Safari sometimes has problems with this coersion when near DST. Adjust if necessary. (bug #2396)
			if (timeAdjust) { // is the time result different than expected?
				adjustedZonedDate = zonedDate.clone().add(timeAdjust); // add milliseconds
				if (date.time() - adjustedZonedDate.time() === 0) { // does it match perfectly now?
					zonedDate = adjustedZonedDate;
				}
			}

			return zonedDate;
		};


		// Returns a moment for the current date, as defined by the client's computer or from the `now` option.
		// Will return an moment with an ambiguous timezone.
		t.getNow = function() {
			var now = t.options.now;
			if (typeof now === 'function') {
				now = now();
			}
			return t.moment(now).stripZone();
		};


		// Get an event's normalized end date. If not present, calculate it from the defaults.
		t.getEventEnd = function(event) {
			if (event.end) {
				return event.end.clone();
			}
			else {
				return t.getDefaultEventEnd(event.allDay, event.start);
			}
		};


		// Given an event's allDay status and start date, return what its fallback end date should be.
		// TODO: rename to computeDefaultEventEnd
		t.getDefaultEventEnd = function(allDay, zonedStart) {
			var end = zonedStart.clone();

			if (allDay) {
				end.stripTime().add(t.defaultAllDayEventDuration);
			}
			else {
				end.add(t.defaultTimedEventDuration);
			}

			if (t.getIsAmbigTimezone()) {
				end.stripZone(); // we don't know what the tzo should be
			}

			return end;
		};


		// Produces a human-readable string for the given duration.
		// Side-effect: changes the locale of the given duration.
		t.humanizeDuration = function(duration) {
			return duration.locale(t.options.locale).humanize();
		};


		
		// Imports
		// -----------------------------------------------------------------------------------


		EventManager.call(t);
		var isFetchNeeded = t.isFetchNeeded;
		var fetchEvents = t.fetchEvents;
		var fetchEventSources = t.fetchEventSources;



		// Locals
		// -----------------------------------------------------------------------------------


		var _element = element[0];
		var header;
		var content;
		var tm; // for making theme classes
		var currentView; // NOTE: keep this in sync with this.view
		var viewsByType = {}; // holds all instantiated view instances, current or not
		var suggestedViewHeight;
		var windowResizeProxy; // wraps the windowResize function
		var ignoreWindowResize = 0;
		var events = [];
		var date; // unzoned
		
		
		
		// Main Rendering
		// -----------------------------------------------------------------------------------


		// compute the initial ambig-timezone date
		if (t.options.defaultDate != null) {
			date = t.moment(t.options.defaultDate).stripZone();
		}
		else {
			date = t.getNow(); // getNow already returns unzoned
		}
		
		
		function render() {
			if (!content) {
				initialRender();
			}
			else if (elementVisible()) {
				// mainly for the public API
				calcSize();
				renderView();
			}
		}
		
		
		function initialRender() {
			element.addClass('fc');

			// called immediately, and upon option change
			t.bindOption('theme', function(theme) {
				tm = theme ? 'ui' : 'fc'; // affects a larger scope
				element.toggleClass('ui-widget', theme);
				element.toggleClass('fc-unthemed', !theme);
			});

			// called immediately, and upon option change.
			// HACK: locale often affects isRTL, so we explicitly listen to that too.
			t.bindOptions([ 'isRTL', 'locale' ], function(isRTL) {
				element.toggleClass('fc-ltr', !isRTL);
				element.toggleClass('fc-rtl', isRTL);
			});

			content = $("<div class='fc-view-container'/>").prependTo(element);

			header = t.header = new Header(t);
			renderHeader();

			renderView(t.options.defaultView);

			if (t.options.handleWindowResize) {
				windowResizeProxy = debounce(windowResize, t.options.windowResizeDelay); // prevents rapid calls
				$(window).resize(windowResizeProxy);
			}
		}


		// can be called repeatedly and Header will rerender
		function renderHeader() {
			header.render();
			if (header.el) {
				element.prepend(header.el);
			}
		}
		
		
		function destroy() {

			if (currentView) {
				currentView.removeElement();

				// NOTE: don't null-out currentView/t.view in case API methods are called after destroy.
				// It is still the "current" view, just not rendered.
			}

			header.removeElement();
			content.remove();
			element.removeClass('fc fc-ltr fc-rtl fc-unthemed ui-widget');

			if (windowResizeProxy) {
				$(window).unbind('resize', windowResizeProxy);
			}
		}
		
		
		function elementVisible() {
			return element.is(':visible');
		}
		
		

		// View Rendering
		// -----------------------------------------------------------------------------------


		// Renders a view because of a date change, view-type change, or for the first time.
		// If not given a viewType, keep the current view but render different dates.
		// Accepts an optional scroll state to restore to.
		function renderView(viewType, explicitScrollState) {
			ignoreWindowResize++;

			// if viewType is changing, remove the old view's rendering
			if (currentView && viewType && currentView.type !== viewType) {
				freezeContentHeight(); // prevent a scroll jump when view element is removed
				clearView();
			}

			// if viewType changed, or the view was never created, create a fresh view
			if (!currentView && viewType) {
				currentView = t.view =
					viewsByType[viewType] ||
					(viewsByType[viewType] = t.instantiateView(viewType));

				currentView.setElement(
					$("<div class='fc-view fc-" + viewType + "-view' />").appendTo(content)
				);
				header.activateButton(viewType);
			}

			if (currentView) {

				// in case the view should render a period of time that is completely hidden
				date = currentView.massageCurrentDate(date);

				// render or rerender the view
				if (
					!currentView.displaying ||
					!( // NOT within interval range signals an implicit date window change
						date >= currentView.intervalStart &&
						date < currentView.intervalEnd
					)
				) {
					if (elementVisible()) {

						currentView.display(date, explicitScrollState); // will call freezeContentHeight
						unfreezeContentHeight(); // immediately unfreeze regardless of whether display is async

						// need to do this after View::render, so dates are calculated
						updateHeaderTitle();
						updateTodayButton();

						getAndRenderEvents();
					}
				}
			}

			unfreezeContentHeight(); // undo any lone freezeContentHeight calls
			ignoreWindowResize--;
		}


		// Unrenders the current view and reflects this change in the Header.
		// Unregsiters the `currentView`, but does not remove from viewByType hash.
		function clearView() {
			header.deactivateButton(currentView.type);
			currentView.removeElement();
			currentView = t.view = null;
		}


		// Destroys the view, including the view object. Then, re-instantiates it and renders it.
		// Maintains the same scroll state.
		// TODO: maintain any other user-manipulated state.
		function reinitView() {
			ignoreWindowResize++;
			freezeContentHeight();

			var viewType = currentView.type;
			var scrollState = currentView.queryScroll();
			clearView();
			renderView(viewType, scrollState);

			unfreezeContentHeight();
			ignoreWindowResize--;
		}

		

		// Resizing
		// -----------------------------------------------------------------------------------


		t.getSuggestedViewHeight = function() {
			if (suggestedViewHeight === undefined) {
				calcSize();
			}
			return suggestedViewHeight;
		};


		t.isHeightAuto = function() {
			return t.options.contentHeight === 'auto' || t.options.height === 'auto';
		};
		
		
		function updateSize(shouldRecalc) {
			if (elementVisible()) {

				if (shouldRecalc) {
					_calcSize();
				}

				ignoreWindowResize++;
				currentView.updateSize(true); // isResize=true. will poll getSuggestedViewHeight() and isHeightAuto()
				ignoreWindowResize--;

				return true; // signal success
			}
		}


		function calcSize() {
			if (elementVisible()) {
				_calcSize();
			}
		}
		
		
		function _calcSize() { // assumes elementVisible
			var contentHeightInput = t.options.contentHeight;
			var heightInput = t.options.height;

			if (typeof contentHeightInput === 'number') { // exists and not 'auto'
				suggestedViewHeight = contentHeightInput;
			}
			else if (typeof contentHeightInput === 'function') { // exists and is a function
				suggestedViewHeight = contentHeightInput();
			}
			else if (typeof heightInput === 'number') { // exists and not 'auto'
				suggestedViewHeight = heightInput - queryHeaderHeight();
			}
			else if (typeof heightInput === 'function') { // exists and is a function
				suggestedViewHeight = heightInput() - queryHeaderHeight();
			}
			else if (heightInput === 'parent') { // set to height of parent element
				suggestedViewHeight = element.parent().height() - queryHeaderHeight();
			}
			else {
				suggestedViewHeight = Math.round(content.width() / Math.max(t.options.aspectRatio, .5));
			}
		}


		function queryHeaderHeight() {
			return header.el ? header.el.outerHeight(true) : 0; // includes margin
		}
		
		
		function windowResize(ev) {
			if (
				!ignoreWindowResize &&
				ev.target === window && // so we don't process jqui "resize" events that have bubbled up
				currentView.start // view has already been rendered
			) {
				if (updateSize(true)) {
					currentView.trigger('windowResize', _element);
				}
			}
		}
		
		
		
		/* Event Fetching/Rendering
		-----------------------------------------------------------------------------*/
		// TODO: going forward, most of this stuff should be directly handled by the view


		function refetchEvents() { // can be called as an API method
			fetchAndRenderEvents();
		}


		// TODO: move this into EventManager?
		function refetchEventSources(matchInputs) {
			fetchEventSources(t.getEventSourcesByMatchArray(matchInputs));
		}


		function renderEvents() { // destroys old events if previously rendered
			if (elementVisible()) {
				freezeContentHeight();
				currentView.displayEvents(events);
				unfreezeContentHeight();
			}
		}
		

		function getAndRenderEvents() {
			if (!t.options.lazyFetching || isFetchNeeded(currentView.start, currentView.end)) {
				fetchAndRenderEvents();
			}
			else {
				renderEvents();
			}
		}


		function fetchAndRenderEvents() {
			fetchEvents(currentView.start, currentView.end);
				// ... will call reportEvents
				// ... which will call renderEvents
		}

		
		// called when event data arrives
		function reportEvents(_events) {
			events = _events;
			renderEvents();
		}


		// called when a single event's data has been changed
		function reportEventChange() {
			renderEvents();
		}



		/* Header Updating
		-----------------------------------------------------------------------------*/


		function updateHeaderTitle() {
			header.updateTitle(currentView.title);
		}


		function updateTodayButton() {
			var now = t.getNow();

			if (now >= currentView.intervalStart && now < currentView.intervalEnd) {
				header.disableButton('today');
			}
			else {
				header.enableButton('today');
			}
		}
		


		/* Selection
		-----------------------------------------------------------------------------*/
		

		// this public method receives start/end dates in any format, with any timezone
		function select(zonedStartInput, zonedEndInput) {
			currentView.select(
				t.buildSelectSpan.apply(t, arguments)
			);
		}
		

		function unselect() { // safe to be called before renderView
			if (currentView) {
				currentView.unselect();
			}
		}
		
		
		
		/* Date
		-----------------------------------------------------------------------------*/
		
		
		function prev() {
			date = currentView.computePrevDate(date);
			renderView();
		}
		
		
		function next() {
			date = currentView.computeNextDate(date);
			renderView();
		}
		
		
		function prevYear() {
			date.add(-1, 'years');
			renderView();
		}
		
		
		function nextYear() {
			date.add(1, 'years');
			renderView();
		}
		
		
		function today() {
			date = t.getNow();
			renderView();
		}
		
		
		function gotoDate(zonedDateInput) {
			date = t.moment(zonedDateInput).stripZone();
			renderView();
		}
		
		
		function incrementDate(delta) {
			date.add(moment.duration(delta));
			renderView();
		}


		// Forces navigation to a view for the given date.
		// `viewType` can be a specific view name or a generic one like "week" or "day".
		function zoomTo(newDate, viewType) {
			var spec;

			viewType = viewType || 'day'; // day is default zoom
			spec = t.getViewSpec(viewType) || t.getUnitViewSpec(viewType);

			date = newDate.clone();
			renderView(spec ? spec.type : null);
		}
		
		
		// for external API
		function getDate() {
			return t.applyTimezone(date); // infuse the calendar's timezone
		}



		/* Height "Freezing"
		-----------------------------------------------------------------------------*/
		// TODO: move this into the view

		t.freezeContentHeight = freezeContentHeight;
		t.unfreezeContentHeight = unfreezeContentHeight;


		function freezeContentHeight() {
			content.css({
				width: '100%',
				height: content.height(),
				overflow: 'hidden'
			});
		}


		function unfreezeContentHeight() {
			content.css({
				width: '',
				height: '',
				overflow: ''
			});
		}
		
		
		
		/* Misc
		-----------------------------------------------------------------------------*/
		

		function getCalendar() {
			return t;
		}

		
		function getView() {
			return currentView;
		}
		
		
		function option(name, value) {
			var newOptionHash;

			if (typeof name === 'string') {
				if (value === undefined) { // getter
					return t.options[name];
				}
				else { // setter for individual option
					newOptionHash = {};
					newOptionHash[name] = value;
					setOptions(newOptionHash);
				}
			}
			else if (typeof name === 'object') { // compound setter with object input
				setOptions(name);
			}
		}


		function setOptions(newOptionHash) {
			var optionCnt = 0;
			var optionName;

			for (optionName in newOptionHash) {
				t.dynamicOverrides[optionName] = newOptionHash[optionName];
			}

			t.viewSpecCache = {}; // the dynamic override invalidates the options in this cache, so just clear it
			t.populateOptionsHash(); // this.options needs to be recomputed after the dynamic override

			// trigger handlers after this.options has been updated
			for (optionName in newOptionHash) {
				t.triggerOptionHandlers(optionName); // recall bindOption/bindOptions
				optionCnt++;
			}

			// special-case handling of single option change.
			// if only one option change, `optionName` will be its name.
			if (optionCnt === 1) {
				if (optionName === 'height' || optionName === 'contentHeight' || optionName === 'aspectRatio') {
					updateSize(true); // true = allow recalculation of height
					return;
				}
				else if (optionName === 'defaultDate') {
					return; // can't change date this way. use gotoDate instead
				}
				else if (optionName === 'businessHours') {
					if (currentView) {
						currentView.unrenderBusinessHours();
						currentView.renderBusinessHours();
					}
					return;
				}
				else if (optionName === 'timezone') {
					t.rezoneArrayEventSources();
					refetchEvents();
					return;
				}
			}

			// catch-all. rerender the header and rebuild/rerender the current view
			renderHeader();
			viewsByType = {}; // even non-current views will be affected by this option change. do before rerender
			reinitView();
		}
		
		
		function trigger(name, thisObj) { // overrides the Emitter's trigger method :(
			var args = Array.prototype.slice.call(arguments, 2);

			thisObj = thisObj || _element;
			this.triggerWith(name, thisObj, args); // Emitter's method

			if (t.options[name]) {
				return t.options[name].apply(thisObj, args);
			}
		}

		t.initialize();
	}

	;;
	/*
	Options binding/triggering system.
	*/
	Calendar.mixin({

		// A map of option names to arrays of handler objects. Initialized to {} in Calendar.
		// Format for a handler object:
		// {
		//   func // callback function to be called upon change
		//   names // option names whose values should be given to func
		// }
		optionHandlers: null, 

		// Calls handlerFunc immediately, and when the given option has changed.
		// handlerFunc will be given the option value.
		bindOption: function(optionName, handlerFunc) {
			this.bindOptions([ optionName ], handlerFunc);
		},

		// Calls handlerFunc immediately, and when any of the given options change.
		// handlerFunc will be given each option value as ordered function arguments.
		bindOptions: function(optionNames, handlerFunc) {
			var handlerObj = { func: handlerFunc, names: optionNames };
			var i;

			for (i = 0; i < optionNames.length; i++) {
				this.registerOptionHandlerObj(optionNames[i], handlerObj);
			}

			this.triggerOptionHandlerObj(handlerObj);
		},

		// Puts the given handler object into the internal hash
		registerOptionHandlerObj: function(optionName, handlerObj) {
			(this.optionHandlers[optionName] || (this.optionHandlers[optionName] = []))
				.push(handlerObj);
		},

		// Reports that the given option has changed, and calls all appropriate handlers.
		triggerOptionHandlers: function(optionName) {
			var handlerObjs = this.optionHandlers[optionName] || [];
			var i;

			for (i = 0; i < handlerObjs.length; i++) {
				this.triggerOptionHandlerObj(handlerObjs[i]);
			}
		},

		// Calls the callback for a specific handler object, passing in the appropriate arguments.
		triggerOptionHandlerObj: function(handlerObj) {
			var optionNames = handlerObj.names;
			var optionValues = [];
			var i;

			for (i = 0; i < optionNames.length; i++) {
				optionValues.push(this.options[optionNames[i]]);
			}

			handlerObj.func.apply(this, optionValues); // maintain the Calendar's `this` context
		}

	});

	;;

	Calendar.defaults = {

		titleRangeSeparator: ' \u2013 ', // en dash
		monthYearFormat: 'MMMM YYYY', // required for en. other locales rely on datepicker computable option

		defaultTimedEventDuration: '02:00:00',
		defaultAllDayEventDuration: { days: 1 },
		forceEventDuration: false,
		nextDayThreshold: '09:00:00', // 9am

		// display
		defaultView: 'month',
		aspectRatio: 1.35,
		header: {
			left: 'title',
			center: '',
			right: 'today prev,next'
		},
		weekends: true,
		weekNumbers: false,

		weekNumberTitle: 'W',
		weekNumberCalculation: 'local',
		
		//editable: false,

		//nowIndicator: false,

		scrollTime: '06:00:00',
		
		// event ajax
		lazyFetching: true,
		startParam: 'start',
		endParam: 'end',
		timezoneParam: 'timezone',

		timezone: false,

		//allDayDefault: undefined,

		// locale
		isRTL: false,
		buttonText: {
			prev: "prev",
			next: "next",
			prevYear: "prev year",
			nextYear: "next year",
			year: 'year', // TODO: locale files need to specify this
			today: 'today',
			month: 'month',
			week: 'week',
			day: 'day'
		},

		buttonIcons: {
			prev: 'left-single-arrow',
			next: 'right-single-arrow',
			prevYear: 'left-double-arrow',
			nextYear: 'right-double-arrow'
		},

		allDayText: 'all-day',
		
		// jquery-ui theming
		theme: false,
		themeButtonIcons: {
			prev: 'circle-triangle-w',
			next: 'circle-triangle-e',
			prevYear: 'seek-prev',
			nextYear: 'seek-next'
		},

		//eventResizableFromStart: false,
		dragOpacity: .75,
		dragRevertDuration: 500,
		dragScroll: true,
		
		//selectable: false,
		unselectAuto: true,
		
		dropAccept: '*',

		eventOrder: 'title',

		eventLimit: false,
		eventLimitText: 'more',
		eventLimitClick: 'popover',
		dayPopoverFormat: 'LL',
		
		handleWindowResize: true,
		windowResizeDelay: 100, // milliseconds before an updateSize happens

		longPressDelay: 1000
		
	};


	Calendar.englishDefaults = { // used by locale.js
		dayPopoverFormat: 'dddd, MMMM D'
	};


	Calendar.rtlDefaults = { // right-to-left defaults
		header: { // TODO: smarter solution (first/center/last ?)
			left: 'next,prev today',
			center: '',
			right: 'title'
		},
		buttonIcons: {
			prev: 'right-single-arrow',
			next: 'left-single-arrow',
			prevYear: 'right-double-arrow',
			nextYear: 'left-double-arrow'
		},
		themeButtonIcons: {
			prev: 'circle-triangle-e',
			next: 'circle-triangle-w',
			nextYear: 'seek-prev',
			prevYear: 'seek-next'
		}
	};

	;;

	var localeOptionHash = FC.locales = {}; // initialize and expose


	// TODO: document the structure and ordering of a FullCalendar locale file


	// Initialize jQuery UI datepicker translations while using some of the translations
	// Will set this as the default locales for datepicker.
	FC.datepickerLocale = function(localeCode, dpLocaleCode, dpOptions) {

		// get the FullCalendar internal option hash for this locale. create if necessary
		var fcOptions = localeOptionHash[localeCode] || (localeOptionHash[localeCode] = {});

		// transfer some simple options from datepicker to fc
		fcOptions.isRTL = dpOptions.isRTL;
		fcOptions.weekNumberTitle = dpOptions.weekHeader;

		// compute some more complex options from datepicker
		$.each(dpComputableOptions, function(name, func) {
			fcOptions[name] = func(dpOptions);
		});

		// is jQuery UI Datepicker is on the page?
		if ($.datepicker) {

			// Register the locale data.
			// FullCalendar and MomentJS use locale codes like "pt-br" but Datepicker
			// does it like "pt-BR" or if it doesn't have the locale, maybe just "pt".
			// Make an alias so the locale can be referenced either way.
			$.datepicker.regional[dpLocaleCode] =
				$.datepicker.regional[localeCode] = // alias
					dpOptions;

			// Alias 'en' to the default locale data. Do this every time.
			$.datepicker.regional.en = $.datepicker.regional[''];

			// Set as Datepicker's global defaults.
			$.datepicker.setDefaults(dpOptions);
		}
	};


	// Sets FullCalendar-specific translations. Will set the locales as the global default.
	FC.locale = function(localeCode, newFcOptions) {
		var fcOptions;
		var momOptions;

		// get the FullCalendar internal option hash for this locale. create if necessary
		fcOptions = localeOptionHash[localeCode] || (localeOptionHash[localeCode] = {});

		// provided new options for this locales? merge them in
		if (newFcOptions) {
			fcOptions = localeOptionHash[localeCode] = mergeOptions([ fcOptions, newFcOptions ]);
		}

		// compute locale options that weren't defined.
		// always do this. newFcOptions can be undefined when initializing from i18n file,
		// so no way to tell if this is an initialization or a default-setting.
		momOptions = getMomentLocaleData(localeCode); // will fall back to en
		$.each(momComputableOptions, function(name, func) {
			if (fcOptions[name] == null) {
				fcOptions[name] = func(momOptions, fcOptions);
			}
		});

		// set it as the default locale for FullCalendar
		Calendar.defaults.locale = localeCode;
	};


	// NOTE: can't guarantee any of these computations will run because not every locale has datepicker
	// configs, so make sure there are English fallbacks for these in the defaults file.
	var dpComputableOptions = {

		buttonText: function(dpOptions) {
			return {
				// the translations sometimes wrongly contain HTML entities
				prev: stripHtmlEntities(dpOptions.prevText),
				next: stripHtmlEntities(dpOptions.nextText),
				today: stripHtmlEntities(dpOptions.currentText)
			};
		},

		// Produces format strings like "MMMM YYYY" -> "September 2014"
		monthYearFormat: function(dpOptions) {
			return dpOptions.showMonthAfterYear ?
				'YYYY[' + dpOptions.yearSuffix + '] MMMM' :
				'MMMM YYYY[' + dpOptions.yearSuffix + ']';
		}

	};

	var momComputableOptions = {

		// Produces format strings like "ddd M/D" -> "Fri 9/15"
		dayOfMonthFormat: function(momOptions, fcOptions) {
			var format = momOptions.longDateFormat('l'); // for the format like "M/D/YYYY"

			// strip the year off the edge, as well as other misc non-whitespace chars
			format = format.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g, '');

			if (fcOptions.isRTL) {
				format += ' ddd'; // for RTL, add day-of-week to end
			}
			else {
				format = 'ddd ' + format; // for LTR, add day-of-week to beginning
			}
			return format;
		},

		// Produces format strings like "h:mma" -> "6:00pm"
		mediumTimeFormat: function(momOptions) { // can't be called `timeFormat` because collides with option
			return momOptions.longDateFormat('LT')
				.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
		},

		// Produces format strings like "h(:mm)a" -> "6pm" / "6:30pm"
		smallTimeFormat: function(momOptions) {
			return momOptions.longDateFormat('LT')
				.replace(':mm', '(:mm)')
				.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
				.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
		},

		// Produces format strings like "h(:mm)t" -> "6p" / "6:30p"
		extraSmallTimeFormat: function(momOptions) {
			return momOptions.longDateFormat('LT')
				.replace(':mm', '(:mm)')
				.replace(/(\Wmm)$/, '($1)') // like above, but for foreign locales
				.replace(/\s*a$/i, 't'); // convert to AM/PM/am/pm to lowercase one-letter. remove any spaces beforehand
		},

		// Produces format strings like "ha" / "H" -> "6pm" / "18"
		hourFormat: function(momOptions) {
			return momOptions.longDateFormat('LT')
				.replace(':mm', '')
				.replace(/(\Wmm)$/, '') // like above, but for foreign locales
				.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
		},

		// Produces format strings like "h:mm" -> "6:30" (with no AM/PM)
		noMeridiemTimeFormat: function(momOptions) {
			return momOptions.longDateFormat('LT')
				.replace(/\s*a$/i, ''); // remove trailing AM/PM
		}

	};


	// options that should be computed off live calendar options (considers override options)
	// TODO: best place for this? related to locale?
	// TODO: flipping text based on isRTL is a bad idea because the CSS `direction` might want to handle it
	var instanceComputableOptions = {

		// Produces format strings for results like "Mo 16"
		smallDayDateFormat: function(options) {
			return options.isRTL ?
				'D dd' :
				'dd D';
		},

		// Produces format strings for results like "Wk 5"
		weekFormat: function(options) {
			return options.isRTL ?
				'w[ ' + options.weekNumberTitle + ']' :
				'[' + options.weekNumberTitle + ' ]w';
		},

		// Produces format strings for results like "Wk5"
		smallWeekFormat: function(options) {
			return options.isRTL ?
				'w[' + options.weekNumberTitle + ']' :
				'[' + options.weekNumberTitle + ']w';
		}

	};

	function populateInstanceComputableOptions(options) {
		$.each(instanceComputableOptions, function(name, func) {
			if (options[name] == null) {
				options[name] = func(options);
			}
		});
	}


	// Returns moment's internal locale data. If doesn't exist, returns English.
	function getMomentLocaleData(localeCode) {
		return moment.localeData(localeCode) || moment.localeData('en');
	}


	// Initialize English by forcing computation of moment-derived options.
	// Also, sets it as the default.
	FC.locale('en', Calendar.englishDefaults);

	;;

	/* Top toolbar area with buttons and title
	----------------------------------------------------------------------------------------------------------------------*/
	// TODO: rename all header-related things to "toolbar"

	function Header(calendar) {
		var t = this;
		
		// exports
		t.render = render;
		t.removeElement = removeElement;
		t.updateTitle = updateTitle;
		t.activateButton = activateButton;
		t.deactivateButton = deactivateButton;
		t.disableButton = disableButton;
		t.enableButton = enableButton;
		t.getViewsWithButtons = getViewsWithButtons;
		t.el = null; // mirrors local `el`
		
		// locals
		var el;
		var viewsWithButtons = [];
		var tm;


		// can be called repeatedly and will rerender
		function render() {
			var options = calendar.options;
			var sections = options.header;

			tm = options.theme ? 'ui' : 'fc';

			if (sections) {
				if (!el) {
					el = this.el = $("<div class='fc-toolbar'/>");
				}
				else {
					el.empty();
				}
				el.append(renderSection('left'))
					.append(renderSection('right'))
					.append(renderSection('center'))
					.append('<div class="fc-clear"/>');
			}
			else {
				removeElement();
			}
		}
		
		
		function removeElement() {
			if (el) {
				el.remove();
				el = t.el = null;
			}
		}
		
		
		function renderSection(position) {
			var sectionEl = $('<div class="fc-' + position + '"/>');
			var options = calendar.options;
			var buttonStr = options.header[position];

			if (buttonStr) {
				$.each(buttonStr.split(' '), function(i) {
					var groupChildren = $();
					var isOnlyButtons = true;
					var groupEl;

					$.each(this.split(','), function(j, buttonName) {
						var customButtonProps;
						var viewSpec;
						var buttonClick;
						var overrideText; // text explicitly set by calendar's constructor options. overcomes icons
						var defaultText;
						var themeIcon;
						var normalIcon;
						var innerHtml;
						var classes;
						var button; // the element

						if (buttonName == 'title') {
							groupChildren = groupChildren.add($('<h2>&nbsp;</h2>')); // we always want it to take up height
							isOnlyButtons = false;
						}
						else {
							if ((customButtonProps = (options.customButtons || {})[buttonName])) {
								buttonClick = function(ev) {
									if (customButtonProps.click) {
										customButtonProps.click.call(button[0], ev);
									}
								};
								overrideText = ''; // icons will override text
								defaultText = customButtonProps.text;
							}
							else if ((viewSpec = calendar.getViewSpec(buttonName))) {
								buttonClick = function() {
									calendar.changeView(buttonName);
								};
								viewsWithButtons.push(buttonName);
								overrideText = viewSpec.buttonTextOverride;
								defaultText = viewSpec.buttonTextDefault;
							}
							else if (calendar[buttonName]) { // a calendar method
								buttonClick = function() {
									calendar[buttonName]();
								};
								overrideText = (calendar.overrides.buttonText || {})[buttonName];
								defaultText = options.buttonText[buttonName]; // everything else is considered default
							}

							if (buttonClick) {

								themeIcon =
									customButtonProps ?
										customButtonProps.themeIcon :
										options.themeButtonIcons[buttonName];

								normalIcon =
									customButtonProps ?
										customButtonProps.icon :
										options.buttonIcons[buttonName];

								if (overrideText) {
									innerHtml = htmlEscape(overrideText);
								}
								else if (themeIcon && options.theme) {
									innerHtml = "<span class='ui-icon ui-icon-" + themeIcon + "'></span>";
								}
								else if (normalIcon && !options.theme) {
									innerHtml = "<span class='fc-icon fc-icon-" + normalIcon + "'></span>";
								}
								else {
									innerHtml = htmlEscape(defaultText);
								}

								classes = [
									'fc-' + buttonName + '-button',
									tm + '-button',
									tm + '-state-default'
								];

								button = $( // type="button" so that it doesn't submit a form
									'<button type="button" class="' + classes.join(' ') + '">' +
										innerHtml +
									'</button>'
									)
									.click(function(ev) {
										// don't process clicks for disabled buttons
										if (!button.hasClass(tm + '-state-disabled')) {

											buttonClick(ev);

											// after the click action, if the button becomes the "active" tab, or disabled,
											// it should never have a hover class, so remove it now.
											if (
												button.hasClass(tm + '-state-active') ||
												button.hasClass(tm + '-state-disabled')
											) {
												button.removeClass(tm + '-state-hover');
											}
										}
									})
									.mousedown(function() {
										// the *down* effect (mouse pressed in).
										// only on buttons that are not the "active" tab, or disabled
										button
											.not('.' + tm + '-state-active')
											.not('.' + tm + '-state-disabled')
											.addClass(tm + '-state-down');
									})
									.mouseup(function() {
										// undo the *down* effect
										button.removeClass(tm + '-state-down');
									})
									.hover(
										function() {
											// the *hover* effect.
											// only on buttons that are not the "active" tab, or disabled
											button
												.not('.' + tm + '-state-active')
												.not('.' + tm + '-state-disabled')
												.addClass(tm + '-state-hover');
										},
										function() {
											// undo the *hover* effect
											button
												.removeClass(tm + '-state-hover')
												.removeClass(tm + '-state-down'); // if mouseleave happens before mouseup
										}
									);

								groupChildren = groupChildren.add(button);
							}
						}
					});

					if (isOnlyButtons) {
						groupChildren
							.first().addClass(tm + '-corner-left').end()
							.last().addClass(tm + '-corner-right').end();
					}

					if (groupChildren.length > 1) {
						groupEl = $('<div/>');
						if (isOnlyButtons) {
							groupEl.addClass('fc-button-group');
						}
						groupEl.append(groupChildren);
						sectionEl.append(groupEl);
					}
					else {
						sectionEl.append(groupChildren); // 1 or 0 children
					}
				});
			}

			return sectionEl;
		}
		
		
		function updateTitle(text) {
			if (el) {
				el.find('h2').text(text);
			}
		}
		
		
		function activateButton(buttonName) {
			if (el) {
				el.find('.fc-' + buttonName + '-button')
					.addClass(tm + '-state-active');
			}
		}
		
		
		function deactivateButton(buttonName) {
			if (el) {
				el.find('.fc-' + buttonName + '-button')
					.removeClass(tm + '-state-active');
			}
		}
		
		
		function disableButton(buttonName) {
			if (el) {
				el.find('.fc-' + buttonName + '-button')
					.prop('disabled', true)
					.addClass(tm + '-state-disabled');
			}
		}
		
		
		function enableButton(buttonName) {
			if (el) {
				el.find('.fc-' + buttonName + '-button')
					.prop('disabled', false)
					.removeClass(tm + '-state-disabled');
			}
		}


		function getViewsWithButtons() {
			return viewsWithButtons;
		}

	}

	;;

	FC.sourceNormalizers = [];
	FC.sourceFetchers = [];

	var ajaxDefaults = {
		dataType: 'json',
		cache: false
	};

	var eventGUID = 1;


	function EventManager() { // assumed to be a calendar
		var t = this;
		
		
		// exports
		t.isFetchNeeded = isFetchNeeded;
		t.fetchEvents = fetchEvents;
		t.fetchEventSources = fetchEventSources;
		t.getEventSources = getEventSources;
		t.getEventSourceById = getEventSourceById;
		t.getEventSourcesByMatchArray = getEventSourcesByMatchArray;
		t.getEventSourcesByMatch = getEventSourcesByMatch;
		t.addEventSource = addEventSource;
		t.removeEventSource = removeEventSource;
		t.removeEventSources = removeEventSources;
		t.updateEvent = updateEvent;
		t.renderEvent = renderEvent;
		t.removeEvents = removeEvents;
		t.clientEvents = clientEvents;
		t.mutateEvent = mutateEvent;
		t.normalizeEventDates = normalizeEventDates;
		t.normalizeEventTimes = normalizeEventTimes;
		
		
		// imports
		var reportEvents = t.reportEvents;
		
		
		// locals
		var stickySource = { events: [] };
		var sources = [ stickySource ];
		var rangeStart, rangeEnd;
		var pendingSourceCnt = 0; // outstanding fetch requests, max one per source
		var cache = []; // holds events that have already been expanded


		$.each(
			(t.options.events ? [ t.options.events ] : []).concat(t.options.eventSources || []),
			function(i, sourceInput) {
				var source = buildEventSource(sourceInput);
				if (source) {
					sources.push(source);
				}
			}
		);
		
		
		
		/* Fetching
		-----------------------------------------------------------------------------*/


		// start and end are assumed to be unzoned
		function isFetchNeeded(start, end) {
			return !rangeStart || // nothing has been fetched yet?
				start < rangeStart || end > rangeEnd; // is part of the new range outside of the old range?
		}
		
		
		function fetchEvents(start, end) {
			rangeStart = start;
			rangeEnd = end;
			fetchEventSources(sources, 'reset');
		}


		// expects an array of event source objects (the originals, not copies)
		// `specialFetchType` is an optimization parameter that affects purging of the event cache.
		function fetchEventSources(specificSources, specialFetchType) {
			var i, source;

			if (specialFetchType === 'reset') {
				cache = [];
			}
			else if (specialFetchType !== 'add') {
				cache = excludeEventsBySources(cache, specificSources);
			}

			for (i = 0; i < specificSources.length; i++) {
				source = specificSources[i];

				// already-pending sources have already been accounted for in pendingSourceCnt
				if (source._status !== 'pending') {
					pendingSourceCnt++;
				}

				source._fetchId = (source._fetchId || 0) + 1;
				source._status = 'pending';
			}

			for (i = 0; i < specificSources.length; i++) {
				source = specificSources[i];

				tryFetchEventSource(source, source._fetchId);
			}
		}


		// fetches an event source and processes its result ONLY if it is still the current fetch.
		// caller is responsible for incrementing pendingSourceCnt first.
		function tryFetchEventSource(source, fetchId) {
			_fetchEventSource(source, function(eventInputs) {
				var isArraySource = $.isArray(source.events);
				var i, eventInput;
				var abstractEvent;

				if (
					// is this the source's most recent fetch?
					// if not, rely on an upcoming fetch of this source to decrement pendingSourceCnt
					fetchId === source._fetchId &&
					// event source no longer valid?
					source._status !== 'rejected'
				) {
					source._status = 'resolved';

					if (eventInputs) {
						for (i = 0; i < eventInputs.length; i++) {
							eventInput = eventInputs[i];

							if (isArraySource) { // array sources have already been convert to Event Objects
								abstractEvent = eventInput;
							}
							else {
								abstractEvent = buildEventFromInput(eventInput, source);
							}

							if (abstractEvent) { // not false (an invalid event)
								cache.push.apply(
									cache,
									expandEvent(abstractEvent) // add individual expanded events to the cache
								);
							}
						}
					}

					decrementPendingSourceCnt();
				}
			});
		}


		function rejectEventSource(source) {
			var wasPending = source._status === 'pending';

			source._status = 'rejected';

			if (wasPending) {
				decrementPendingSourceCnt();
			}
		}


		function decrementPendingSourceCnt() {
			pendingSourceCnt--;
			if (!pendingSourceCnt) {
				reportEvents(cache);
			}
		}
		
		
		function _fetchEventSource(source, callback) {
			var i;
			var fetchers = FC.sourceFetchers;
			var res;

			for (i=0; i<fetchers.length; i++) {
				res = fetchers[i].call(
					t, // this, the Calendar object
					source,
					rangeStart.clone(),
					rangeEnd.clone(),
					t.options.timezone,
					callback
				);

				if (res === true) {
					// the fetcher is in charge. made its own async request
					return;
				}
				else if (typeof res == 'object') {
					// the fetcher returned a new source. process it
					_fetchEventSource(res, callback);
					return;
				}
			}

			var events = source.events;
			if (events) {
				if ($.isFunction(events)) {
					t.pushLoading();
					events.call(
						t, // this, the Calendar object
						rangeStart.clone(),
						rangeEnd.clone(),
						t.options.timezone,
						function(events) {
							callback(events);
							t.popLoading();
						}
					);
				}
				else if ($.isArray(events)) {
					callback(events);
				}
				else {
					callback();
				}
			}else{
				var url = source.url;
				if (url) {
					var success = source.success;
					var error = source.error;
					var complete = source.complete;

					// retrieve any outbound GET/POST $.ajax data from the options
					var customData;
					if ($.isFunction(source.data)) {
						// supplied as a function that returns a key/value object
						customData = source.data();
					}
					else {
						// supplied as a straight key/value object
						customData = source.data;
					}

					// use a copy of the custom data so we can modify the parameters
					// and not affect the passed-in object.
					var data = $.extend({}, customData || {});

					var startParam = firstDefined(source.startParam, t.options.startParam);
					var endParam = firstDefined(source.endParam, t.options.endParam);
					var timezoneParam = firstDefined(source.timezoneParam, t.options.timezoneParam);

					if (startParam) {
						data[startParam] = rangeStart.format();
					}
					if (endParam) {
						data[endParam] = rangeEnd.format();
					}
					if (t.options.timezone && t.options.timezone != 'local') {
						data[timezoneParam] = t.options.timezone;
					}

					t.pushLoading();
					$.ajax($.extend({}, ajaxDefaults, source, {
						data: data,
						success: function(events) {
							events = events || [];
							var res = applyAll(success, this, arguments);
							if ($.isArray(res)) {
								events = res;
							}
							callback(events);
						},
						error: function() {
							applyAll(error, this, arguments);
							callback();
						},
						complete: function() {
							applyAll(complete, this, arguments);
							t.popLoading();
						}
					}));
				}else{
					callback();
				}
			}
		}
		
		
		
		/* Sources
		-----------------------------------------------------------------------------*/


		function addEventSource(sourceInput) {
			var source = buildEventSource(sourceInput);
			if (source) {
				sources.push(source);
				fetchEventSources([ source ], 'add'); // will eventually call reportEvents
			}
		}


		function buildEventSource(sourceInput) { // will return undefined if invalid source
			var normalizers = FC.sourceNormalizers;
			var source;
			var i;

			if ($.isFunction(sourceInput) || $.isArray(sourceInput)) {
				source = { events: sourceInput };
			}
			else if (typeof sourceInput === 'string') {
				source = { url: sourceInput };
			}
			else if (typeof sourceInput === 'object') {
				source = $.extend({}, sourceInput); // shallow copy
			}

			if (source) {

				// TODO: repeat code, same code for event classNames
				if (source.className) {
					if (typeof source.className === 'string') {
						source.className = source.className.split(/\s+/);
					}
					// otherwise, assumed to be an array
				}
				else {
					source.className = [];
				}

				// for array sources, we convert to standard Event Objects up front
				if ($.isArray(source.events)) {
					source.origArray = source.events; // for removeEventSource
					source.events = $.map(source.events, function(eventInput) {
						return buildEventFromInput(eventInput, source);
					});
				}

				for (i=0; i<normalizers.length; i++) {
					normalizers[i].call(t, source);
				}

				return source;
			}
		}


		function removeEventSource(matchInput) {
			removeSpecificEventSources(
				getEventSourcesByMatch(matchInput)
			);
		}


		// if called with no arguments, removes all.
		function removeEventSources(matchInputs) {
			if (matchInputs == null) {
				removeSpecificEventSources(sources, true); // isAll=true
			}
			else {
				removeSpecificEventSources(
					getEventSourcesByMatchArray(matchInputs)
				);
			}
		}


		function removeSpecificEventSources(targetSources, isAll) {
			var i;

			// cancel pending requests
			for (i = 0; i < targetSources.length; i++) {
				rejectEventSource(targetSources[i]);
			}

			if (isAll) { // an optimization
				sources = [];
				cache = [];
			}
			else {
				// remove from persisted source list
				sources = $.grep(sources, function(source) {
					for (i = 0; i < targetSources.length; i++) {
						if (source === targetSources[i]) {
							return false; // exclude
						}
					}
					return true; // include
				});

				cache = excludeEventsBySources(cache, targetSources);
			}

			reportEvents(cache);
		}


		function getEventSources() {
			return sources.slice(1); // returns a shallow copy of sources with stickySource removed
		}


		function getEventSourceById(id) {
			return $.grep(sources, function(source) {
				return source.id && source.id === id;
			})[0];
		}


		// like getEventSourcesByMatch, but accepts multple match criteria (like multiple IDs)
		function getEventSourcesByMatchArray(matchInputs) {

			// coerce into an array
			if (!matchInputs) {
				matchInputs = [];
			}
			else if (!$.isArray(matchInputs)) {
				matchInputs = [ matchInputs ];
			}

			var matchingSources = [];
			var i;

			// resolve raw inputs to real event source objects
			for (i = 0; i < matchInputs.length; i++) {
				matchingSources.push.apply( // append
					matchingSources,
					getEventSourcesByMatch(matchInputs[i])
				);
			}

			return matchingSources;
		}


		// matchInput can either by a real event source object, an ID, or the function/URL for the source.
		// returns an array of matching source objects.
		function getEventSourcesByMatch(matchInput) {
			var i, source;

			// given an proper event source object
			for (i = 0; i < sources.length; i++) {
				source = sources[i];
				if (source === matchInput) {
					return [ source ];
				}
			}

			// an ID match
			source = getEventSourceById(matchInput);
			if (source) {
				return [ source ];
			}

			return $.grep(sources, function(source) {
				return isSourcesEquivalent(matchInput, source);
			});
		}


		function isSourcesEquivalent(source1, source2) {
			return source1 && source2 && getSourcePrimitive(source1) == getSourcePrimitive(source2);
		}


		function getSourcePrimitive(source) {
			return (
				(typeof source === 'object') ? // a normalized event source?
					(source.origArray || source.googleCalendarId || source.url || source.events) : // get the primitive
					null
			) ||
			source; // the given argument *is* the primitive
		}


		// util
		// returns a filtered array without events that are part of any of the given sources
		function excludeEventsBySources(specificEvents, specificSources) {
			return $.grep(specificEvents, function(event) {
				for (var i = 0; i < specificSources.length; i++) {
					if (event.source === specificSources[i]) {
						return false; // exclude
					}
				}
				return true; // keep
			});
		}
		
		
		
		/* Manipulation
		-----------------------------------------------------------------------------*/


		// Only ever called from the externally-facing API
		function updateEvent(event) {

			// massage start/end values, even if date string values
			event.start = t.moment(event.start);
			if (event.end) {
				event.end = t.moment(event.end);
			}
			else {
				event.end = null;
			}

			mutateEvent(event, getMiscEventProps(event)); // will handle start/end/allDay normalization
			reportEvents(cache); // reports event modifications (so we can redraw)
		}


		// Returns a hash of misc event properties that should be copied over to related events.
		function getMiscEventProps(event) {
			var props = {};

			$.each(event, function(name, val) {
				if (isMiscEventPropName(name)) {
					if (val !== undefined && isAtomic(val)) { // a defined non-object
						props[name] = val;
					}
				}
			});

			return props;
		}

		// non-date-related, non-id-related, non-secret
		function isMiscEventPropName(name) {
			return !/^_|^(id|allDay|start|end)$/.test(name);
		}

		
		// returns the expanded events that were created
		function renderEvent(eventInput, stick) {
			var abstractEvent = buildEventFromInput(eventInput);
			var events;
			var i, event;

			if (abstractEvent) { // not false (a valid input)
				events = expandEvent(abstractEvent);

				for (i = 0; i < events.length; i++) {
					event = events[i];

					if (!event.source) {
						if (stick) {
							stickySource.events.push(event);
							event.source = stickySource;
						}
						cache.push(event);
					}
				}

				reportEvents(cache);

				return events;
			}

			return [];
		}
		
		
		function removeEvents(filter) {
			var eventID;
			var i;

			if (filter == null) { // null or undefined. remove all events
				filter = function() { return true; }; // will always match
			}
			else if (!$.isFunction(filter)) { // an event ID
				eventID = filter + '';
				filter = function(event) {
					return event._id == eventID;
				};
			}

			// Purge event(s) from our local cache
			cache = $.grep(cache, filter, true); // inverse=true

			// Remove events from array sources.
			// This works because they have been converted to official Event Objects up front.
			// (and as a result, event._id has been calculated).
			for (i=0; i<sources.length; i++) {
				if ($.isArray(sources[i].events)) {
					sources[i].events = $.grep(sources[i].events, filter, true);
				}
			}

			reportEvents(cache);
		}

		
		function clientEvents(filter) {
			if ($.isFunction(filter)) {
				return $.grep(cache, filter);
			}
			else if (filter != null) { // not null, not undefined. an event ID
				filter += '';
				return $.grep(cache, function(e) {
					return e._id == filter;
				});
			}
			return cache; // else, return all
		}


		// Makes sure all array event sources have their internal event objects
		// converted over to the Calendar's current timezone.
		t.rezoneArrayEventSources = function() {
			var i;
			var events;
			var j;

			for (i = 0; i < sources.length; i++) {
				events = sources[i].events;
				if ($.isArray(events)) {

					for (j = 0; j < events.length; j++) {
						rezoneEventDates(events[j]);
					}
				}
			}
		};

		function rezoneEventDates(event) {
			event.start = t.moment(event.start);
			if (event.end) {
				event.end = t.moment(event.end);
			}
			backupEventDates(event);
		}
		
		
		/* Event Normalization
		-----------------------------------------------------------------------------*/


		// Given a raw object with key/value properties, returns an "abstract" Event object.
		// An "abstract" event is an event that, if recurring, will not have been expanded yet.
		// Will return `false` when input is invalid.
		// `source` is optional
		function buildEventFromInput(input, source) {
			var out = {};
			var start, end;
			var allDay;

			if (t.options.eventDataTransform) {
				input = t.options.eventDataTransform(input);
			}
			if (source && source.eventDataTransform) {
				input = source.eventDataTransform(input);
			}

			// Copy all properties over to the resulting object.
			// The special-case properties will be copied over afterwards.
			$.extend(out, input);

			if (source) {
				out.source = source;
			}

			out._id = input._id || (input.id === undefined ? '_fc' + eventGUID++ : input.id + '');

			if (input.className) {
				if (typeof input.className == 'string') {
					out.className = input.className.split(/\s+/);
				}
				else { // assumed to be an array
					out.className = input.className;
				}
			}
			else {
				out.className = [];
			}

			start = input.start || input.date; // "date" is an alias for "start"
			end = input.end;

			// parse as a time (Duration) if applicable
			if (isTimeString(start)) {
				start = moment.duration(start);
			}
			if (isTimeString(end)) {
				end = moment.duration(end);
			}

			if (input.dow || moment.isDuration(start) || moment.isDuration(end)) {

				// the event is "abstract" (recurring) so don't calculate exact start/end dates just yet
				out.start = start ? moment.duration(start) : null; // will be a Duration or null
				out.end = end ? moment.duration(end) : null; // will be a Duration or null
				out._recurring = true; // our internal marker
			}
			else {

				if (start) {
					start = t.moment(start);
					if (!start.isValid()) {
						return false;
					}
				}

				if (end) {
					end = t.moment(end);
					if (!end.isValid()) {
						end = null; // let defaults take over
					}
				}

				allDay = input.allDay;
				if (allDay === undefined) { // still undefined? fallback to default
					allDay = firstDefined(
						source ? source.allDayDefault : undefined,
						t.options.allDayDefault
					);
					// still undefined? normalizeEventDates will calculate it
				}

				assignDatesToEvent(start, end, allDay, out);
			}

			t.normalizeEvent(out); // hook for external use. a prototype method

			return out;
		}
		t.buildEventFromInput = buildEventFromInput;


		// Normalizes and assigns the given dates to the given partially-formed event object.
		// NOTE: mutates the given start/end moments. does not make a copy.
		function assignDatesToEvent(start, end, allDay, event) {
			event.start = start;
			event.end = end;
			event.allDay = allDay;
			normalizeEventDates(event);
			backupEventDates(event);
		}


		// Ensures proper values for allDay/start/end. Accepts an Event object, or a plain object with event-ish properties.
		// NOTE: Will modify the given object.
		function normalizeEventDates(eventProps) {

			normalizeEventTimes(eventProps);

			if (eventProps.end && !eventProps.end.isAfter(eventProps.start)) {
				eventProps.end = null;
			}

			if (!eventProps.end) {
				if (t.options.forceEventDuration) {
					eventProps.end = t.getDefaultEventEnd(eventProps.allDay, eventProps.start);
				}
				else {
					eventProps.end = null;
				}
			}
		}


		// Ensures the allDay property exists and the timeliness of the start/end dates are consistent
		function normalizeEventTimes(eventProps) {
			if (eventProps.allDay == null) {
				eventProps.allDay = !(eventProps.start.hasTime() || (eventProps.end && eventProps.end.hasTime()));
			}

			if (eventProps.allDay) {
				eventProps.start.stripTime();
				if (eventProps.end) {
					// TODO: consider nextDayThreshold here? If so, will require a lot of testing and adjustment
					eventProps.end.stripTime();
				}
			}
			else {
				if (!eventProps.start.hasTime()) {
					eventProps.start = t.applyTimezone(eventProps.start.time(0)); // will assign a 00:00 time
				}
				if (eventProps.end && !eventProps.end.hasTime()) {
					eventProps.end = t.applyTimezone(eventProps.end.time(0)); // will assign a 00:00 time
				}
			}
		}


		// If the given event is a recurring event, break it down into an array of individual instances.
		// If not a recurring event, return an array with the single original event.
		// If given a falsy input (probably because of a failed buildEventFromInput call), returns an empty array.
		// HACK: can override the recurring window by providing custom rangeStart/rangeEnd (for businessHours).
		function expandEvent(abstractEvent, _rangeStart, _rangeEnd) {
			var events = [];
			var dowHash;
			var dow;
			var i;
			var date;
			var startTime, endTime;
			var start, end;
			var event;

			_rangeStart = _rangeStart || rangeStart;
			_rangeEnd = _rangeEnd || rangeEnd;

			if (abstractEvent) {
				if (abstractEvent._recurring) {

					// make a boolean hash as to whether the event occurs on each day-of-week
					if ((dow = abstractEvent.dow)) {
						dowHash = {};
						for (i = 0; i < dow.length; i++) {
							dowHash[dow[i]] = true;
						}
					}

					// iterate through every day in the current range
					date = _rangeStart.clone().stripTime(); // holds the date of the current day
					while (date.isBefore(_rangeEnd)) {

						if (!dowHash || dowHash[date.day()]) { // if everyday, or this particular day-of-week

							startTime = abstractEvent.start; // the stored start and end properties are times (Durations)
							endTime = abstractEvent.end; // "
							start = date.clone();
							end = null;

							if (startTime) {
								start = start.time(startTime);
							}
							if (endTime) {
								end = date.clone().time(endTime);
							}

							event = $.extend({}, abstractEvent); // make a copy of the original
							assignDatesToEvent(
								start, end,
								!startTime && !endTime, // allDay?
								event
							);
							events.push(event);
						}

						date.add(1, 'days');
					}
				}
				else {
					events.push(abstractEvent); // return the original event. will be a one-item array
				}
			}

			return events;
		}
		t.expandEvent = expandEvent;



		/* Event Modification Math
		-----------------------------------------------------------------------------------------*/


		// Modifies an event and all related events by applying the given properties.
		// Special date-diffing logic is used for manipulation of dates.
		// If `props` does not contain start/end dates, the updated values are assumed to be the event's current start/end.
		// All date comparisons are done against the event's pristine _start and _end dates.
		// Returns an object with delta information and a function to undo all operations.
		// For making computations in a granularity greater than day/time, specify largeUnit.
		// NOTE: The given `newProps` might be mutated for normalization purposes.
		function mutateEvent(event, newProps, largeUnit) {
			var miscProps = {};
			var oldProps;
			var clearEnd;
			var startDelta;
			var endDelta;
			var durationDelta;
			var undoFunc;

			// diffs the dates in the appropriate way, returning a duration
			function diffDates(date1, date0) { // date1 - date0
				if (largeUnit) {
					return diffByUnit(date1, date0, largeUnit);
				}
				else if (newProps.allDay) {
					return diffDay(date1, date0);
				}
				else {
					return diffDayTime(date1, date0);
				}
			}

			newProps = newProps || {};

			// normalize new date-related properties
			if (!newProps.start) {
				newProps.start = event.start.clone();
			}
			if (newProps.end === undefined) {
				newProps.end = event.end ? event.end.clone() : null;
			}
			if (newProps.allDay == null) { // is null or undefined?
				newProps.allDay = event.allDay;
			}
			normalizeEventDates(newProps);

			// create normalized versions of the original props to compare against
			// need a real end value, for diffing
			oldProps = {
				start: event._start.clone(),
				end: event._end ? event._end.clone() : t.getDefaultEventEnd(event._allDay, event._start),
				allDay: newProps.allDay // normalize the dates in the same regard as the new properties
			};
			normalizeEventDates(oldProps);

			// need to clear the end date if explicitly changed to null
			clearEnd = event._end !== null && newProps.end === null;

			// compute the delta for moving the start date
			startDelta = diffDates(newProps.start, oldProps.start);

			// compute the delta for moving the end date
			if (newProps.end) {
				endDelta = diffDates(newProps.end, oldProps.end);
				durationDelta = endDelta.subtract(startDelta);
			}
			else {
				durationDelta = null;
			}

			// gather all non-date-related properties
			$.each(newProps, function(name, val) {
				if (isMiscEventPropName(name)) {
					if (val !== undefined) {
						miscProps[name] = val;
					}
				}
			});

			// apply the operations to the event and all related events
			undoFunc = mutateEvents(
				clientEvents(event._id), // get events with this ID
				clearEnd,
				newProps.allDay,
				startDelta,
				durationDelta,
				miscProps
			);

			return {
				dateDelta: startDelta,
				durationDelta: durationDelta,
				undo: undoFunc
			};
		}


		// Modifies an array of events in the following ways (operations are in order):
		// - clear the event's `end`
		// - convert the event to allDay
		// - add `dateDelta` to the start and end
		// - add `durationDelta` to the event's duration
		// - assign `miscProps` to the event
		//
		// Returns a function that can be called to undo all the operations.
		//
		// TODO: don't use so many closures. possible memory issues when lots of events with same ID.
		//
		function mutateEvents(events, clearEnd, allDay, dateDelta, durationDelta, miscProps) {
			var isAmbigTimezone = t.getIsAmbigTimezone();
			var undoFunctions = [];

			// normalize zero-length deltas to be null
			if (dateDelta && !dateDelta.valueOf()) { dateDelta = null; }
			if (durationDelta && !durationDelta.valueOf()) { durationDelta = null; }

			$.each(events, function(i, event) {
				var oldProps;
				var newProps;

				// build an object holding all the old values, both date-related and misc.
				// for the undo function.
				oldProps = {
					start: event.start.clone(),
					end: event.end ? event.end.clone() : null,
					allDay: event.allDay
				};
				$.each(miscProps, function(name) {
					oldProps[name] = event[name];
				});

				// new date-related properties. work off the original date snapshot.
				// ok to use references because they will be thrown away when backupEventDates is called.
				newProps = {
					start: event._start,
					end: event._end,
					allDay: allDay // normalize the dates in the same regard as the new properties
				};
				normalizeEventDates(newProps); // massages start/end/allDay

				// strip or ensure the end date
				if (clearEnd) {
					newProps.end = null;
				}
				else if (durationDelta && !newProps.end) { // the duration translation requires an end date
					newProps.end = t.getDefaultEventEnd(newProps.allDay, newProps.start);
				}

				if (dateDelta) {
					newProps.start.add(dateDelta);
					if (newProps.end) {
						newProps.end.add(dateDelta);
					}
				}

				if (durationDelta) {
					newProps.end.add(durationDelta); // end already ensured above
				}

				// if the dates have changed, and we know it is impossible to recompute the
				// timezone offsets, strip the zone.
				if (
					isAmbigTimezone &&
					!newProps.allDay &&
					(dateDelta || durationDelta)
				) {
					newProps.start.stripZone();
					if (newProps.end) {
						newProps.end.stripZone();
					}
				}

				$.extend(event, miscProps, newProps); // copy over misc props, then date-related props
				backupEventDates(event); // regenerate internal _start/_end/_allDay

				undoFunctions.push(function() {
					$.extend(event, oldProps);
					backupEventDates(event); // regenerate internal _start/_end/_allDay
				});
			});

			return function() {
				for (var i = 0; i < undoFunctions.length; i++) {
					undoFunctions[i]();
				}
			};
		}


		/* Overlapping / Constraining
		-----------------------------------------------------------------------------------------*/

		t.isEventSpanAllowed = isEventSpanAllowed;
		t.isExternalSpanAllowed = isExternalSpanAllowed;
		t.isSelectionSpanAllowed = isSelectionSpanAllowed;


		// Determines if the given event can be relocated to the given span (unzoned start/end with other misc data)
		function isEventSpanAllowed(span, event) {
			var source = event.source || {};
			var constraint = firstDefined(
				event.constraint,
				source.constraint,
				t.options.eventConstraint
			);
			var overlap = firstDefined(
				event.overlap,
				source.overlap,
				t.options.eventOverlap
			);
			return isSpanAllowed(span, constraint, overlap, event);
		}


		// Determines if an external event can be relocated to the given span (unzoned start/end with other misc data)
		function isExternalSpanAllowed(eventSpan, eventLocation, eventProps) {
			var eventInput;
			var event;

			// note: very similar logic is in View's reportExternalDrop
			if (eventProps) {
				eventInput = $.extend({}, eventProps, eventLocation);
				event = expandEvent(buildEventFromInput(eventInput))[0];
			}

			if (event) {
				return isEventSpanAllowed(eventSpan, event);
			}
			else { // treat it as a selection

				return isSelectionSpanAllowed(eventSpan);
			}
		}


		// Determines the given span (unzoned start/end with other misc data) can be selected.
		function isSelectionSpanAllowed(span) {
			return isSpanAllowed(span, t.options.selectConstraint, t.options.selectOverlap);
		}


		// Returns true if the given span (caused by an event drop/resize or a selection) is allowed to exist
		// according to the constraint/overlap settings.
		// `event` is not required if checking a selection.
		function isSpanAllowed(span, constraint, overlap, event) {
			var constraintEvents;
			var anyContainment;
			var peerEvents;
			var i, peerEvent;
			var peerOverlap;

			// the range must be fully contained by at least one of produced constraint events
			if (constraint != null) {

				// not treated as an event! intermediate data structure
				// TODO: use ranges in the future
				constraintEvents = constraintToEvents(constraint);

				anyContainment = false;
				for (i = 0; i < constraintEvents.length; i++) {
					if (t.spanContainsSpan(constraintEvents[i], span)) {
						anyContainment = true;
						break;
					}
				}

				if (!anyContainment) {
					return false;
				}
			}

			peerEvents = t.getPeerEvents(span, event);

			for (i = 0; i < peerEvents.length; i++)  {
				peerEvent = peerEvents[i];

				// there needs to be an actual intersection before disallowing anything
				if (eventIntersectsRange(peerEvent, span)) {

					// evaluate overlap for the given range and short-circuit if necessary
					if (overlap === false) {
						return false;
					}
					// if the event's overlap is a test function, pass the peer event in question as the first param
					else if (typeof overlap === 'function' && !overlap(peerEvent, event)) {
						return false;
					}

					// if we are computing if the given range is allowable for an event, consider the other event's
					// EventObject-specific or Source-specific `overlap` property
					if (event) {
						peerOverlap = firstDefined(
							peerEvent.overlap,
							(peerEvent.source || {}).overlap
							// we already considered the global `eventOverlap`
						);
						if (peerOverlap === false) {
							return false;
						}
						// if the peer event's overlap is a test function, pass the subject event as the first param
						if (typeof peerOverlap === 'function' && !peerOverlap(event, peerEvent)) {
							return false;
						}
					}
				}
			}

			return true;
		}


		// Given an event input from the API, produces an array of event objects. Possible event inputs:
		// 'businessHours'
		// An event ID (number or string)
		// An object with specific start/end dates or a recurring event (like what businessHours accepts)
		function constraintToEvents(constraintInput) {

			if (constraintInput === 'businessHours') {
				return t.getCurrentBusinessHourEvents();
			}

			if (typeof constraintInput === 'object') {
				return expandEvent(buildEventFromInput(constraintInput));
			}

			return clientEvents(constraintInput); // probably an ID
		}


		// Does the event's date range intersect with the given range?
		// start/end already assumed to have stripped zones :(
		function eventIntersectsRange(event, range) {
			var eventStart = event.start.clone().stripZone();
			var eventEnd = t.getEventEnd(event).stripZone();

			return range.start < eventEnd && range.end > eventStart;
		}


		t.getEventCache = function() {
			return cache;
		};

	}


	// hook for external libs to manipulate event properties upon creation.
	// should manipulate the event in-place.
	Calendar.prototype.normalizeEvent = function(event) {
	};


	// Does the given span (start, end, and other location information)
	// fully contain the other?
	Calendar.prototype.spanContainsSpan = function(outerSpan, innerSpan) {
		var eventStart = outerSpan.start.clone().stripZone();
		var eventEnd = this.getEventEnd(outerSpan).stripZone();

		return innerSpan.start >= eventStart && innerSpan.end <= eventEnd;
	};


	// Returns a list of events that the given event should be compared against when being considered for a move to
	// the specified span. Attached to the Calendar's prototype because EventManager is a mixin for a Calendar.
	Calendar.prototype.getPeerEvents = function(span, event) {
		var cache = this.getEventCache();
		var peerEvents = [];
		var i, otherEvent;

		for (i = 0; i < cache.length; i++) {
			otherEvent = cache[i];
			if (
				!event ||
				event._id !== otherEvent._id // don't compare the event to itself or other related [repeating] events
			) {
				peerEvents.push(otherEvent);
			}
		}

		return peerEvents;
	};


	// updates the "backup" properties, which are preserved in order to compute diffs later on.
	function backupEventDates(event) {
		event._allDay = event.allDay;
		event._start = event.start.clone();
		event._end = event.end ? event.end.clone() : null;
	}


	/* Business Hours
	-----------------------------------------------------------------------------------------*/

	var BUSINESS_HOUR_EVENT_DEFAULTS = {
		id: '_fcBusinessHours', // will relate events from different calls to expandEvent
		start: '09:00',
		end: '17:00',
		dow: [ 1, 2, 3, 4, 5 ], // monday - friday
		rendering: 'inverse-background'
		// classNames are defined in businessHoursSegClasses
	};

	// Return events objects for business hours within the current view.
	// Abuse of our event system :(
	Calendar.prototype.getCurrentBusinessHourEvents = function(wholeDay) {
		return this.computeBusinessHourEvents(wholeDay, this.options.businessHours);
	};

	// Given a raw input value from options, return events objects for business hours within the current view.
	Calendar.prototype.computeBusinessHourEvents = function(wholeDay, input) {
		if (input === true) {
			return this.expandBusinessHourEvents(wholeDay, [ {} ]);
		}
		else if ($.isPlainObject(input)) {
			return this.expandBusinessHourEvents(wholeDay, [ input ]);
		}
		else if ($.isArray(input)) {
			return this.expandBusinessHourEvents(wholeDay, input, true);
		}
		else {
			return [];
		}
	};

	// inputs expected to be an array of objects.
	// if ignoreNoDow is true, will ignore entries that don't specify a day-of-week (dow) key.
	Calendar.prototype.expandBusinessHourEvents = function(wholeDay, inputs, ignoreNoDow) {
		var view = this.getView();
		var events = [];
		var i, input;

		for (i = 0; i < inputs.length; i++) {
			input = inputs[i];

			if (ignoreNoDow && !input.dow) {
				continue;
			}

			// give defaults. will make a copy
			input = $.extend({}, BUSINESS_HOUR_EVENT_DEFAULTS, input);

			// if a whole-day series is requested, clear the start/end times
			if (wholeDay) {
				input.start = null;
				input.end = null;
			}

			events.push.apply(events, // append
				this.expandEvent(
					this.buildEventFromInput(input),
					view.start,
					view.end
				)
			);
		}

		return events;
	};

	;;

	/* An abstract class for the "basic" views, as well as month view. Renders one or more rows of day cells.
	----------------------------------------------------------------------------------------------------------------------*/
	// It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.
	// It is responsible for managing width/height.

	var BasicView = FC.BasicView = View.extend({

		scroller: null,

		dayGridClass: DayGrid, // class the dayGrid will be instantiated from (overridable by subclasses)
		dayGrid: null, // the main subcomponent that does most of the heavy lifting

		dayNumbersVisible: false, // display day numbers on each day cell?
		colWeekNumbersVisible: false, // display week numbers along the side?
		cellWeekNumbersVisible: false, // display week numbers in day cell?

		weekNumberWidth: null, // width of all the week-number cells running down the side

		headContainerEl: null, // div that hold's the dayGrid's rendered date header
		headRowEl: null, // the fake row element of the day-of-week header


		initialize: function() {
			this.dayGrid = this.instantiateDayGrid();

			this.scroller = new Scroller({
				overflowX: 'hidden',
				overflowY: 'auto'
			});
		},


		// Generates the DayGrid object this view needs. Draws from this.dayGridClass
		instantiateDayGrid: function() {
			// generate a subclass on the fly with BasicView-specific behavior
			// TODO: cache this subclass
			var subclass = this.dayGridClass.extend(basicDayGridMethods);

			return new subclass(this);
		},


		// Sets the display range and computes all necessary dates
		setRange: function(range) {
			View.prototype.setRange.call(this, range); // call the super-method

			this.dayGrid.breakOnWeeks = /year|month|week/.test(this.intervalUnit); // do before setRange
			this.dayGrid.setRange(range);
		},


		// Compute the value to feed into setRange. Overrides superclass.
		computeRange: function(date) {
			var range = View.prototype.computeRange.call(this, date); // get value from the super-method

			// year and month views should be aligned with weeks. this is already done for week
			if (/year|month/.test(range.intervalUnit)) {
				range.start.startOf('week');
				range.start = this.skipHiddenDays(range.start);

				// make end-of-week if not already
				if (range.end.weekday()) {
					range.end.add(1, 'week').startOf('week');
					range.end = this.skipHiddenDays(range.end, -1, true); // exclusively move backwards
				}
			}

			return range;
		},


		// Renders the view into `this.el`, which should already be assigned
		renderDates: function() {

			this.dayNumbersVisible = this.dayGrid.rowCnt > 1; // TODO: make grid responsible
			if (this.opt('weekNumbers')) {
				if (this.opt('weekNumbersWithinDays')) {
					this.cellWeekNumbersVisible = true;
					this.colWeekNumbersVisible = false;
				}
				else {
					this.cellWeekNumbersVisible = false;
					this.colWeekNumbersVisible = true;
				};
			}
			this.dayGrid.numbersVisible = this.dayNumbersVisible ||
				this.cellWeekNumbersVisible || this.colWeekNumbersVisible;

			this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml());
			this.renderHead();

			this.scroller.render();
			var dayGridContainerEl = this.scroller.el.addClass('fc-day-grid-container');
			var dayGridEl = $('<div class="fc-day-grid" />').appendTo(dayGridContainerEl);
			this.el.find('.fc-body > tr > td').append(dayGridContainerEl);

			this.dayGrid.setElement(dayGridEl);
			this.dayGrid.renderDates(this.hasRigidRows());
		},


		// render the day-of-week headers
		renderHead: function() {
			this.headContainerEl =
				this.el.find('.fc-head-container')
					.html(this.dayGrid.renderHeadHtml());
			this.headRowEl = this.headContainerEl.find('.fc-row');
		},


		// Unrenders the content of the view. Since we haven't separated skeleton rendering from date rendering,
		// always completely kill the dayGrid's rendering.
		unrenderDates: function() {
			this.dayGrid.unrenderDates();
			this.dayGrid.removeElement();
			this.scroller.destroy();
		},


		renderBusinessHours: function() {
			this.dayGrid.renderBusinessHours();
		},


		unrenderBusinessHours: function() {
			this.dayGrid.unrenderBusinessHours();
		},


		// Builds the HTML skeleton for the view.
		// The day-grid component will render inside of a container defined by this HTML.
		renderSkeletonHtml: function() {
			return '' +
				'<table>' +
					'<thead class="fc-head">' +
						'<tr>' +
							'<td class="fc-head-container ' + this.widgetHeaderClass + '"></td>' +
						'</tr>' +
					'</thead>' +
					'<tbody class="fc-body">' +
						'<tr>' +
							'<td class="' + this.widgetContentClass + '"></td>' +
						'</tr>' +
					'</tbody>' +
				'</table>';
		},


		// Generates an HTML attribute string for setting the width of the week number column, if it is known
		weekNumberStyleAttr: function() {
			if (this.weekNumberWidth !== null) {
				return 'style="width:' + this.weekNumberWidth + 'px"';
			}
			return '';
		},


		// Determines whether each row should have a constant height
		hasRigidRows: function() {
			var eventLimit = this.opt('eventLimit');
			return eventLimit && typeof eventLimit !== 'number';
		},


		/* Dimensions
		------------------------------------------------------------------------------------------------------------------*/


		// Refreshes the horizontal dimensions of the view
		updateWidth: function() {
			if (this.colWeekNumbersVisible) {
				// Make sure all week number cells running down the side have the same width.
				// Record the width for cells created later.
				this.weekNumberWidth = matchCellWidths(
					this.el.find('.fc-week-number')
				);
			}
		},


		// Adjusts the vertical dimensions of the view to the specified values
		setHeight: function(totalHeight, isAuto) {
			var eventLimit = this.opt('eventLimit');
			var scrollerHeight;
			var scrollbarWidths;

			// reset all heights to be natural
			this.scroller.clear();
			uncompensateScroll(this.headRowEl);

			this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed

			// is the event limit a constant level number?
			if (eventLimit && typeof eventLimit === 'number') {
				this.dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
			}

			// distribute the height to the rows
			// (totalHeight is a "recommended" value if isAuto)
			scrollerHeight = this.computeScrollerHeight(totalHeight);
			this.setGridHeight(scrollerHeight, isAuto);

			// is the event limit dynamically calculated?
			if (eventLimit && typeof eventLimit !== 'number') {
				this.dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
			}

			if (!isAuto) { // should we force dimensions of the scroll container?

				this.scroller.setHeight(scrollerHeight);
				scrollbarWidths = this.scroller.getScrollbarWidths();

				if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?

					compensateScroll(this.headRowEl, scrollbarWidths);

					// doing the scrollbar compensation might have created text overflow which created more height. redo
					scrollerHeight = this.computeScrollerHeight(totalHeight);
					this.scroller.setHeight(scrollerHeight);
				}

				// guarantees the same scrollbar widths
				this.scroller.lockOverflow(scrollbarWidths);
			}
		},


		// given a desired total height of the view, returns what the height of the scroller should be
		computeScrollerHeight: function(totalHeight) {
			return totalHeight -
				subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
		},


		// Sets the height of just the DayGrid component in this view
		setGridHeight: function(height, isAuto) {
			if (isAuto) {
				undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding
			}
			else {
				distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows
			}
		},


		/* Scroll
		------------------------------------------------------------------------------------------------------------------*/


		queryScroll: function() {
			return this.scroller.getScrollTop();
		},


		setScroll: function(top) {
			this.scroller.setScrollTop(top);
		},


		/* Hit Areas
		------------------------------------------------------------------------------------------------------------------*/
		// forward all hit-related method calls to dayGrid


		prepareHits: function() {
			this.dayGrid.prepareHits();
		},


		releaseHits: function() {
			this.dayGrid.releaseHits();
		},


		queryHit: function(left, top) {
			return this.dayGrid.queryHit(left, top);
		},


		getHitSpan: function(hit) {
			return this.dayGrid.getHitSpan(hit);
		},


		getHitEl: function(hit) {
			return this.dayGrid.getHitEl(hit);
		},


		/* Events
		------------------------------------------------------------------------------------------------------------------*/


		// Renders the given events onto the view and populates the segments array
		renderEvents: function(events) {
			this.dayGrid.renderEvents(events);

			this.updateHeight(); // must compensate for events that overflow the row
		},


		// Retrieves all segment objects that are rendered in the view
		getEventSegs: function() {
			return this.dayGrid.getEventSegs();
		},


		// Unrenders all event elements and clears internal segment data
		unrenderEvents: function() {
			this.dayGrid.unrenderEvents();

			// we DON'T need to call updateHeight() because
			// a renderEvents() call always happens after this, which will eventually call updateHeight()
		},


		/* Dragging (for both events and external elements)
		------------------------------------------------------------------------------------------------------------------*/


		// A returned value of `true` signals that a mock "helper" event has been rendered.
		renderDrag: function(dropLocation, seg) {
			return this.dayGrid.renderDrag(dropLocation, seg);
		},


		unrenderDrag: function() {
			this.dayGrid.unrenderDrag();
		},


		/* Selection
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of a selection
		renderSelection: function(span) {
			this.dayGrid.renderSelection(span);
		},


		// Unrenders a visual indications of a selection
		unrenderSelection: function() {
			this.dayGrid.unrenderSelection();
		}

	});


	// Methods that will customize the rendering behavior of the BasicView's dayGrid
	var basicDayGridMethods = {


		// Generates the HTML that will go before the day-of week header cells
		renderHeadIntroHtml: function() {
			var view = this.view;

			if (view.colWeekNumbersVisible) {
				return '' +
					'<th class="fc-week-number ' + view.widgetHeaderClass + '" ' + view.weekNumberStyleAttr() + '>' +
						'<span>' + // needed for matchCellWidths
							htmlEscape(view.opt('weekNumberTitle')) +
						'</span>' +
					'</th>';
			}

			return '';
		},


		// Generates the HTML that will go before content-skeleton cells that display the day/week numbers
		renderNumberIntroHtml: function(row) {
			var view = this.view;

			if (view.colWeekNumbersVisible) {
				return '' +
					'<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '>' +
						'<span>' + // needed for matchCellWidths
							this.getCellDate(row, 0).format('w') +
						'</span>' +
					'</td>';
			}

			return '';
		},


		// Generates the HTML that goes before the day bg cells for each day-row
		renderBgIntroHtml: function() {
			var view = this.view;

			if (view.colWeekNumbersVisible) {
				return '<td class="fc-week-number ' + view.widgetContentClass + '" ' +
					view.weekNumberStyleAttr() + '></td>';
			}

			return '';
		},


		// Generates the HTML that goes before every other type of row generated by DayGrid.
		// Affects helper-skeleton and highlight-skeleton rows.
		renderIntroHtml: function() {
			var view = this.view;

			if (view.colWeekNumbersVisible) {
				return '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '></td>';
			}

			return '';
		}

	};

	;;

	/* A month view with day cells running in rows (one-per-week) and columns
	----------------------------------------------------------------------------------------------------------------------*/

	var MonthView = FC.MonthView = BasicView.extend({

		// Produces information about what range to display
		computeRange: function(date) {
			var range = BasicView.prototype.computeRange.call(this, date); // get value from super-method
			var rowCnt;

			// ensure 6 weeks
			if (this.isFixedWeeks()) {
				rowCnt = Math.ceil(range.end.diff(range.start, 'weeks', true)); // could be partial weeks due to hiddenDays
				range.end.add(6 - rowCnt, 'weeks');
			}

			return range;
		},


		// Overrides the default BasicView behavior to have special multi-week auto-height logic
		setGridHeight: function(height, isAuto) {

			isAuto = isAuto || this.opt('weekMode') === 'variable'; // LEGACY: weekMode is deprecated

			// if auto, make the height of each row the height that it would be if there were 6 weeks
			if (isAuto) {
				height *= this.rowCnt / 6;
			}

			distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows
		},


		isFixedWeeks: function() {
			var weekMode = this.opt('weekMode'); // LEGACY: weekMode is deprecated
			if (weekMode) {
				return weekMode === 'fixed'; // if any other type of weekMode, assume NOT fixed
			}

			return this.opt('fixedWeekCount');
		}

	});

	;;

	fcViews.basic = {
		'class': BasicView
	};

	fcViews.basicDay = {
		type: 'basic',
		duration: { days: 1 }
	};

	fcViews.basicWeek = {
		type: 'basic',
		duration: { weeks: 1 }
	};

	fcViews.month = {
		'class': MonthView,
		duration: { months: 1 }, // important for prev/next
		defaults: {
			fixedWeekCount: true
		}
	};
	;;

	/* An abstract class for all agenda-related views. Displays one more columns with time slots running vertically.
	----------------------------------------------------------------------------------------------------------------------*/
	// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
	// Responsible for managing width/height.

	var AgendaView = FC.AgendaView = View.extend({

		scroller: null,

		timeGridClass: TimeGrid, // class used to instantiate the timeGrid. subclasses can override
		timeGrid: null, // the main time-grid subcomponent of this view

		dayGridClass: DayGrid, // class used to instantiate the dayGrid. subclasses can override
		dayGrid: null, // the "all-day" subcomponent. if all-day is turned off, this will be null

		axisWidth: null, // the width of the time axis running down the side

		headContainerEl: null, // div that hold's the timeGrid's rendered date header
		noScrollRowEls: null, // set of fake row elements that must compensate when scroller has scrollbars

		// when the time-grid isn't tall enough to occupy the given height, we render an <hr> underneath
		bottomRuleEl: null,


		initialize: function() {
			this.timeGrid = this.instantiateTimeGrid();

			if (this.opt('allDaySlot')) { // should we display the "all-day" area?
				this.dayGrid = this.instantiateDayGrid(); // the all-day subcomponent of this view
			}

			this.scroller = new Scroller({
				overflowX: 'hidden',
				overflowY: 'auto'
			});
		},


		// Instantiates the TimeGrid object this view needs. Draws from this.timeGridClass
		instantiateTimeGrid: function() {
			var subclass = this.timeGridClass.extend(agendaTimeGridMethods);

			return new subclass(this);
		},


		// Instantiates the DayGrid object this view might need. Draws from this.dayGridClass
		instantiateDayGrid: function() {
			var subclass = this.dayGridClass.extend(agendaDayGridMethods);

			return new subclass(this);
		},


		/* Rendering
		------------------------------------------------------------------------------------------------------------------*/


		// Sets the display range and computes all necessary dates
		setRange: function(range) {
			View.prototype.setRange.call(this, range); // call the super-method

			this.timeGrid.setRange(range);
			if (this.dayGrid) {
				this.dayGrid.setRange(range);
			}
		},


		// Renders the view into `this.el`, which has already been assigned
		renderDates: function() {

			this.el.addClass('fc-agenda-view').html(this.renderSkeletonHtml());
			this.renderHead();

			this.scroller.render();
			var timeGridWrapEl = this.scroller.el.addClass('fc-time-grid-container');
			var timeGridEl = $('<div class="fc-time-grid" />').appendTo(timeGridWrapEl);
			this.el.find('.fc-body > tr > td').append(timeGridWrapEl);

			this.timeGrid.setElement(timeGridEl);
			this.timeGrid.renderDates();

			// the <hr> that sometimes displays under the time-grid
			this.bottomRuleEl = $('<hr class="fc-divider ' + this.widgetHeaderClass + '"/>')
				.appendTo(this.timeGrid.el); // inject it into the time-grid

			if (this.dayGrid) {
				this.dayGrid.setElement(this.el.find('.fc-day-grid'));
				this.dayGrid.renderDates();

				// have the day-grid extend it's coordinate area over the <hr> dividing the two grids
				this.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight();
			}

			this.noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)'); // fake rows not within the scroller
		},


		// render the day-of-week headers
		renderHead: function() {
			this.headContainerEl =
				this.el.find('.fc-head-container')
					.html(this.timeGrid.renderHeadHtml());
		},


		// Unrenders the content of the view. Since we haven't separated skeleton rendering from date rendering,
		// always completely kill each grid's rendering.
		unrenderDates: function() {
			this.timeGrid.unrenderDates();
			this.timeGrid.removeElement();

			if (this.dayGrid) {
				this.dayGrid.unrenderDates();
				this.dayGrid.removeElement();
			}

			this.scroller.destroy();
		},


		// Builds the HTML skeleton for the view.
		// The day-grid and time-grid components will render inside containers defined by this HTML.
		renderSkeletonHtml: function() {
			return '' +
				'<table>' +
					'<thead class="fc-head">' +
						'<tr>' +
							'<td class="fc-head-container ' + this.widgetHeaderClass + '"></td>' +
						'</tr>' +
					'</thead>' +
					'<tbody class="fc-body">' +
						'<tr>' +
							'<td class="' + this.widgetContentClass + '">' +
								(this.dayGrid ?
									'<div class="fc-day-grid"/>' +
									'<hr class="fc-divider ' + this.widgetHeaderClass + '"/>' :
									''
									) +
							'</td>' +
						'</tr>' +
					'</tbody>' +
				'</table>';
		},


		// Generates an HTML attribute string for setting the width of the axis, if it is known
		axisStyleAttr: function() {
			if (this.axisWidth !== null) {
				 return 'style="width:' + this.axisWidth + 'px"';
			}
			return '';
		},


		/* Business Hours
		------------------------------------------------------------------------------------------------------------------*/


		renderBusinessHours: function() {
			this.timeGrid.renderBusinessHours();

			if (this.dayGrid) {
				this.dayGrid.renderBusinessHours();
			}
		},


		unrenderBusinessHours: function() {
			this.timeGrid.unrenderBusinessHours();

			if (this.dayGrid) {
				this.dayGrid.unrenderBusinessHours();
			}
		},


		/* Now Indicator
		------------------------------------------------------------------------------------------------------------------*/


		getNowIndicatorUnit: function() {
			return this.timeGrid.getNowIndicatorUnit();
		},


		renderNowIndicator: function(date) {
			this.timeGrid.renderNowIndicator(date);
		},


		unrenderNowIndicator: function() {
			this.timeGrid.unrenderNowIndicator();
		},


		/* Dimensions
		------------------------------------------------------------------------------------------------------------------*/


		updateSize: function(isResize) {
			this.timeGrid.updateSize(isResize);

			View.prototype.updateSize.call(this, isResize); // call the super-method
		},


		// Refreshes the horizontal dimensions of the view
		updateWidth: function() {
			// make all axis cells line up, and record the width so newly created axis cells will have it
			this.axisWidth = matchCellWidths(this.el.find('.fc-axis'));
		},


		// Adjusts the vertical dimensions of the view to the specified values
		setHeight: function(totalHeight, isAuto) {
			var eventLimit;
			var scrollerHeight;
			var scrollbarWidths;

			// reset all dimensions back to the original state
			this.bottomRuleEl.hide(); // .show() will be called later if this <hr> is necessary
			this.scroller.clear(); // sets height to 'auto' and clears overflow
			uncompensateScroll(this.noScrollRowEls);

			// limit number of events in the all-day area
			if (this.dayGrid) {
				this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed

				eventLimit = this.opt('eventLimit');
				if (eventLimit && typeof eventLimit !== 'number') {
					eventLimit = AGENDA_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number
				}
				if (eventLimit) {
					this.dayGrid.limitRows(eventLimit);
				}
			}

			if (!isAuto) { // should we force dimensions of the scroll container?

				scrollerHeight = this.computeScrollerHeight(totalHeight);
				this.scroller.setHeight(scrollerHeight);
				scrollbarWidths = this.scroller.getScrollbarWidths();

				if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?

					// make the all-day and header rows lines up
					compensateScroll(this.noScrollRowEls, scrollbarWidths);

					// the scrollbar compensation might have changed text flow, which might affect height, so recalculate
					// and reapply the desired height to the scroller.
					scrollerHeight = this.computeScrollerHeight(totalHeight);
					this.scroller.setHeight(scrollerHeight);
				}

				// guarantees the same scrollbar widths
				this.scroller.lockOverflow(scrollbarWidths);

				// if there's any space below the slats, show the horizontal rule.
				// this won't cause any new overflow, because lockOverflow already called.
				if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {
					this.bottomRuleEl.show();
				}
			}
		},


		// given a desired total height of the view, returns what the height of the scroller should be
		computeScrollerHeight: function(totalHeight) {
			return totalHeight -
				subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
		},


		/* Scroll
		------------------------------------------------------------------------------------------------------------------*/


		// Computes the initial pre-configured scroll state prior to allowing the user to change it
		computeInitialScroll: function() {
			var scrollTime = moment.duration(this.opt('scrollTime'));
			var top = this.timeGrid.computeTimeTop(scrollTime);

			// zoom can give weird floating-point values. rather scroll a little bit further
			top = Math.ceil(top);

			if (top) {
				top++; // to overcome top border that slots beyond the first have. looks better
			}

			return top;
		},


		queryScroll: function() {
			return this.scroller.getScrollTop();
		},


		setScroll: function(top) {
			this.scroller.setScrollTop(top);
		},


		/* Hit Areas
		------------------------------------------------------------------------------------------------------------------*/
		// forward all hit-related method calls to the grids (dayGrid might not be defined)


		prepareHits: function() {
			this.timeGrid.prepareHits();
			if (this.dayGrid) {
				this.dayGrid.prepareHits();
			}
		},


		releaseHits: function() {
			this.timeGrid.releaseHits();
			if (this.dayGrid) {
				this.dayGrid.releaseHits();
			}
		},


		queryHit: function(left, top) {
			var hit = this.timeGrid.queryHit(left, top);

			if (!hit && this.dayGrid) {
				hit = this.dayGrid.queryHit(left, top);
			}

			return hit;
		},


		getHitSpan: function(hit) {
			// TODO: hit.component is set as a hack to identify where the hit came from
			return hit.component.getHitSpan(hit);
		},


		getHitEl: function(hit) {
			// TODO: hit.component is set as a hack to identify where the hit came from
			return hit.component.getHitEl(hit);
		},


		/* Events
		------------------------------------------------------------------------------------------------------------------*/


		// Renders events onto the view and populates the View's segment array
		renderEvents: function(events) {
			var dayEvents = [];
			var timedEvents = [];
			var daySegs = [];
			var timedSegs;
			var i;

			// separate the events into all-day and timed
			for (i = 0; i < events.length; i++) {
				if (events[i].allDay) {
					dayEvents.push(events[i]);
				}
				else {
					timedEvents.push(events[i]);
				}
			}

			// render the events in the subcomponents
			timedSegs = this.timeGrid.renderEvents(timedEvents);
			if (this.dayGrid) {
				daySegs = this.dayGrid.renderEvents(dayEvents);
			}

			// the all-day area is flexible and might have a lot of events, so shift the height
			this.updateHeight();
		},


		// Retrieves all segment objects that are rendered in the view
		getEventSegs: function() {
			return this.timeGrid.getEventSegs().concat(
				this.dayGrid ? this.dayGrid.getEventSegs() : []
			);
		},


		// Unrenders all event elements and clears internal segment data
		unrenderEvents: function() {

			// unrender the events in the subcomponents
			this.timeGrid.unrenderEvents();
			if (this.dayGrid) {
				this.dayGrid.unrenderEvents();
			}

			// we DON'T need to call updateHeight() because
			// a renderEvents() call always happens after this, which will eventually call updateHeight()
		},


		/* Dragging (for events and external elements)
		------------------------------------------------------------------------------------------------------------------*/


		// A returned value of `true` signals that a mock "helper" event has been rendered.
		renderDrag: function(dropLocation, seg) {
			if (dropLocation.start.hasTime()) {
				return this.timeGrid.renderDrag(dropLocation, seg);
			}
			else if (this.dayGrid) {
				return this.dayGrid.renderDrag(dropLocation, seg);
			}
		},


		unrenderDrag: function() {
			this.timeGrid.unrenderDrag();
			if (this.dayGrid) {
				this.dayGrid.unrenderDrag();
			}
		},


		/* Selection
		------------------------------------------------------------------------------------------------------------------*/


		// Renders a visual indication of a selection
		renderSelection: function(span) {
			if (span.start.hasTime() || span.end.hasTime()) {
				this.timeGrid.renderSelection(span);
			}
			else if (this.dayGrid) {
				this.dayGrid.renderSelection(span);
			}
		},


		// Unrenders a visual indications of a selection
		unrenderSelection: function() {
			this.timeGrid.unrenderSelection();
			if (this.dayGrid) {
				this.dayGrid.unrenderSelection();
			}
		}

	});


	// Methods that will customize the rendering behavior of the AgendaView's timeGrid
	// TODO: move into TimeGrid
	var agendaTimeGridMethods = {


		// Generates the HTML that will go before the day-of week header cells
		renderHeadIntroHtml: function() {
			var view = this.view;
			var weekText;

			if (view.opt('weekNumbers')) {
				weekText = this.start.format(view.opt('smallWeekFormat'));

				return '' +
					'<th class="fc-axis fc-week-number ' + view.widgetHeaderClass + '" ' + view.axisStyleAttr() + '>' +
						'<span>' + // needed for matchCellWidths
							htmlEscape(weekText) +
						'</span>' +
					'</th>';
			}
			else {
				return '<th class="fc-axis ' + view.widgetHeaderClass + '" ' + view.axisStyleAttr() + '></th>';
			}
		},


		// Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
		renderBgIntroHtml: function() {
			var view = this.view;

			return '<td class="fc-axis ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '></td>';
		},


		// Generates the HTML that goes before all other types of cells.
		// Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.
		renderIntroHtml: function() {
			var view = this.view;

			return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>';
		}

	};


	// Methods that will customize the rendering behavior of the AgendaView's dayGrid
	var agendaDayGridMethods = {


		// Generates the HTML that goes before the all-day cells
		renderBgIntroHtml: function() {
			var view = this.view;

			return '' +
				'<td class="fc-axis ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '>' +
					'<span>' + // needed for matchCellWidths
						view.getAllDayHtml() +
					'</span>' +
				'</td>';
		},


		// Generates the HTML that goes before all other types of cells.
		// Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.
		renderIntroHtml: function() {
			var view = this.view;

			return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>';
		}

	};

	;;

	var AGENDA_ALL_DAY_EVENT_LIMIT = 5;

	// potential nice values for the slot-duration and interval-duration
	// from largest to smallest
	var AGENDA_STOCK_SUB_DURATIONS = [
		{ hours: 1 },
		{ minutes: 30 },
		{ minutes: 15 },
		{ seconds: 30 },
		{ seconds: 15 }
	];

	fcViews.agenda = {
		'class': AgendaView,
		defaults: {
			allDaySlot: true,
			slotDuration: '00:30:00',
			minTime: '00:00:00',
			maxTime: '24:00:00',
			slotEventOverlap: true // a bad name. confused with overlap/constraint system
		}
	};

	fcViews.agendaDay = {
		type: 'agenda',
		duration: { days: 1 }
	};

	fcViews.agendaWeek = {
		type: 'agenda',
		duration: { weeks: 1 }
	};
	;;

	/*
	Responsible for the scroller, and forwarding event-related actions into the "grid"
	*/
	var ListView = View.extend({

		grid: null,
		scroller: null,

		initialize: function() {
			this.grid = new ListViewGrid(this);
			this.scroller = new Scroller({
				overflowX: 'hidden',
				overflowY: 'auto'
			});
		},

		setRange: function(range) {
			View.prototype.setRange.call(this, range); // super

			this.grid.setRange(range); // needs to process range-related options
		},

		renderSkeleton: function() {
			this.el.addClass(
				'fc-list-view ' +
				this.widgetContentClass
			);

			this.scroller.render();
			this.scroller.el.appendTo(this.el);

			this.grid.setElement(this.scroller.scrollEl);
		},

		unrenderSkeleton: function() {
			this.scroller.destroy(); // will remove the Grid too
		},

		setHeight: function(totalHeight, isAuto) {
			this.scroller.setHeight(this.computeScrollerHeight(totalHeight));
		},

		computeScrollerHeight: function(totalHeight) {
			return totalHeight -
				subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
		},

		renderEvents: function(events) {
			this.grid.renderEvents(events);
		},

		unrenderEvents: function() {
			this.grid.unrenderEvents();
		},

		isEventResizable: function(event) {
			return false;
		},

		isEventDraggable: function(event) {
			return false;
		}

	});

	/*
	Responsible for event rendering and user-interaction.
	Its "el" is the inner-content of the above view's scroller.
	*/
	var ListViewGrid = Grid.extend({

		segSelector: '.fc-list-item', // which elements accept event actions
		hasDayInteractions: false, // no day selection or day clicking

		// slices by day
		spanToSegs: function(span) {
			var view = this.view;
			var dayStart = view.start.clone();
			var dayEnd;
			var seg;
			var segs = [];

			while (dayStart < view.end) {
				dayEnd = dayStart.clone().add(1, 'day');
				seg = intersectRanges(span, {
					start: dayStart,
					end: dayEnd
				});
				if (seg) {
					segs.push(seg);
				}
				dayStart = dayEnd;
			}

			return segs;
		},

		// like "4:00am"
		computeEventTimeFormat: function() {
			return this.view.opt('mediumTimeFormat');
		},

		// for events with a url, the whole <tr> should be clickable,
		// but it's impossible to wrap with an <a> tag. simulate this.
		handleSegClick: function(seg, ev) {
			var url;

			Grid.prototype.handleSegClick.apply(this, arguments); // super. might prevent the default action

			// not clicking on or within an <a> with an href
			if (!$(ev.target).closest('a[href]').length) {
				url = seg.event.url;
				if (url && !ev.isDefaultPrevented()) { // jsEvent not cancelled in handler
					window.location.href = url; // simulate link click
				}
			}
		},

		// returns list of foreground segs that were actually rendered
		renderFgSegs: function(segs) {
			segs = this.renderFgSegEls(segs); // might filter away hidden events

			if (!segs.length) {
				this.renderEmptyMessage();
				return segs;
			}
			else {
				return this.renderSegList(segs);
			}
		},

		renderEmptyMessage: function() {
			this.el.html(
				'<div class="fc-list-empty-wrap2">' + // TODO: try less wraps
				'<div class="fc-list-empty-wrap1">' +
				'<div class="fc-list-empty">' +
					htmlEscape(this.view.opt('noEventsMessage')) +
				'</div>' +
				'</div>' +
				'</div>'
			);
		},

		// render the event segments in the view. returns the mutated array.
		renderSegList: function(segs) {
			var tableEl = $('<table class="fc-list-table"><tbody/></table>');
			var tbodyEl = tableEl.find('tbody');
			var i, seg;
			var dayDate;

			this.sortEventSegs(segs);

			for (i = 0; i < segs.length; i++) {
				seg = segs[i];

				// append a day header
				if (!dayDate || !seg.start.isSame(dayDate, 'day')) {
					dayDate = seg.start.clone().stripTime();
					tbodyEl.append(this.dayHeaderHtml(dayDate));
				}

				tbodyEl.append(seg.el); // append event row
			}

			this.el.empty().append(tableEl);

			return segs; // return the sorted list
		},

		// generates the HTML for the day headers that live amongst the event rows
		dayHeaderHtml: function(dayDate) {
			var mainFormat = this.view.opt('listDayFormat');
			var altFormat = this.view.opt('listDayAltFormat');

			return '<tr class="fc-list-heading">' +
				'<td class="' + this.view.widgetHeaderClass + '" colspan="3">' +
					(mainFormat ?
						'<span class="fc-list-heading-main">' +
							htmlEscape(dayDate.format(mainFormat)) +
						'</span>' :
						'') +
					(altFormat ?
						'<span class="fc-list-heading-alt">' +
							htmlEscape(dayDate.format(altFormat)) +
						'</span>' :
						'') +
				'</td>' +
			'</tr>';
		},

		// generates the HTML for a single event row
		fgSegHtml: function(seg) {
			var view = this.view;
			var classes = [ 'fc-list-item' ].concat(this.getSegCustomClasses(seg));
			var bgColor = this.getSegBackgroundColor(seg);
			var url = seg.event.url;
			var timeHtml;

			if (!seg.start.hasTime()) {
				timeHtml = view.getAllDayHtml();
			}
			else {
				timeHtml = htmlEscape(this.getEventTimeText(seg));
			}

			if (url) {
				classes.push('fc-has-url');
			}

			return '<tr class="' + classes.join(' ') + '">' +
				'<td class="fc-list-item-marker ' + view.widgetContentClass + '">' +
					'<span class="fc-event-dot"' +
					(bgColor ?
						' style="background-color:' + bgColor + '"' :
						'') +
					'></span>' +
				'</td>' +
				(view.opt('listTime') ?
					'<td class="fc-list-item-time ' + view.widgetContentClass + '">' +
						timeHtml +
					'</td>' :
					'') +
				'<td class="fc-list-item-title ' + view.widgetContentClass + '">' +
					'<a' + (url ? ' href="' + htmlEscape(url) + '"' : '') + '>' +
						htmlEscape(seg.event.title) +
					'</a>' +
				'</td>' +
			'</tr>';
		}

	});

	;;

	fcViews.list = {
		'class': ListView,
		buttonTextKey: 'list', // what to lookup in locale files
		defaults: {
			buttonText: 'list', // text to display for English
			listTime: true, // show the time column?
			listDayFormat: 'LL', // like "January 1, 2016"
			noEventsMessage: 'No events to display'
		}
	};

	fcViews.listDay = {
		type: 'list',
		duration: { days: 1 },
		defaults: {
			listDayFormat: 'dddd' // day-of-week is all we need. full date is probably in header
		}
	};

	fcViews.listWeek = {
		type: 'list',
		duration: { weeks: 1 },
		defaults: {
			listDayFormat: 'dddd', // day-of-week is more important
			listDayAltFormat: 'LL'
		}
	};

	fcViews.listMonth = {
		type: 'list',
		duration: { month: 1 },
		defaults: {
			listDayAltFormat: 'dddd' // day-of-week is nice-to-have
		}
	};

	fcViews.listYear = {
		type: 'list',
		duration: { year: 1 },
		defaults: {
			listDayAltFormat: 'dddd' // day-of-week is nice-to-have
		}
	};

	;;

	return FC; // export for Node/CommonJS
	});

/***/ },
/* 446 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _marked = __webpack_require__(369);

	var _marked2 = _interopRequireDefault(_marked);

	var _sortablejs = __webpack_require__(414);

	var _sortablejs2 = _interopRequireDefault(_sortablejs);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Form = function () {
	  function Form() {
	    _classCallCheck(this, Form);

	    if ((0, _jquery2.default)(".new_project, .edit_project").length > 0) this._bindProject();
	    if ((0, _jquery2.default)(".new_scale, .edit_scale").length > 0) this._bindScale();
	    if ((0, _jquery2.default)(".multi-select2").length > 0) this._select2ProjectForn();
	  }

	  _createClass(Form, [{
	    key: '_select2ProjectForn',
	    value: function _select2ProjectForn() {
	      var selected = (0, _jquery2.default)('.multi-select2').data('selected').map(function (e) {
	        return { id: e[0], text: e[1] };
	      });

	      (0, _jquery2.default)(".multi-select2").select2({
	        data: selected,
	        ajax: {
	          url: "/users/select2",
	          dataType: 'json',
	          delay: 250,
	          data: function data(params) {
	            return {
	              q: params.term, // search term
	              page: params.page
	            };
	          },
	          processResults: function processResults(data, params) {
	            params.page = params.page || 1;
	            return {
	              results: data.items,
	              pagination: {
	                more: params.page * 30 < data.total_count
	              }
	            };
	          },
	          cache: true
	        },
	        minimumInputLength: 2,
	        dropdownAutoWidth: true,
	        escapeMarkup: function escapeMarkup(markup) {
	          return markup;
	        }, // let our custom formatter work
	        templateResult: function templateResult(data) {
	          return '<span>' + (data.text || data.login) + '</span>';
	        },
	        templateSelection: function templateSelection(data) {
	          return '<span>' + (data.text || data.login) + '</span>';
	        }
	      }).val(selected.map(function (e) {
	        return e.id;
	      })).change();
	    }
	  }, {
	    key: '_bindProject',
	    value: function _bindProject() {
	      this._hideDependancies();
	      this._bindEstimations();
	      this._bindRules();
	      this._initRules();
	      this._updateSelectSkills();
	      this._bindCodeModal();
	      this._bindSortableRules();

	      (0, _jquery2.default)(document).on('change', '.project_projects_skills_skill select', this._updateSelectSkills.bind(this));
	      (0, _jquery2.default)(document).on('cocoon:after-insert', this._updateSelectSkills.bind(this));
	      (0, _jquery2.default)(document).on('cocoon:after-remove', this._updateSelectSkills.bind(this));
	      (0, _jquery2.default)("#projects_sessions").on('cocoon:before-insert', this._addProjectSessionLink.bind(this));
	      (0, _jquery2.default)("#projects_sessions").on('cocoon:after-insert', this._addProjectSessionField.bind(this));
	      (0, _jquery2.default)("#projects_sessions").on('cocoon:before-remove', this._removeProjectSessionLink.bind(this));
	      (0, _jquery2.default)("#projects_sessions").on('cocoon:after-remove', this._removeProjectSessionField.bind(this));
	      (0, _jquery2.default)(document).on('click', '.project-session-nav-tabs [data-toggle]', this._initRules.bind(this));
	      // PK? :'( $("#projects_sessions").on('cocoon:before-insert', this._addProjectSessionLink.bind(this));

	      (0, _jquery2.default)("a[data-add-session]").data("association-insertion-method", 'append').data("association-insertion-traversal", 'closest');
	      (0, _jquery2.default)(".add-ps a").click(function () {
	        (0, _jquery2.default)("a[data-add-session]").trigger("click");
	      });
	      (0, _jquery2.default)("#project_cursus_ids").change(this._updateSelectSkills.bind(this));
	      // $("[data-associations='project_sessions_rules']")
	      //   .data("association-insertion-method", 'before')
	      //   .data("association-insertion-node", '[data-association="project_sessions_rule"]')
	    }
	  }, {
	    key: '_bindCodeModal',
	    value: function _bindCodeModal() {
	      (0, _jquery2.default)('ul.list-group').on('click', "a[id^='button_code_']", function () {
	        var modal_id = (0, _jquery2.default)(this).data().uid;
	        var rule_id = (0, _jquery2.default)(this).parents('.list-group-item').find('.rules_select').val();
	        var ct = (0, _jquery2.default)('.modal#rule_code_' + modal_id);

	        ct.find('#code').text('').hide();
	        ct.find('#not_found').hide();
	        ct.find('#text_loading').show();
	        ct.modal();
	        _jquery2.default.ajax({
	          url: '/rules/' + rule_id + '/code.json',
	          type: 'GET',
	          success: function success(d) {
	            ct.find('#code').html(d.code).show();
	            ct.find('#text_loading').hide();
	          },
	          error: function error(d) {
	            ct.find('#text_loading').hide();
	            ct.find('#not_found').show();
	          }
	        });
	      });
	    }
	  }, {
	    key: '_addProjectSessionLink',
	    value: function _addProjectSessionLink(e, field) {
	      if ((0, _jquery2.default)(e.target).find("a[data-add-session]").length > 0) {
	        ps_counter += 1;
	        (0, _jquery2.default)("li.add-ps").before('<li role=\'presentation\'><a aria-controls=\'main settings\' data-toggle=\'tab\' href=\'#project-session-' + ps_counter + '\' role=\'tab\'>unsaved Project session</a></li>');
	      }
	    }
	  }, {
	    key: '_addProjectSessionField',
	    value: function _addProjectSessionField(e, f) {
	      if ((0, _jquery2.default)(e.target).find("a[data-add-session]").length > 0) {
	        var field = (0, _jquery2.default)(".buffer-links .nested-fields").detach();
	        field.appendTo(".main-project-session-tab-content");
	        field.wrap("<div class='tab-pane' id='project-session-" + ps_counter + "'></div>");
	        (0, _jquery2.default)('a[href=\'#project-session-' + ps_counter + '\']').trigger('click');
	      }
	    }
	  }, {
	    key: '_removeProjectSessionLink',
	    value: function _removeProjectSessionLink(e, field) {
	      if ((0, _jquery2.default)(field.context).attr("data-remove-session") !== undefined) {
	        var ref = (0, _jquery2.default)(field).closest(".tab-pane").attr("id");
	        (0, _jquery2.default)('a[href=\'#' + ref + '\']').parent().detach();
	      }
	    }
	  }, {
	    key: '_removeProjectSessionField',
	    value: function _removeProjectSessionField(e, f) {
	      if ((0, _jquery2.default)(f.context).attr("data-remove-session") !== undefined) {
	        if ((0, _jquery2.default)(f.context).attr("data-saved") == 'true') {
	          (0, _jquery2.default)(f).closest(".tab-pane").hide();
	          (0, _jquery2.default)('a[href^=\'#project-session\']').trigger('click');
	        } else {
	          (0, _jquery2.default)(f).closest(".tab-pane").detach();
	          (0, _jquery2.default)('a[href^=\'#project-session\']').trigger('click');
	        }
	      }
	    }
	  }, {
	    key: '_bindNameCheck',
	    value: function _bindNameCheck() {
	      var ctx = this;

	      (0, _jquery2.default)("#project_name").keyup(function () {
	        var elt = (0, _jquery2.default)(this);
	        if ((0, _jquery2.default)(this).val().length > 0) {
	          var name = (0, _jquery2.default)(this).val();
	          _jquery2.default.getJSON("#{location.origin}/projects.json", function (names) {
	            var rest = _lodash2.default.findWhere(names, { name: name });
	            if (rest) {
	              ctx._updateNextHelp(elt, "#{name} is already taken");
	              ctx._updateNextHelp("#project_tag_ids", "");
	            } else {
	              ctx._updateNextHelp(elt, "#{name} seems to be a nice name !");
	              ctx._updateNextHelp("#project_tag_ids", "The tag #{name} will also be automaticaly created.");
	            }
	          });
	        } else {
	          ctx._updateNextHelp(elt, "");
	          ctx._updateNextHelp("#project_tag_ids", "");
	        }
	      });
	    }
	  }, {
	    key: '_bindEstimations',
	    value: function _bindEstimations() {
	      (0, _jquery2.default)("#project_estimate_time").val("604800");
	    }
	  }, {
	    key: '_initRules',
	    value: function _initRules() {
	      (0, _jquery2.default)(".rules_select").each(this._setRuleTemplate);
	    }
	  }, {
	    key: '_bindRules',
	    value: function _bindRules() {
	      (0, _jquery2.default)(document).on('change', '.rules_select', this._setRuleTemplate);
	    }
	  }, {
	    key: '_setRuleTemplate',
	    value: function _setRuleTemplate() {
	      var ruleTemplate = _lodash2.default.template('\n      <div class="col-sm-2">\n        <span class="rule-kind <%= kind %>"><%= kind %></span>\n      </div>\n      <div class="col-sm-10 rule-desc">\n        <span>\n          <b><%= name %></b>\n        </span>\n        \u2013\n        <small>\n          <%= readable || \'No description\' %>\n        </small>\n      </div>\n    ');
	      var desc = (0, _jquery2.default)(this).parents(".project-opts").children(".rule-description").first();
	      var selected = _lodash2.default.find(rules_description, { id: parseInt((0, _jquery2.default)(this).val()) });
	      if (selected && selected["kind"] && selected["name"]) {
	        desc.html(ruleTemplate(selected));
	      }
	    }
	  }, {
	    key: '_bindSortableRules',
	    value: function _bindSortableRules() {
	      (0, _jquery2.default)('ul.list-group.sortable-rules').each(function (index, el) {
	        var $ul = (0, _jquery2.default)(el);
	        _sortablejs2.default.create(el, {
	          onSort: function onSort() {
	            $ul.children('li').each(function (index, el) {
	              (0, _jquery2.default)(el).find('.project_project_sessions_project_sessions_rules_position').find('input').val(index + 1);
	              (0, _jquery2.default)(el).find('.rule-position').text(index + 1);
	            });
	          }
	        });
	      });
	    }
	  }, {
	    key: '_hideDependancies',
	    value: function _hideDependancies() {
	      if ((0, _jquery2.default)("#project_parent_id").val() != "") (0, _jquery2.default)(".project_inherited_team").hide();
	      (0, _jquery2.default)("#project_parent_id").change(function () {
	        if ((0, _jquery2.default)(this).val() == "") (0, _jquery2.default)(".project_inherited_team").show();else (0, _jquery2.default)(".project_inherited_team").hide();
	      });
	    }
	  }, {
	    key: '_updateNextHelp',
	    value: function _updateNextHelp(elt, text) {
	      var next = (0, _jquery2.default)(elt).parent().find(".help-block").last();
	      if ((0, _jquery2.default)(next).length > 0) (0, _jquery2.default)(next).html(text);
	    }

	    // ================ The scales form ================


	  }, {
	    key: '_bindScale',
	    value: function _bindScale() {
	      var _this = this;

	      this._bindMarkdownPreviews();
	      this._checkScales();
	      this._bindNavbarArchi();
	      (0, _jquery2.default)(document).on('cocoon:after-insert', function (_) {
	        _this._bindNavbarArchi();
	      });
	      (0, _jquery2.default)(".section-counter-item input[type='text']").keyup(function (_) {
	        _this._bindNavbarArchi();
	      });
	    }
	  }, {
	    key: '_checkScales',
	    value: function _checkScales() {
	      var template_existing = _lodash2.default.template('\n      <p class=\'text-warning primary-warning\'>An other scale (<%= name %>) is already set as <b>primary</b>. You can <a href=\'<%= link %>/edit\' target=\'_blank\'>edit it now</a></p>\n    ');
	      var template_not_existing = _lodash2.default.template('\n      <p class=\'text-warning primary-warning\'>There is no other scale defined as primary for this project. Don\'t forget to set this scale as primary later if you want to use it for defenses.</a></p>\n    ');
	      if (existing_scales) (0, _jquery2.default)("#scale_is_primary").parents(".checkbox").after(template_existing(existing_scales));
	      (0, _jquery2.default)("#scale_is_primary").change(function () {
	        var val = this.checked;
	        (0, _jquery2.default)(".primary-warning").detach();
	        if (val && existing_scales) (0, _jquery2.default)("#scale_is_primary").parents(".checkbox").after(template_existing(existing_scales));else if (!val && !existing_scales) (0, _jquery2.default)("#scale_is_primary").parents(".checkbox").after(template_not_existing());
	      });
	    }
	  }, {
	    key: '_bindMarkdownPreviews',
	    value: function _bindMarkdownPreviews() {
	      (0, _jquery2.default)("[data-markdown-preview]").each(function (e) {
	        var container = (0, _jquery2.default)("<div class='markdown-preview-container'></div>");
	        (0, _jquery2.default)(this).after(container);
	        (0, _jquery2.default)(this).keyup(function () {
	          (0, _jquery2.default)(container).html((0, _marked2.default)((0, _jquery2.default)(this).val()));
	        });
	      });
	    }
	  }, {
	    key: '_bindNavbarArchi',
	    value: function _bindNavbarArchi() {
	      var _this2 = this;

	      var nav = (0, _jquery2.default)("#navbar-scale-edit .nav .sections-list");

	      nav.html('<li><h5 class=\'marked-title\'><a href=\'#sections\'>Sections <small>(' + (0, _jquery2.default)(".section-counter-item").length + ' defined)</small></a></h5><ol class=\'section-root\'></ol></li>');
	      (0, _jquery2.default)(".section-counter-item").each(function (_) {
	        var section_value = (0, _jquery2.default)(_this2).find(".scale_sections_name input");
	        var elt = (0, _jquery2.default)('<li><a href=\'#' + section_value.attr('id') + '\'>' + section_value.val() + '</a></li>');

	        if ((0, _jquery2.default)(_this2).find(".question-item").length > 0) {
	          q_list = (0, _jquery2.default)("<ol></ol>");
	          (0, _jquery2.default)(_this2).find(".question-item").each(function (_) {
	            var question_value = (0, _jquery2.default)(_this2).find(".scale_sections_questions_name input");
	            var q_elt = (0, _jquery2.default)('<li><a href=\'#' + question_value.attr('id') + '\'>' + question_value.val() + '</a></li>');
	            q_list.append(q_elt);
	          });
	          elt.append(q_list);
	        }
	        nav.find(".section-root").append(elt);
	      });
	    }

	    // ========= Skills auto-filter

	  }, {
	    key: '_getValuesSelectSkillInputs',
	    value: function _getValuesSelectSkillInputs() {
	      _lodash2.default.map((0, _jquery2.default)('.fields:visible .project_projects_skills_skill select.chosen'), function (select) {
	        return parseInt((0, _jquery2.default)(select).val(), 10);
	      });
	    }
	  }, {
	    key: '_getAvailableSkills',
	    value: function _getAvailableSkills() {
	      var cursus = (0, _jquery2.default)("#project_cursus_ids").val() || [];
	      var skills = _lodash2.default.map(cursus, function (e) {
	        return available_skills[parseInt(e, 10)];
	      });

	      _lodash2.default.merge.apply(_lodash2.default, _toConsumableArray(skills));
	    }
	  }, {
	    key: '_updateSelectSkills',
	    value: function _updateSelectSkills() {
	      var selected_skills = this._getValuesSelectSkillInputs();
	      var skills = this._getAvailableSkills();
	      if (!skills) return;
	      skills = _lodash2.default.without(skills, selected_skills);

	      (0, _jquery2.default)('.fields:visible .project_projects_skills_skill select.chosen').each(function (index, select) {
	        (0, _jquery2.default)(select).children(':not(:selected)').each(function (index, option) {
	          var skillId = parseInt((0, _jquery2.default)(option).val(), 10);
	          (0, _jquery2.default)(option).prop("disabled", skills.indexOf(skillId) == -1);
	        });
	        (0, _jquery2.default)(select).trigger("chosen:updated");
	      });
	    }
	  }]);

	  return Form;
	}();

	exports.default = Form;

/***/ },
/* 447 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _list = __webpack_require__(448);

	var _list2 = _interopRequireDefault(_list);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var OPTIONS = ["name", "duration", "recommendation", "registration"];
	var SELECTOR = "projects-list-container";

	var ProjectsList = function () {
	  function ProjectsList() {
	    _classCallCheck(this, ProjectsList);

	    if ((0, _jquery2.default)('#' + SELECTOR).length === 0) return;

	    this.options = {
	      valueNames: _lodash2.default.map(OPTIONS, function (e) {
	        return 'project-' + e;
	      }),
	      sortFunction: this._sort.bind(this),
	      page: 1000
	    };
	    (0, _jquery2.default)('[data-toggle=tooltip]').tooltip();
	    this.projectsList = new _list2.default(SELECTOR, this.options);
	    this._bindSearch();
	    this._bindFilters();
	  }

	  _createClass(ProjectsList, [{
	    key: '_bindSearch',
	    value: function _bindSearch() {
	      var _this = this;

	      var elt = document.getElementsByClassName("projects-list--search")[0];
	      if (elt) {
	        elt.addEventListener('keyup', function (_) {
	          _this.projectsList.search(elt.value, ['project-name']);
	        });
	      }
	    }
	  }, {
	    key: '_bindFilters',
	    value: function _bindFilters() {
	      var header = document.getElementsByClassName("projects-list--header")[0];
	      if (header) {
	        var _iteratorNormalCompletion = true;
	        var _didIteratorError = false;
	        var _iteratorError = undefined;

	        try {
	          for (var _iterator = header.getElementsByClassName("filter-trigger")[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	            var trigger = _step.value;

	            trigger.addEventListener('click', this._filter(trigger));
	          }
	        } catch (err) {
	          _didIteratorError = true;
	          _iteratorError = err;
	        } finally {
	          try {
	            if (!_iteratorNormalCompletion && _iterator.return) {
	              _iterator.return();
	            }
	          } finally {
	            if (_didIteratorError) {
	              throw _iteratorError;
	            }
	          }
	        }
	      }
	    }
	  }, {
	    key: '_escapeValue',
	    value: function _escapeValue(value) {
	      _lodash2.default.snakeCase(_lodash2.default.trim(_lodash2.default.deburr(value)));
	    }
	  }, {
	    key: '_cmp',
	    value: function _cmp(e, key) {
	      if (key == "project-duration") return parseInt(e.elm.attributes.getNamedItem('data-' + key.slice(8)).value);else if (key == "project-difficulty") {
	        if (!e.elm.attributes.getNamedItem('data-' + key.slice(8))) return 0;
	        return parseInt(e.elm.attributes.getNamedItem('data-' + key.slice(8)).value);
	      }

	      var elt = e.elm.attributes.getNamedItem('data-' + key.slice(8));
	      return (elt ? elt.value : "_") + '_' + e.elm.attributes.getNamedItem("data-name").value;
	    }
	  }, {
	    key: '_sort',
	    value: function _sort(a, b, c) {
	      var aCmp = this._cmp(a, c.valueName);
	      var bCmp = this._cmp(b, c.valueName);
	      if (c.order === "asc") {
	        return aCmp > bCmp ? 1 : aCmp < bCmp ? -1 : 0;
	      } else {
	        return aCmp < bCmp ? 1 : aCmp > bCmp ? -1 : 0;
	      }
	    }
	  }, {
	    key: '_filter',
	    value: function _filter(elt) {
	      var _this2 = this;

	      return function (evt) {
	        //reset all filters
	        if (elt.classList.contains("active")) {
	          var _iteratorNormalCompletion2 = true;
	          var _didIteratorError2 = false;
	          var _iteratorError2 = undefined;

	          try {
	            for (var _iterator2 = document.getElementsByClassName("filter-trigger")[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
	              var trigger = _step2.value;

	              trigger.classList.remove("active");
	            }
	          } catch (err) {
	            _didIteratorError2 = true;
	            _iteratorError2 = err;
	          } finally {
	            try {
	              if (!_iteratorNormalCompletion2 && _iterator2.return) {
	                _iterator2.return();
	              }
	            } finally {
	              if (_didIteratorError2) {
	                throw _iteratorError2;
	              }
	            }
	          }

	          var _iteratorNormalCompletion3 = true;
	          var _didIteratorError3 = false;
	          var _iteratorError3 = undefined;

	          try {
	            for (var _iterator3 = document.getElementsByClassName("default-filter")[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
	              var _trigger = _step3.value;

	              _trigger.classList.add("active");
	            }
	          } catch (err) {
	            _didIteratorError3 = true;
	            _iteratorError3 = err;
	          } finally {
	            try {
	              if (!_iteratorNormalCompletion3 && _iterator3.return) {
	                _iterator3.return();
	              }
	            } finally {
	              if (_didIteratorError3) {
	                throw _iteratorError3;
	              }
	            }
	          }

	          _this2.projectsList.filter(_this2._filterClear);
	        } else {
	          var _iteratorNormalCompletion4 = true;
	          var _didIteratorError4 = false;
	          var _iteratorError4 = undefined;

	          try {
	            for (var _iterator4 = document.getElementsByClassName("filter-trigger")[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
	              var _trigger2 = _step4.value;

	              _trigger2.classList.remove("active");
	            }
	          } catch (err) {
	            _didIteratorError4 = true;
	            _iteratorError4 = err;
	          } finally {
	            try {
	              if (!_iteratorNormalCompletion4 && _iterator4.return) {
	                _iterator4.return();
	              }
	            } finally {
	              if (_didIteratorError4) {
	                throw _iteratorError4;
	              }
	            }
	          }

	          var _iteratorNormalCompletion5 = true;
	          var _didIteratorError5 = false;
	          var _iteratorError5 = undefined;

	          try {
	            for (var _iterator5 = document.getElementsByClassName("default-filter")[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
	              var _trigger3 = _step5.value;

	              _trigger3.classList.add("active");
	            }
	          } catch (err) {
	            _didIteratorError5 = true;
	            _iteratorError5 = err;
	          } finally {
	            try {
	              if (!_iteratorNormalCompletion5 && _iterator5.return) {
	                _iterator5.return();
	              }
	            } finally {
	              if (_didIteratorError5) {
	                throw _iteratorError5;
	              }
	            }
	          }

	          elt.parentElement.getElementsByClassName("default-filter")[0].classList.remove("active");
	          //trigger.classList.remove("active")
	          elt.classList.add("active");
	          var meth = _this2['_filter' + _lodash2.default.capitalize(_lodash2.default.camelCase(elt.attributes.getNamedItem("data-filter").value))];
	          _this2.projectsList.filter(meth);
	        }
	      };
	    }

	    // On measure projects

	  }, {
	    key: '_filterRecommendedprojects',
	    value: function _filterRecommendedprojects(item) {
	      return item.elm.attributes.getNamedItem("data-recommendation").value == "a_recommended" && item.elm.attributes.getNamedItem("data-registration").value == "not_registered";
	    }
	  }, {
	    key: '_filterCursus',
	    value: function _filterCursus(item) {
	      var itemCursus = JSON.parse(item.elm.attributes.getNamedItem("data-cursus").value);
	      var chosenCursus = parseInt(document.querySelectorAll('[data-filter=cursus].active')[0].attributes.getNamedItem("data-cursus").value);
	      return itemCursus.includes(chosenCursus);
	    }
	  }, {
	    key: '_filterClear',
	    value: function _filterClear(item) {
	      return true;
	    }
	  }]);

	  return ProjectsList;
	}();

	exports.default = ProjectsList;

/***/ },
/* 448 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_RESULT__;'use strict';

	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

	!function () {
	  function a(b, c, d) {
	    var e = a.resolve(b);
	    if (null == e) {
	      d = d || b, c = c || "root";
	      var f = new Error('Failed to require "' + d + '" from "' + c + '"');
	      throw f.path = d, f.parent = c, f.require = !0, f;
	    }
	    var g = a.modules[e];
	    if (!g._resolving && !g.exports) {
	      var h = {};
	      h.exports = {}, h.client = h.component = !0, g._resolving = !0, g.call(this, h.exports, a.relative(e), h), delete g._resolving, g.exports = h.exports;
	    }
	    return g.exports;
	  }
	  a.modules = {}, a.aliases = {}, a.resolve = function (b) {
	    "/" === b.charAt(0) && (b = b.slice(1));
	    for (var c = [b, b + ".js", b + ".json", b + "/index.js", b + "/index.json"], d = 0; d < c.length; d++) {
	      var b = c[d];
	      if (a.modules.hasOwnProperty(b)) return b;
	      if (a.aliases.hasOwnProperty(b)) return a.aliases[b];
	    }
	  }, a.normalize = function (a, b) {
	    var c = [];
	    if ("." != b.charAt(0)) return b;
	    a = a.split("/"), b = b.split("/");
	    for (var d = 0; d < b.length; ++d) {
	      ".." == b[d] ? a.pop() : "." != b[d] && "" != b[d] && c.push(b[d]);
	    }return a.concat(c).join("/");
	  }, a.register = function (b, c) {
	    a.modules[b] = c;
	  }, a.alias = function (b, c) {
	    if (!a.modules.hasOwnProperty(b)) throw new Error('Failed to alias "' + b + '", it does not exist');
	    a.aliases[c] = b;
	  }, a.relative = function (b) {
	    function c(a, b) {
	      for (var c = a.length; c--;) {
	        if (a[c] === b) return c;
	      }return -1;
	    }

	    function d(c) {
	      var e = d.resolve(c);
	      return a(e, b, c);
	    }
	    var e = a.normalize(b, "..");
	    return d.resolve = function (d) {
	      var f = d.charAt(0);
	      if ("/" == f) return d.slice(1);
	      if ("." == f) return a.normalize(e, d);
	      var g = b.split("/"),
	          h = c(g, "deps") + 1;
	      return h || (h = 0), d = g.slice(0, h + 1).join("/") + "/deps/" + d;
	    }, d.exists = function (b) {
	      return a.modules.hasOwnProperty(d.resolve(b));
	    }, d;
	  }, a.register("component-classes/index.js", function (a, b, c) {
	    function d(a) {
	      if (!a) throw new Error("A DOM element reference is required");
	      this.el = a, this.list = a.classList;
	    }
	    var e = b("indexof"),
	        f = /\s+/,
	        g = Object.prototype.toString;
	    c.exports = function (a) {
	      return new d(a);
	    }, d.prototype.add = function (a) {
	      if (this.list) return this.list.add(a), this;
	      var b = this.array(),
	          c = e(b, a);
	      return ~c || b.push(a), this.el.className = b.join(" "), this;
	    }, d.prototype.remove = function (a) {
	      if ("[object RegExp]" == g.call(a)) return this.removeMatching(a);
	      if (this.list) return this.list.remove(a), this;
	      var b = this.array(),
	          c = e(b, a);
	      return ~c && b.splice(c, 1), this.el.className = b.join(" "), this;
	    }, d.prototype.removeMatching = function (a) {
	      for (var b = this.array(), c = 0; c < b.length; c++) {
	        a.test(b[c]) && this.remove(b[c]);
	      }return this;
	    }, d.prototype.toggle = function (a, b) {
	      return this.list ? ("undefined" != typeof b ? b !== this.list.toggle(a, b) && this.list.toggle(a) : this.list.toggle(a), this) : ("undefined" != typeof b ? b ? this.add(a) : this.remove(a) : this.has(a) ? this.remove(a) : this.add(a), this);
	    }, d.prototype.array = function () {
	      var a = this.el.className.replace(/^\s+|\s+$/g, ""),
	          b = a.split(f);
	      return "" === b[0] && b.shift(), b;
	    }, d.prototype.has = d.prototype.contains = function (a) {
	      return this.list ? this.list.contains(a) : !!~e(this.array(), a);
	    };
	  }), a.register("segmentio-extend/index.js", function (a, b, c) {
	    c.exports = function (a) {
	      for (var b, c = Array.prototype.slice.call(arguments, 1), d = 0; b = c[d]; d++) {
	        if (b) for (var e in b) {
	          a[e] = b[e];
	        }
	      }return a;
	    };
	  }), a.register("component-indexof/index.js", function (a, b, c) {
	    c.exports = function (a, b) {
	      if (a.indexOf) return a.indexOf(b);
	      for (var c = 0; c < a.length; ++c) {
	        if (a[c] === b) return c;
	      }return -1;
	    };
	  }), a.register("component-event/index.js", function (a) {
	    var b = window.addEventListener ? "addEventListener" : "attachEvent",
	        c = window.removeEventListener ? "removeEventListener" : "detachEvent",
	        d = "addEventListener" !== b ? "on" : "";
	    a.bind = function (a, c, e, f) {
	      return a[b](d + c, e, f || !1), e;
	    }, a.unbind = function (a, b, e, f) {
	      return a[c](d + b, e, f || !1), e;
	    };
	  }), a.register("timoxley-to-array/index.js", function (a, b, c) {
	    function d(a) {
	      return "[object Array]" === Object.prototype.toString.call(a);
	    }
	    c.exports = function (a) {
	      if ("undefined" == typeof a) return [];
	      if (null === a) return [null];
	      if (a === window) return [window];
	      if ("string" == typeof a) return [a];
	      if (d(a)) return a;
	      if ("number" != typeof a.length) return [a];
	      if ("function" == typeof a && a instanceof Function) return [a];
	      for (var b = [], c = 0; c < a.length; c++) {
	        (Object.prototype.hasOwnProperty.call(a, c) || c in a) && b.push(a[c]);
	      }return b.length ? b : [];
	    };
	  }), a.register("javve-events/index.js", function (a, b) {
	    var c = b("event"),
	        d = b("to-array");
	    a.bind = function (a, b, e, f) {
	      a = d(a);
	      for (var g = 0; g < a.length; g++) {
	        c.bind(a[g], b, e, f);
	      }
	    }, a.unbind = function (a, b, e, f) {
	      a = d(a);
	      for (var g = 0; g < a.length; g++) {
	        c.unbind(a[g], b, e, f);
	      }
	    };
	  }), a.register("javve-get-by-class/index.js", function (a, b, c) {
	    c.exports = function () {
	      return document.getElementsByClassName ? function (a, b, c) {
	        return c ? a.getElementsByClassName(b)[0] : a.getElementsByClassName(b);
	      } : document.querySelector ? function (a, b, c) {
	        return b = "." + b, c ? a.querySelector(b) : a.querySelectorAll(b);
	      } : function (a, b, c) {
	        var d = [],
	            e = "*";
	        null == a && (a = document);
	        for (var f = a.getElementsByTagName(e), g = f.length, h = new RegExp("(^|\\s)" + b + "(\\s|$)"), i = 0, j = 0; g > i; i++) {
	          if (h.test(f[i].className)) {
	            if (c) return f[i];
	            d[j] = f[i], j++;
	          }
	        }return d;
	      };
	    }();
	  }), a.register("javve-get-attribute/index.js", function (a, b, c) {
	    c.exports = function (a, b) {
	      var c = a.getAttribute && a.getAttribute(b) || null;
	      if (!c) for (var d = a.attributes, e = d.length, f = 0; e > f; f++) {
	        void 0 !== b[f] && b[f].nodeName === b && (c = b[f].nodeValue);
	      }return c;
	    };
	  }), a.register("javve-natural-sort/index.js", function (a, b, c) {
	    c.exports = function (a, b, c) {
	      var d,
	          e,
	          f = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
	          g = /(^[ ]*|[ ]*$)/g,
	          h = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
	          i = /^0x[0-9a-f]+$/i,
	          j = /^0/,
	          c = c || {},
	          k = function k(a) {
	        return c.insensitive && ("" + a).toLowerCase() || "" + a;
	      },
	          l = k(a).replace(g, "") || "",
	          m = k(b).replace(g, "") || "",
	          n = l.replace(f, "\x00$1\x00").replace(/\0$/, "").replace(/^\0/, "").split("\x00"),
	          o = m.replace(f, "\x00$1\x00").replace(/\0$/, "").replace(/^\0/, "").split("\x00"),
	          p = parseInt(l.match(i)) || 1 != n.length && l.match(h) && Date.parse(l),
	          q = parseInt(m.match(i)) || p && m.match(h) && Date.parse(m) || null,
	          r = c.desc ? -1 : 1;
	      if (q) {
	        if (q > p) return -1 * r;
	        if (p > q) return 1 * r;
	      }
	      for (var s = 0, t = Math.max(n.length, o.length); t > s; s++) {
	        if (d = !(n[s] || "").match(j) && parseFloat(n[s]) || n[s] || 0, e = !(o[s] || "").match(j) && parseFloat(o[s]) || o[s] || 0, isNaN(d) !== isNaN(e)) return isNaN(d) ? 1 : -1;
	        if ((typeof d === 'undefined' ? 'undefined' : _typeof(d)) != (typeof e === 'undefined' ? 'undefined' : _typeof(e)) && (d += "", e += ""), e > d) return -1 * r;
	        if (d > e) return 1 * r;
	      }
	      return 0;
	    };
	  }), a.register("javve-to-string/index.js", function (a, b, c) {
	    c.exports = function (a) {
	      return a = void 0 === a ? "" : a, a = null === a ? "" : a, a = a.toString();
	    };
	  }), a.register("component-type/index.js", function (a, b, c) {
	    var d = Object.prototype.toString;
	    c.exports = function (a) {
	      switch (d.call(a)) {
	        case "[object Date]":
	          return "date";
	        case "[object RegExp]":
	          return "regexp";
	        case "[object Arguments]":
	          return "arguments";
	        case "[object Array]":
	          return "array";
	        case "[object Error]":
	          return "error";
	      }
	      return null === a ? "null" : void 0 === a ? "undefined" : a !== a ? "nan" : a && 1 === a.nodeType ? "element" : _typeof(a.valueOf());
	    };
	  }), a.register("list.js/index.js", function (a, b, c) {
	    !function (a, d) {
	      "use strict";

	      var e = a.document,
	          f = b("get-by-class"),
	          g = b("extend"),
	          h = b("indexof"),
	          i = function i(a, c, j) {
	        var k,
	            l = this,
	            m = b("./src/item")(l),
	            n = b("./src/add-async")(l),
	            o = b("./src/parse")(l);
	        k = {
	          start: function start() {
	            l.listClass = "list", l.searchClass = "search", l.sortClass = "sort", l.page = 200, l.i = 1, l.items = [], l.visibleItems = [], l.matchingItems = [], l.searched = !1, l.filtered = !1, l.handlers = {
	              updated: []
	            }, l.plugins = {}, l.helpers = {
	              getByClass: f,
	              extend: g,
	              indexOf: h
	            }, g(l, c), l.listContainer = "string" == typeof a ? e.getElementById(a) : a, l.listContainer && (l.list = f(l.listContainer, l.listClass, !0), l.templater = b("./src/templater")(l), l.search = b("./src/search")(l), l.filter = b("./src/filter")(l), l.sort = b("./src/sort")(l), this.items(), l.update(), this.plugins());
	          },
	          items: function items() {
	            o(l.list), j !== d && l.add(j);
	          },
	          plugins: function plugins() {
	            for (var a = 0; a < l.plugins.length; a++) {
	              var b = l.plugins[a];
	              l[b.name] = b, b.init(l, i);
	            }
	          }
	        }, this.add = function (a, b) {
	          if (b) return n(a, b), void 0;
	          var c = [],
	              e = !1;
	          a[0] === d && (a = [a]);
	          for (var f = 0, g = a.length; g > f; f++) {
	            var h = null;
	            a[f] instanceof m ? (h = a[f], h.reload()) : (e = l.items.length > l.page ? !0 : !1, h = new m(a[f], d, e)), l.items.push(h), c.push(h);
	          }
	          return l.update(), c;
	        }, this.show = function (a, b) {
	          return this.i = a, this.page = b, l.update(), l;
	        }, this.remove = function (a, b, c) {
	          for (var d = 0, e = 0, f = l.items.length; f > e; e++) {
	            l.items[e].values()[a] == b && (l.templater.remove(l.items[e], c), l.items.splice(e, 1), f--, e--, d++);
	          }return l.update(), d;
	        }, this.get = function (a, b) {
	          for (var c = [], d = 0, e = l.items.length; e > d; d++) {
	            var f = l.items[d];
	            f.values()[a] == b && c.push(f);
	          }
	          return c;
	        }, this.size = function () {
	          return l.items.length;
	        }, this.clear = function () {
	          return l.templater.clear(), l.items = [], l;
	        }, this.on = function (a, b) {
	          return l.handlers[a].push(b), l;
	        }, this.off = function (a, b) {
	          var c = l.handlers[a],
	              d = h(c, b);
	          return d > -1 && c.splice(d, 1), l;
	        }, this.trigger = function (a) {
	          for (var b = l.handlers[a].length; b--;) {
	            l.handlers[a][b](l);
	          }return l;
	        }, this.reset = {
	          filter: function filter() {
	            console.log("FILTER-SEARCH-BEG - l.items", l.items);
	            for (var a = l.items, b = a.length; b--;) {
	              a[b].filtered = !1;
	            }console.log("FILTER-SEARCH-END - l", l);
	            return l;
	          },
	          search: function search() {
	            console.log("LIST-SEARCH-BEG - l.items", l.items);
	            for (var a = l.items, b = a.length; b--;) {
	              a[b].found = !1;
	            }console.log("LIST-SEARCH-END - l", l);
	            return l;
	          }
	        }, this.update = function () {
	          var a = l.items,
	              b = a.length;
	          l.visibleItems = [], l.matchingItems = [], l.templater.clear();
	          for (var c = 0; b > c; c++) {
	            a[c].matching() && l.matchingItems.length + 1 >= l.i && l.visibleItems.length < l.page ? (a[c].show(), l.visibleItems.push(a[c]), l.matchingItems.push(a[c])) : a[c].matching() ? (l.matchingItems.push(a[c]), a[c].hide()) : a[c].hide();
	          }return l.trigger("updated"), l;
	        }, k.start();
	      };
	      c.exports = i;
	    }(window);
	  }), a.register("list.js/src/search.js", function (a, b, c) {
	    var d = b("events"),
	        e = b("get-by-class"),
	        f = b("to-string");
	    c.exports = function (a) {
	      var b,
	          c,
	          g,
	          h,
	          i = {
	        resetList: function resetList() {
	          a.i = 1, a.templater.clear(), h = void 0;
	        },
	        setOptions: function setOptions(a) {
	          2 == a.length && a[1] instanceof Array ? c = a[1] : 2 == a.length && "function" == typeof a[1] ? h = a[1] : 3 == a.length && (c = a[1], h = a[2]);
	        },
	        setColumns: function setColumns() {
	          c = void 0 === c ? i.toArray(a.items[0].values()) : c;
	        },
	        setSearchString: function setSearchString(a) {
	          a = f(a).toLowerCase(), a = a.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"), g = a;
	        },
	        toArray: function toArray(a) {
	          var b = [];
	          for (var c in a) {
	            b.push(c);
	          }return b;
	        }
	      },
	          j = {
	        list: function list() {
	          for (var b = 0, c = a.items.length; c > b; b++) {
	            j.item(a.items[b]);
	          }
	        },
	        item: function item(a) {
	          a.found = !1;
	          for (var b = 0, d = c.length; d > b; b++) {
	            if (j.values(a.values(), c[b])) return a.found = !0, void 0;
	          }
	        },
	        values: function values(a, c) {
	          return a.hasOwnProperty(c) && (b = f(a[c]).toLowerCase(), "" !== g && b.search(g) > -1) ? !0 : !1;
	        },
	        reset: function reset() {
	          a.reset.search(), a.searched = !1;
	        }
	      },
	          k = function k(b) {
	        return a.trigger("searchStart"), i.resetList(), i.setSearchString(b), i.setOptions(arguments), i.setColumns(), "" === g ? j.reset() : (a.searched = !0, h ? h(g, c) : j.list()), a.update(), a.trigger("searchComplete"), a.visibleItems;
	      };
	      return a.handlers.searchStart = a.handlers.searchStart || [], a.handlers.searchComplete = a.handlers.searchComplete || [], d.bind(e(a.listContainer, a.searchClass), "keyup", function (b) {
	        var c = b.target || b.srcElement,
	            d = "" === c.value && !a.searched;
	        d || k(c.value);
	      }), d.bind(e(a.listContainer, a.searchClass), "input", function (a) {
	        var b = a.target || a.srcElement;
	        "" === b.value && k("");
	      }), a.helpers.toString = f, k;
	    };
	  }), a.register("list.js/src/sort.js", function (a, b, c) {
	    var d = b("natural-sort"),
	        e = b("classes"),
	        f = b("events"),
	        g = b("get-by-class"),
	        h = b("get-attribute");
	    c.exports = function (a) {
	      a.sortFunction = a.sortFunction || function (a, b, c) {
	        return c.desc = "desc" == c.order ? !0 : !1, d(a.values()[c.valueName], b.values()[c.valueName], c);
	      };
	      var b = {
	        els: void 0,
	        clear: function clear() {
	          for (var a = 0, c = b.els.length; c > a; a++) {
	            e(b.els[a]).remove("asc"), e(b.els[a]).remove("desc");
	          }
	        },
	        getOrder: function getOrder(a) {
	          var b = h(a, "data-order");
	          return "asc" == b || "desc" == b ? b : e(a).has("desc") ? "asc" : e(a).has("asc") ? "desc" : "asc";
	        },
	        getInSensitive: function getInSensitive(a, b) {
	          var c = h(a, "data-insensitive");
	          b.insensitive = "true" === c ? !0 : !1;
	        },
	        setOrder: function setOrder(a) {
	          for (var c = 0, d = b.els.length; d > c; c++) {
	            var f = b.els[c];
	            if (h(f, "data-sort") === a.valueName) {
	              var g = h(f, "data-order");
	              "asc" == g || "desc" == g ? g == a.order && e(f).add(a.order) : e(f).add(a.order);
	            }
	          }
	        }
	      },
	          c = function c() {
	        a.trigger("sortStart"), options = {};
	        var c = arguments[0].currentTarget || arguments[0].srcElement || void 0;
	        c ? (options.valueName = h(c, "data-sort"), b.getInSensitive(c, options), options.order = b.getOrder(c)) : (options = arguments[1] || options, options.valueName = arguments[0], options.order = options.order || "asc", options.insensitive = "undefined" == typeof options.insensitive ? !0 : options.insensitive), b.clear(), b.setOrder(options), options.sortFunction = options.sortFunction || a.sortFunction, a.items.sort(function (a, b) {
	          return options.sortFunction(a, b, options);
	        }), a.update(), a.trigger("sortComplete");
	      };
	      return a.handlers.sortStart = a.handlers.sortStart || [], a.handlers.sortComplete = a.handlers.sortComplete || [], b.els = g(a.listContainer, a.sortClass), f.bind(b.els, "click", c), a.on("searchStart", b.clear), a.on("filterStart", b.clear), a.helpers.classes = e, a.helpers.naturalSort = d, a.helpers.events = f, a.helpers.getAttribute = h, c;
	    };
	  }), a.register("list.js/src/item.js", function (a, b, c) {
	    c.exports = function (a) {
	      return function (b, c, d) {
	        var e = this;
	        this._values = {}, this.found = !1, this.filtered = !1;
	        var f = function f(b, c, d) {
	          if (void 0 === c) d ? e.values(b, d) : e.values(b);else {
	            e.elm = c;
	            var f = a.templater.get(e, b);
	            e.values(f);
	          }
	        };
	        this.values = function (b, c) {
	          if (void 0 === b) return e._values;
	          for (var d in b) {
	            e._values[d] = b[d];
	          }c !== !0 && a.templater.set(e, e.values());
	        }, this.show = function () {
	          a.templater.show(e);
	        }, this.hide = function () {
	          a.templater.hide(e);
	        }, this.matching = function () {
	          return a.filtered && a.searched && e.found && e.filtered || a.filtered && !a.searched && e.filtered || !a.filtered && a.searched && e.found || !a.filtered && !a.searched;
	        }, this.visible = function () {
	          return e.elm.parentNode == a.list ? !0 : !1;
	        }, f(b, c, d);
	      };
	    };
	  }), a.register("list.js/src/templater.js", function (a, b, c) {
	    var d = b("get-by-class"),
	        e = function e(a) {
	      function b(b) {
	        if (void 0 === b) {
	          for (var c = a.list.childNodes, d = 0, e = c.length; e > d; d++) {
	            if (void 0 === c[d].data) return c[d];
	          }return null;
	        }
	        if (-1 !== b.indexOf("<")) {
	          var f = document.createElement("div");
	          return f.innerHTML = b, f.firstChild;
	        }
	        return document.getElementById(a.item);
	      }
	      var c = b(a.item),
	          e = this;
	      this.get = function (a, b) {
	        e.create(a);
	        for (var c = {}, f = 0, g = b.length; g > f; f++) {
	          var h = d(a.elm, b[f], !0);
	          c[b[f]] = h ? h.innerHTML : "";
	        }
	        return c;
	      }, this.set = function (a, b) {
	        if (!e.create(a)) for (var c in b) {
	          if (b.hasOwnProperty(c)) {
	            var f = d(a.elm, c, !0);
	            f && ("IMG" === f.tagName && "" !== b[c] ? f.src = b[c] : f.innerHTML = b[c]);
	          }
	        }
	      }, this.create = function (a) {
	        if (void 0 !== a.elm) return !1;
	        var b = c.cloneNode(!0);
	        return b.removeAttribute("id"), a.elm = b, e.set(a, a.values()), !0;
	      }, this.remove = function (b) {
	        a.list.removeChild(b.elm);
	      }, this.show = function (b) {
	        e.create(b), a.list.appendChild(b.elm);
	      }, this.hide = function (b) {
	        void 0 !== b.elm && b.elm.parentNode === a.list && a.list.removeChild(b.elm);
	      }, this.clear = function () {
	        if (a.list.hasChildNodes()) for (; a.list.childNodes.length >= 1;) {
	          a.list.removeChild(a.list.firstChild);
	        }
	      };
	    };
	    c.exports = function (a) {
	      return new e(a);
	    };
	  }), a.register("list.js/src/filter.js", function (a, b, c) {
	    c.exports = function (a) {
	      return a.handlers.filterStart = a.handlers.filterStart || [], a.handlers.filterComplete = a.handlers.filterComplete || [], function (b) {
	        if (a.trigger("filterStart"), a.i = 1, a.reset.filter(), void 0 === b) a.filtered = !1;else {
	          a.filtered = !0;
	          for (var c = a.items, d = 0, e = c.length; e > d; d++) {
	            var f = c[d];
	            f.filtered = b(f) ? !0 : !1;
	          }
	        }
	        return a.update(), a.trigger("filterComplete"), a.visibleItems;
	      };
	    };
	  }), a.register("list.js/src/add-async.js", function (a, b, c) {
	    c.exports = function (a) {
	      return function (b, c, d) {
	        var e = b.splice(0, 100);
	        d = d || [], d = d.concat(a.add(e)), b.length > 0 ? setTimeout(function () {
	          addAsync(b, c, d);
	        }, 10) : (a.update(), c(d));
	      };
	    };
	  }), a.register("list.js/src/parse.js", function (a, b, c) {
	    c.exports = function (a) {
	      var c = b("./item")(a),
	          d = function d(a) {
	        for (var b = a.childNodes, c = [], d = 0, e = b.length; e > d; d++) {
	          void 0 === b[d].data && c.push(b[d]);
	        }return c;
	      },
	          e = function e(b, d) {
	        for (var e = 0, f = b.length; f > e; e++) {
	          a.items.push(new c(d, b[e]));
	        }
	      },
	          f = function f(b, c) {
	        var d = b.splice(0, 100);
	        e(d, c), b.length > 0 ? setTimeout(function () {
	          init.items.indexAsync(b, c);
	        }, 10) : a.update();
	      };
	      return function () {
	        var b = d(a.list),
	            c = a.valueNames;
	        a.indexAsync ? f(b, c) : e(b, c);
	      };
	    };
	  }), a.alias("component-classes/index.js", "list.js/deps/classes/index.js"), a.alias("component-classes/index.js", "classes/index.js"), a.alias("component-indexof/index.js", "component-classes/deps/indexof/index.js"), a.alias("segmentio-extend/index.js", "list.js/deps/extend/index.js"), a.alias("segmentio-extend/index.js", "extend/index.js"), a.alias("component-indexof/index.js", "list.js/deps/indexof/index.js"), a.alias("component-indexof/index.js", "indexof/index.js"), a.alias("javve-events/index.js", "list.js/deps/events/index.js"), a.alias("javve-events/index.js", "events/index.js"), a.alias("component-event/index.js", "javve-events/deps/event/index.js"), a.alias("timoxley-to-array/index.js", "javve-events/deps/to-array/index.js"), a.alias("javve-get-by-class/index.js", "list.js/deps/get-by-class/index.js"), a.alias("javve-get-by-class/index.js", "get-by-class/index.js"), a.alias("javve-get-attribute/index.js", "list.js/deps/get-attribute/index.js"), a.alias("javve-get-attribute/index.js", "get-attribute/index.js"), a.alias("javve-natural-sort/index.js", "list.js/deps/natural-sort/index.js"), a.alias("javve-natural-sort/index.js", "natural-sort/index.js"), a.alias("javve-to-string/index.js", "list.js/deps/to-string/index.js"), a.alias("javve-to-string/index.js", "list.js/deps/to-string/index.js"), a.alias("javve-to-string/index.js", "to-string/index.js"), a.alias("javve-to-string/index.js", "javve-to-string/index.js"), a.alias("component-type/index.js", "list.js/deps/type/index.js"), a.alias("component-type/index.js", "type/index.js"), "object" == ( false ? 'undefined' : _typeof(exports)) ? module.exports = a("list.js") :  true ? !(__WEBPACK_AMD_DEFINE_RESULT__ = function () {
	    return a("list.js");
	  }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : this.List = a("list.js");
	}();

/***/ },
/* 449 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _marked = __webpack_require__(369);

	var _marked2 = _interopRequireDefault(_marked);

	var _sortablejs = __webpack_require__(414);

	var _sortablejs2 = _interopRequireDefault(_sortablejs);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var ProjectSessionForm = function () {
	  function ProjectSessionForm() {
	    _classCallCheck(this, ProjectSessionForm);

	    if ((0, _jquery2.default)(".project_session_form").length > 0) {
	      this._bindProject();
	      (0, _jquery2.default)(document).on('change', '#project_session_commit', this._disableVersionedFields);
	    }
	    if ((0, _jquery2.default)(".new_scale, .edit_scale").length > 0) this._bindScale();
	    if ((0, _jquery2.default)("#project_authors_user_ids").length > 0) this._select2ProjectForn();
	  }

	  _createClass(ProjectSessionForm, [{
	    key: '_bindProject',
	    value: function _bindProject() {
	      this._initRules();
	    }
	  }, {
	    key: '_disableVersionedFields',
	    value: function _disableVersionedFields() {
	      var commit = document.getElementById('project_session_commit');
	      var disabled = Boolean(commit && commit.value);
	      var attributes = ['solo', 'difficulty', 'estimate_time', 'duration_days', 'skill'];
	      attributes.forEach(function (attribute) {
	        (0, _jquery2.default)('#project_session_' + attribute).prop("disabled", disabled).trigger("chosen:updated");
	      });
	      if (disabled) {
	        document.getElementsByClassName('project-session-skills')[0].style.opacity = 0.5;
	        document.getElementsByClassName('project-session-skills')[0].style.cursor = 'not-allowed';
	      } else {
	        document.getElementsByClassName('project-session-skills')[0].style.opacity = 1;
	        document.getElementsByClassName('project-session-skills')[0].style.cursor = 'initial';
	      }
	    }
	  }, {
	    key: '_initRules',
	    value: function _initRules() {
	      (0, _jquery2.default)(".rules_select").each(this._setRuleTemplate);
	      (0, _jquery2.default)(document).on('change', '.rules_select', this._setRuleTemplate);
	      this._bindCodeModal();
	      this._bindSortableRules();
	    }
	  }, {
	    key: '_setRuleTemplate',
	    value: function _setRuleTemplate() {
	      var ruleTemplate = _lodash2.default.template('\n      <div class="row">\n        <div class="col-sm-2">\n          <span class="rule-kind <%= kind %>"><%= kind %></span>\n        </div>\n        <div class="col-sm-10 rule-desc">\n          <span>\n            <b><%= name %></b>\n          </span>\n          \u2013\n          <small>\n            <%= readable || \'No description\' %>\n          </small>\n        </div>\n      </div>\n    ');
	      var desc = (0, _jquery2.default)(this).parents(".project-opts").children(".rule-description").first();
	      var selected = _lodash2.default.find(rules_description, { id: parseInt((0, _jquery2.default)(this).val()) });
	      if (selected && selected["kind"] && selected["name"]) {
	        desc.html(ruleTemplate(selected));
	      }
	    }
	  }, {
	    key: '_bindCodeModal',
	    value: function _bindCodeModal() {
	      (0, _jquery2.default)('ul.list-group').on('click', "a[id^='button_code_']", function () {
	        var modal_id = (0, _jquery2.default)(this).data().uid;
	        var rule_id = (0, _jquery2.default)(this).parents('.list-group-item').find('.rules_select').val();
	        var ct = (0, _jquery2.default)('.modal#rule_code_' + modal_id);

	        ct.find('#code').text('').hide();
	        ct.find('#not_found').hide();
	        ct.find('#text_loading').show();
	        ct.modal();
	        _jquery2.default.ajax({
	          url: '/rules/' + rule_id + '/code.json',
	          type: 'GET',
	          success: function success(d) {
	            ct.find('#code').html(d.code).show();
	            ct.find('#text_loading').hide();
	          },
	          error: function error(d) {
	            ct.find('#text_loading').hide();
	            ct.find('#not_found').show();
	          }
	        });
	      });
	    }
	  }, {
	    key: '_bindSortableRules',
	    value: function _bindSortableRules() {
	      (0, _jquery2.default)('ul.list-group.sortable-rules').each(function (index, el) {
	        var $ul = (0, _jquery2.default)(el);
	        _sortablejs2.default.create(el, {
	          onSort: function onSort() {
	            $ul.children('li').each(function (index, el) {
	              (0, _jquery2.default)(el).find('.project_session_project_sessions_rules_position').find('input').val(index + 1);
	              (0, _jquery2.default)(el).find('.rule-position').text(index + 1);
	            });
	          }
	        });
	      });
	    }
	  }]);

	  return ProjectSessionForm;
	}();

	exports.default = ProjectSessionForm;

/***/ },
/* 450 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _list = __webpack_require__(448);

	var _list2 = _interopRequireDefault(_list);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var ProjectUserList = function () {
	  function ProjectUserList() {
	    _classCallCheck(this, ProjectUserList);

	    this.OPTIONS = ["project-user--user", "project-user--startedat", "project-user--mark"];
	    this.SELECTOR = "projectuser-list-container";

	    if ((0, _jquery2.default)('#' + this.SELECTOR).length === 0) return;

	    this.options = {
	      valueNames: this.OPTIONS,
	      sortFunction: this._sort.bind(this, this._cmp),
	      page: 500
	    };

	    this.projectUserList = new _list2.default(this.SELECTOR, this.options);
	    this._bindSearch();
	    this._bindFilters();
	  }

	  _createClass(ProjectUserList, [{
	    key: '_bindSearch',
	    value: function _bindSearch() {
	      var _this = this;

	      var elt = document.getElementsByClassName("projects-list--search")[0];
	      if (elt) {
	        elt.addEventListener('keyup', function (_) {
	          _this.projectUserList.search(elt.value, ['project-user--user', 'project-user--mark']);
	        });
	      }
	    }
	  }, {
	    key: '_bindFilters',
	    value: function _bindFilters() {
	      var header = document.getElementsByClassName("projects-list--header")[0];

	      if (header) {
	        var _iteratorNormalCompletion = true;
	        var _didIteratorError = false;
	        var _iteratorError = undefined;

	        try {
	          for (var _iterator = header.getElementsByClassName("filter-trigger")[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	            var trigger = _step.value;

	            trigger.addEventListener('click', this._filter(trigger));
	          }
	        } catch (err) {
	          _didIteratorError = true;
	          _iteratorError = err;
	        } finally {
	          try {
	            if (!_iteratorNormalCompletion && _iterator.return) {
	              _iterator.return();
	            }
	          } finally {
	            if (_didIteratorError) {
	              throw _iteratorError;
	            }
	          }
	        }
	      }
	    }
	  }, {
	    key: '_filter',
	    value: function _filter(elt) {
	      var _this2 = this;

	      return function (evt) {
	        if (elt.classList.contains("active")) {
	          elt.classList.remove("active");
	          elt.parentElement.getElementsByClassName("filter-trigger")[0].classList.add("active");
	          _this2.projectUserList.filter(_this2._filterClear);
	        } else {
	          var _iteratorNormalCompletion2 = true;
	          var _didIteratorError2 = false;
	          var _iteratorError2 = undefined;

	          try {
	            for (var _iterator2 = elt.parentElement.getElementsByClassName("filter-trigger")[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
	              var trigger = _step2.value;

	              trigger.classList.remove("active");
	            }
	          } catch (err) {
	            _didIteratorError2 = true;
	            _iteratorError2 = err;
	          } finally {
	            try {
	              if (!_iteratorNormalCompletion2 && _iterator2.return) {
	                _iterator2.return();
	              }
	            } finally {
	              if (_didIteratorError2) {
	                throw _iteratorError2;
	              }
	            }
	          }

	          elt.classList.add("active");
	          var meth = _this2['_filter' + _lodash2.default.capitalize(_lodash2.default.camelCase(elt.attributes.getNamedItem("data-filter").value))];
	          _this2.projectUserList.filter(_this2._filterProjectUserList);
	        }
	      };
	    }
	  }, {
	    key: '_escapeValue',
	    value: function _escapeValue(value) {
	      _lodash2.default.snakeCase(_lodash2.default.trim(_lodash2.default.deburr(value)));
	    }
	  }, {
	    key: '_cmp',
	    value: function _cmp(e, key) {
	      return e.elm.attributes.getNamedItem('data-' + key).value + e.elm.attributes.getNamedItem("data-pu-user").value;
	    }
	  }, {
	    key: '_sort',
	    value: function _sort(_cmp, a, b, c) {
	      var order = c.order == "asc" ? 1 : -1;

	      if (_cmp(a, c.valueName) < _cmp(b, c.valueName)) return -1 * order;else if (_cmp(a, c.valueName) > _cmp(b, c.valueName)) return 1 * order;else return 0;
	    }

	    // On measure projects

	  }, {
	    key: '_filterProjectUserList',
	    value: function _filterProjectUserList(item) {
	      var filter = (0, _jquery2.default)(".filter-trigger.active").data("filter");
	      if (!filter || filter == "clear") return true;else return item.elm.attributes.getNamedItem("data-status").value == filter;
	    }
	  }, {
	    key: '_filterClear',
	    value: function _filterClear(item) {
	      return true;
	    }
	  }]);

	  return ProjectUserList;
	}();

	exports.default = ProjectUserList;

/***/ },
/* 451 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Radios = function () {
	  function Radios() {
	    _classCallCheck(this, Radios);

	    var self = this;
	    (0, _jquery2.default)("[data-radio-item] label").each(function () {
	      var _this = this;

	      var s = this;

	      (0, _jquery2.default)('#' + (0, _jquery2.default)(this).attr('for')).on('change', function (_) {
	        return self._activate(s);
	      });
	      (0, _jquery2.default)(this).on("click", function (_) {
	        return self._activate(_this);
	      });
	    });
	  }

	  _createClass(Radios, [{
	    key: '_activate',
	    value: function _activate(e) {
	      var item = (0, _jquery2.default)(e).parent().attr('data-radio-item');

	      (0, _jquery2.default)('[data-radio-item=\'' + item + '\'] label').removeClass("active");
	      (0, _jquery2.default)(e).addClass("active");
	      if ((0, _jquery2.default)(e).hasClass("negative")) (0, _jquery2.default)(".scale-section-answers").addClass("hidden");else (0, _jquery2.default)(".scale-section-answers").removeClass("hidden");
	    }
	  }]);

	  return Radios;
	}();

	exports.default = Radios;

/***/ },
/* 452 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _highcharts = __webpack_require__(318);

	var _highcharts2 = _interopRequireDefault(_highcharts);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	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"); } }

	var Chart = function () {
	  function Chart() {
	    _classCallCheck(this, Chart);

	    if (!(0, _jquery2.default)("#project-chart-success").length) return;
	    (0, _jquery2.default)("[data-toggle=tooltip]").tooltip();
	    var self = this;
	    _highcharts2.default.theme = {
	      colors: ['#00babc', '#D84869', '#5CB85C', '#E6B291', '#B378E6', '#0583F2', '#3F4351'],
	      title: {
	        style: {
	          color: '#000',
	          font: '16px "Noto Sans", sans-serif'
	        }
	      },
	      subtitle: {
	        style: {
	          color: '#666',
	          font: '12px "Noto Sans", sans-serif'
	        }
	      },
	      credits: {
	        enabled: false
	      },
	      legend: {
	        itemStyle: {
	          font: '10px "Noto Sans", sans-serif',
	          color: '#666'
	        }
	      }
	    };
	    _highcharts2.default.setOptions(_highcharts2.default.theme);
	    var id = window.location.pathname.split('/')[2];
	    _jquery2.default.getJSON('/projects/' + id + '/stats.json' + window.location.search, function (json) {
	      self.drawSuccessChart(json.success);
	      self.drawFinalmarkByCampusChart(json.final_mark_by_campus);
	      self.drawTeamLifespanChart(json.average_team_lifespan);
	      self.drawFlagsChart(json.flags);
	    });
	  }

	  _createClass(Chart, [{
	    key: 'drawFlagsChart',
	    value: function drawFlagsChart(data) {
	      if (data.length <= 1) {
	        (0, _jquery2.default)('#project-chart-flags').remove();
	        return;
	      }
	      var _iteratorNormalCompletion = true;
	      var _didIteratorError = false;
	      var _iteratorError = undefined;

	      try {
	        for (var _iterator = data[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	          var item = _step.value;

	          if (item.name == 'Ok' || item.name == "Outstanding project") item.color = '#00babc';else item.color = '#D84869';
	        }
	      } catch (err) {
	        _didIteratorError = true;
	        _iteratorError = err;
	      } finally {
	        try {
	          if (!_iteratorNormalCompletion && _iterator.return) {
	            _iterator.return();
	          }
	        } finally {
	          if (_didIteratorError) {
	            throw _iteratorError;
	          }
	        }
	      }

	      (0, _jquery2.default)("#project-chart-flags").highcharts({
	        chart: {
	          plotBackgroundColor: null,
	          plotBorderWidth: null,
	          plotShadow: false,
	          type: 'pie'
	        },
	        title: {
	          text: 'Flag distribution'
	        },
	        tooltip: {
	          pointFormat: 'Evaluations: <b>{point.y}</b>'
	        },
	        plotOptions: {
	          pie: {
	            cursor: 'pointer',
	            dataLabels: {
	              enabled: true,
	              format: '{point.name}: <b>{point.percentage:.1f}%</b>'
	            }
	          }
	        },
	        series: [{
	          colorByPoint: true,
	          data: data
	        }]
	      });
	    }
	  }, {
	    key: 'drawFinalmarkByCampusChart',
	    value: function drawFinalmarkByCampusChart(data) {
	      var any_mark_exists = data.find(function (a) {
	        return a.data.length > 0;
	      });
	      if (!any_mark_exists) {
	        (0, _jquery2.default)("#project-chart-finalmark-by-campus").remove();
	        return;
	      }
	      var _iteratorNormalCompletion2 = true;
	      var _didIteratorError2 = false;
	      var _iteratorError2 = undefined;

	      try {
	        for (var _iterator2 = data[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
	          var item = _step2.value;

	          var _loop = function _loop(i) {
	            var found = item.data.find(function (a) {
	              return a[0] == i * 10;
	            });
	            if (found === undefined) item.data.push([i * 10, 0]);
	          };

	          for (var i = 0; i <= 12; i++) {
	            _loop(i);
	          }
	          item.data.sort(function (a, b) {
	            return a[0] - b[0];
	          });
	        }
	      } catch (err) {
	        _didIteratorError2 = true;
	        _iteratorError2 = err;
	      } finally {
	        try {
	          if (!_iteratorNormalCompletion2 && _iterator2.return) {
	            _iterator2.return();
	          }
	        } finally {
	          if (_didIteratorError2) {
	            throw _iteratorError2;
	          }
	        }
	      }

	      (0, _jquery2.default)("#project-chart-finalmark-by-campus").highcharts({
	        chart: {
	          type: 'area'
	        },
	        title: {
	          text: 'Marks by campus'
	        },
	        tooltip: {
	          useHTML: true,
	          pointFormat: '<b>{series.name}</b> mark: <b>~{point.x}</b> users: <b>{point.y:.1f}%</b></br>',
	          shared: true
	        },
	        xAxis: {
	          min: 0,
	          max: 125,
	          title: {
	            text: 'Grade'
	          }
	        },
	        yAxis: _defineProperty({
	          min: 0,
	          max: 100,
	          title: {
	            text: 'Percent of users'
	          }
	        }, 'min', 0),
	        series: data
	      });
	    }
	  }, {
	    key: 'drawSuccessChart',
	    value: function drawSuccessChart(data) {
	      if (!data.true && !data.false) {
	        (0, _jquery2.default)("#project-chart-success").remove();
	        return;
	      }
	      (0, _jquery2.default)("#project-chart-success").highcharts({
	        chart: {
	          plotBackgroundColor: null,
	          plotBorderWidth: null,
	          plotShadow: false,
	          type: 'pie'
	        },
	        title: {
	          text: 'Success Rate'
	        },
	        tooltip: {
	          pointFormat: 'users: <b>{point.y}</b>'
	        },
	        plotOptions: {
	          pie: {
	            cursor: 'pointer',
	            dataLabels: {
	              enabled: true,
	              format: '{point.name}: <b>{point.percentage:.1f}%</b>'
	            }
	          }
	        },
	        series: [{
	          colorByPoint: true,
	          data: [{
	            name: 'No grade yet',
	            y: data.none || 0,
	            color: '#ccc'
	          }, {
	            name: 'Success',
	            y: data.true || 0,
	            color: '#00babc'
	          }, {
	            name: 'Fail',
	            y: data.false || 0,
	            color: '#D8636F'
	          }]
	        }]
	      });
	    }
	  }, {
	    key: 'drawTeamLifespanChart',
	    value: function drawTeamLifespanChart(data) {
	      if (!data.none && !data.true && !data.false) {
	        (0, _jquery2.default)('#project-chart-team-lifespan').remove();
	        return;
	      }
	      (0, _jquery2.default)("#project-chart-team-lifespan").highcharts({
	        chart: {
	          plotBackgroundColor: null,
	          plotBorderWidth: null,
	          plotShadow: false,
	          type: 'bar'
	        },
	        title: {
	          text: 'Average team lifespan'
	        },
	        tooltip: {
	          pointFormat: '<b>{point.y}</b> days'
	        },
	        legend: {
	          enabled: false
	        },
	        plotOptions: {
	          bar: {
	            groupPadding: 0
	          }
	        },
	        xAxis: {
	          categories: ['No grade yet', 'Success', 'Fail']
	        },
	        yAxis: {
	          title: {
	            text: 'Number of days between team lock and team close'
	          }
	        },
	        series: [{
	          colorByPoint: true,
	          maxPointWidth: 20,
	          data: [{
	            name: 'No grade yet',
	            y: data.none || 0,
	            color: '#ccc'
	          }, {
	            name: 'Success',
	            y: data.true || 0,
	            color: '#00babc'
	          }, {
	            name: 'Fail',
	            y: data.false || 0,
	            color: '#D8636F'
	          }]
	        }]
	      });
	    }
	  }]);

	  return Chart;
	}();

	exports.default = Chart;

/***/ },
/* 453 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _corejsTypeahead = __webpack_require__(211);

	var _corejsTypeahead2 = _interopRequireDefault(_corejsTypeahead);

	var _copy = __webpack_require__(417);

	var _copy2 = _interopRequireDefault(_copy);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Rules = function () {
	  function Rules() {
	    var _this = this;

	    _classCallCheck(this, Rules);

	    if ((0, _jquery2.default)('[data-select-url]').length === 0) return;
	    this.reg = /(([^ ]|\\ )*)$/;
	    this._save = '';
	    (0, _jquery2.default)('form .autocomplete').map(function (index, element) {
	      return _this._bindAutoComplete(element);
	    });
	    this.url = (0, _jquery2.default)("[data-select-url]").data("select-url");
	    (0, _jquery2.default)('.rules_select').each(function () {
	      if ((0, _jquery2.default)(this).find('option:checked').attr('value').length == 0) (0, _jquery2.default)(this).parents('.form-group').siblings('.params_fields').html("");
	    });
	    (0, _jquery2.default)('form').on('change', '.rules_select', function (e) {
	      return _this.changed(e.target);
	    });
	  }

	  _createClass(Rules, [{
	    key: '_bindAutoComplete',
	    value: function _bindAutoComplete(field) {
	      var _this2 = this;

	      var $field = (0, _jquery2.default)(field);
	      var bloodhound = new _corejsTypeahead2.default({
	        datumTokenizer: function datumTokenizer(datum) {
	          return _corejsTypeahead2.default.tokenizers.whitespace(datum.displayKey);
	        },
	        queryTokenizer: _corejsTypeahead2.default.tokenizers.whitespace,
	        remote: {
	          url: location.origin + '/completions.json' + '?query=%QUERY',
	          wildcard: '%QUERY',
	          prepare: function prepare(query, settings) {
	            query = query.substring(_this2.reg.exec(query).index);
	            settings.url = settings.url.replace('%QUERY', encodeURIComponent(query));
	            return settings;
	          },
	          transform: function transform(categories) {
	            var results = [];
	            for (var key in categories) {
	              _.map(categories[key], function (data) {
	                var obj = {};
	                obj['cat'] = key;
	                obj['value'] = data['slug'];
	                obj['name'] = data['name'];
	                results.push(obj);
	              });
	            }
	            return results;
	          }
	        }
	      });

	      bloodhound.initialize();
	      $field.typeahead({
	        highlight: false,
	        hint: false
	      }, {
	        limit: 15,
	        display: 'value',
	        source: bloodhound.ttAdapter(),
	        templates: {
	          suggestion: function suggestion(_suggestion) {
	            return '<p><span class=\'label label-primary\'> ' + _suggestion.cat + ' </span> &nbsp; ' + _suggestion.name + '</p>';
	          }
	        }
	      });

	      $field.on('typeahead:active, typeahead:idle', function (e) {
	        if ((0, _jquery2.default)(e.currentTarget).val()) (0, _jquery2.default)(e.currentTarget).val(_this2._value);
	      });

	      $field.on('typeahead:render', function (e) {
	        _this2._value = (0, _jquery2.default)(e.currentTarget).val();
	      });

	      $field.on('typeahead:cursorchange', function (e, obj) {
	        (0, _jquery2.default)(e.currentTarget).val(_this2._value);
	      });

	      $field.on('typeahead:select', function (e, obj) {
	        setTimeout(function (_) {
	          _this2._value = _this2._value.substring(0, _this2.reg.exec(_this2._value).index);
	          _this2._value += obj ? obj.value : '';
	          (0, _jquery2.default)(e.currentTarget).val(_this2._value);
	        }, 0);
	      });

	      $field.on('typeahead:change', function (e) {
	        setTimeout(function (_) {
	          if ((0, _jquery2.default)(e.currentTarget).val()) (0, _jquery2.default)(e.currentTarget).val(_this2._value);
	        }, 0);
	      });
	    }
	  }, {
	    key: 'changed',
	    value: function changed(elem) {
	      var _this3 = this;

	      var $container = (0, _jquery2.default)(elem).parents('.form-group').siblings('.params_fields');

	      var empty = function empty(_) {
	        $container.find('.autocomplete').typeahead('destroy');
	        $container.html("");
	      };

	      (0, _jquery2.default)('input[type="submit"]').attr('disabled', 'disabled');

	      fetch = function fetch(url) {
	        _jquery2.default.getJSON(url, function (data) {
	          (0, _jquery2.default)('input[type="submit"]').attr('disabled', false);
	          var $fields = (0, _jquery2.default)("<div class='row form-group input optional project_session_project_sessions_rules'></div>");
	          var basename = (0, _jquery2.default)(elem).attr("name");

	          _jquery2.default.each(data, function (index, param) {
	            var time = new Date().getTime();
	            var field = '<label class=\'select optional col-sm-2 control-label\' for=\'project_session_project_sessions_rules_attributes_params_attributes_' + time + '_rule_id\'>' + param.name + '</label>';
	            if (['projects', 'skill', 'cursus', 'quests'].indexOf(param.name) != -1) field += '\n            <div class=\'col-sm-10\'>\n                <input class=\'input optional autocomplete form-control\'\n                       data-completion-url=\'' + location.origin + '/completions.json\'\n                       value=\'' + param.default_value.replace(/(')/g, "&#39;") + '\'\n                       id=\'project_session_project_sessions_rules_attributes_params_attributes_' + time + '_value\'\n                       name=\'' + basename.replace('[rule_id]', '[params_project_sessions_rules_attributes][' + time + index + '][value]') + '\' />\n            </div>';else field += '\n            <div class=\'col-sm-10\'><input class=\'input optional form-control\'\n                           value=\'' + param.default_value.replace(/(')/g, "&#39;") + '\'\n                            id=\'project_session_project_sessions_rules_attributes_params_attributes_' + time + '_value\'\n                            name=\'' + basename.replace('[rule_id]', '[params_project_sessions_rules_attributes][' + time + index + '][value]') + '\' />\n            </div>';
	            field += '\n                <div class=\'col-sm-12\'>\n                    <input class=\'hidden optional form-control\'\n                           value=\'' + param.id + '\'\n                           name=\'' + basename.replace('[rule_id]', '[params_project_sessions_rules_attributes][' + time + index + '][param_id]') + '\' />\n                </div>';
	            $fields.append(field);
	          });
	          [].concat(_toConsumableArray($container.find(':input'))).forEach(function (e) {
	            if (/[0-9]_id$/.test(e['id']) && e.value) {
	              (0, _jquery2.default)(e).siblings(':input').remove();
	              var element = document.createElement('input');
	              element.id = e.id.replace(/_id$/, '_destroy');
	              element.name = e.name.replace(/\[id\]$/, '[_destroy]');
	              element.type = 'hidden';
	              element.value = true;
	              e.parentElement.appendChild(element);
	            } else {
	              (0, _jquery2.default)(e).closest('.form-group').remove();
	            }
	          });
	          $container.append($fields);
	          $fields.find('.autocomplete').map(function (i, v) {
	            return _this3._bindAutoComplete(v);
	          });
	        });
	      };

	      if ((0, _jquery2.default)(elem).find('option:checked').attr('value').length == 0) empty($container);else fetch(this.url.replace(":id", (0, _jquery2.default)(elem).find('option:checked').attr('value')));
	    }
	  }]);

	  return Rules;
	}();

	exports.default = Rules;

/***/ },
/* 454 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	__webpack_require__(455);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Scales = function () {
	  function Scales() {
	    _classCallCheck(this, Scales);

	    if ((0, _jquery2.default)('.skillSummary').length === 0 && (0, _jquery2.default)('#feedback_form').length === 0) return;

	    this._sliderSlt = 'input[type="range"]';
	    this._skillSummaryCtnSlt = '.skillSummary';
	    this._typeInputInputSlt = '[data-skill-type]';
	    this._questionKindInputSlt = '[data-question-kind]';
	    this._addSkillStl = "[data-association='questions_skills'].add_nested_fields";

	    // cache summary skills
	    if ((0, _jquery2.default)('.skillSummary').length != 0) {
	      this._getSummarySkills();
	    }

	    //this._createSliders(); // create sliders

	    if ((0, _jquery2.default)('.skillSummary').length != 0) {
	      // update limits + Summary
	      this._bind(); // bind form events
	      (0, _jquery2.default)(this._sliderSlt).parents('.form-group').show(); // show sliders row already loaded
	      this._updateLimits();
	      this._updateSummary();
	    }
	  }

	  // will create the slider and set max attribute depends of question kind


	  _createClass(Scales, [{
	    key: '_createSliders',
	    value: function _createSliders() {
	      var _this2 = this;

	      var _this = this;

	      (0, _jquery2.default)(this._sliderSlt).not('.slided').each(function (index, input) {
	        var $input = (0, _jquery2.default)(input);
	        var kind = $input.data('kind');

	        if (typeof $input.attr('max') === "undefined") $input.attr('max', kind == 'standard' ? 100 : 25);

	        $input.rangeslider({
	          polyfill: false,
	          onSlide: function onSlide() {
	            _this._checkLimit.apply(_this, _jquery2.default.merge(arguments, this.$element));
	          },
	          onSlideEnd: function onSlideEnd(_) {
	            if ((0, _jquery2.default)('.skillSummary').length != 0) {
	              _this2._updateLimits();
	              _this2._updateSummary();
	            }
	          }
	        });
	        $input.addClass('slided');
	      });
	    }

	    // will bind the DOM events

	  }, {
	    key: '_bind',
	    value: function _bind() {
	      var _this3 = this;

	      var _this = this;

	      (0, _jquery2.default)(document).on('change', _this._questionKindInputSlt, function (e) {
	        _this._onQuestionKindChange(e);
	      });
	      (0, _jquery2.default)(document).on('change', _this._typeInputInputSlt, function (e) {
	        _this._onSkillIdChange(e);
	      });

	      // when a skill is removed -> update limit + update summary
	      (0, _jquery2.default)(document).on('nested:fieldRemoved', function (_) {
	        _this3._updateLimits();
	        _this3._updateSummary();
	      });

	      // when a skill is added -> set kind attribute and create hidden slider
	      (0, _jquery2.default)(document).on('nested:fieldAdded:questions', function (e) {
	        e.field.find('' + _this._questionKindInputSlt).change();
	      });

	      // when a skill is added -> set kind attribute and create hidden slider
	      (0, _jquery2.default)(document).on('nested:fieldAdded:questions_skills', function (_) {
	        var $newSliders = (0, _jquery2.default)(_this._sliderSlt).not('.slided');
	        var kind = $newSliders.parents('.fields:eq(1)').find('' + _this._questionKindInputSlt).val();
	        $newSliders.data('kind', kind);
	        _this._createSliders();
	        $newSliders.parents('.fields:eq(0)').find('[data-skill-type]').change();
	      });
	    }

	    // when a questionKind change Then reset all sliders associated and show/add addSkill btn

	  }, {
	    key: '_onQuestionKindChange',
	    value: function _onQuestionKindChange(e) {
	      var $questionKindInput = (0, _jquery2.default)(e.currentTarget);
	      var $parentSelector = $questionKindInput.parents('.fields').first();
	      var $associatedSliders = $parentSelector.find(this._sliderSlt);

	      $associatedSliders.data('kind', $questionKindInput.val()); // set new question kind value to sliders
	      // reset sliders
	      $associatedSliders.val(0);
	      $associatedSliders.rangeslider('destroy').removeClass('slided');
	      this._createSliders();
	      // update Limits + summary
	      this._updateLimits();
	      this._updateSummary();
	    }

	    // when skillId change -> update skillId + show/hide slider + reset value + update limits + update summary

	  }, {
	    key: '_onSkillIdChange',
	    value: function _onSkillIdChange(e) {
	      var _this = this;
	      var $skillTypeInput = (0, _jquery2.default)(e.currentTarget);
	      var skillId = $skillTypeInput.val();
	      var $sliderRow = $skillTypeInput.parents('.form-group').next();
	      var $slider = $sliderRow.find(this._sliderSlt);

	      // if user select a skill when show else hide slider
	      if (skillId) {
	        $sliderRow.fadeIn('slow');
	        $slider.attr('data-slider-id', skillId);
	      } else $sliderRow.fadeOut('slow');
	      $slider.val(0); // reset value to zero to set correct limit
	      this._updateLimits(); // update limits
	      if (skillId) $slider.val($slider.data('slider-limit')).change(); // set new value to max limit
	      // update Limits + summary
	      this._updateLimits();
	      this._updateSummary();
	    }

	    // limit the slider position when changing and update the printed value

	  }, {
	    key: '_checkLimit',
	    value: function _checkLimit(position, value, element) {
	      (0, _jquery2.default)(element).next().find('.rangeslider__handle').html('' + value); // update printed value
	      var limit = (0, _jquery2.default)(element).data('slider-limit');
	      if (value > limit) (0, _jquery2.default)(element).val(limit).change();
	    }

	    // update the limits of sliders

	  }, {
	    key: '_updateLimits',
	    value: function _updateLimits() {
	      if ((0, _jquery2.default)('.skillSummary').length != 0) return;
	      var $sliders = this._getUniqSliders();

	      $sliders.each(function (index, element) {
	        var id = (0, _jquery2.default)(element).attr('data-slider-id');
	        var kind = (0, _jquery2.default)(element).data('kind');
	        var max = (0, _jquery2.default)(element).attr('max') >> 0;
	        var min = (0, _jquery2.default)(element).attr('min') >> 0;

	        // get similar skill => same sliderId and same question kind
	        var $similarSkills = (0, _jquery2.default)(this._sliderSlt + ':visible[data-slider-id=' + id + ']').filter(function (index, element) {
	          return (0, _jquery2.default)(element).data('kind') == kind;
	        });
	        var limit = max;
	        // define the limit by sustract the value of all associate sliders
	        $similarSkills.each(function (index, slider) {
	          limit -= (0, _jquery2.default)(slider).val() >> 0;
	        });
	        // avoid overflow
	        if (limit < min) limit = min;
	        // set new limit
	        $similarSkills.each(function (index, slider) {
	          (0, _jquery2.default)(slider).data('slider-limit', limit + ((0, _jquery2.default)(slider).val() >> 0));
	        });
	      });
	    }

	    // get all sliders and remove duplicated skill from the selection by question kind

	  }, {
	    key: '_getUniqSliders',
	    value: function _getUniqSliders() {
	      var $sliders = (0, _jquery2.default)(this._sliderSlt + ':visible.slided');
	      var ids = {
	        standard: [],
	        bonus: []
	      };
	      return $sliders.filter(function (pos, element) {
	        var id = (0, _jquery2.default)(element).attr('data-slider-id');
	        var kind = (0, _jquery2.default)(element).data('kind');

	        if (ids[kind].indexOf(id) == -1) {
	          ids[kind].push(id);
	          return true;
	        } else return false;
	      });
	    }

	    // get all skills from summary section

	  }, {
	    key: '_getSummarySkills',
	    value: function _getSummarySkills() {
	      this._summarySkills = (0, _jquery2.default)(this._skillSummaryCtnSlt + ' [data-skill-id]').map(function (index, element) {
	        return { id: (0, _jquery2.default)(element).attr('data-skill-id'), $element: (0, _jquery2.default)(element) };
	      });
	      return this._summarySkills;
	    }

	    // update Summary by iterate each skill , get all associate sliders and sum their values

	  }, {
	    key: '_updateSummary',
	    value: function _updateSummary() {
	      var _this4 = this;

	      this._summarySkills.each(function (index, skill) {
	        var sum = {
	          standard: 0,
	          bonus: 0
	        };

	        if (skill.id) {
	          var $similarSkills = (0, _jquery2.default)(_this4._sliderSlt + ':visible[data-slider-id=' + skill.id + ']');
	          $similarSkills.each(function (index, slider) {
	            var kind = (0, _jquery2.default)(slider).data('kind');

	            sum[kind] += (0, _jquery2.default)(slider).val() >> 0;
	          });
	        }

	        skill.$element.find(".standard .value").html(sum.standard);
	        skill.$element.find(".bonus .value").html(sum.bonus);
	      });
	    }
	  }], [{
	    key: 'isScales',
	    value: function isScales() {
	      return (0, _jquery2.default)('.skillSummary').length;
	    }
	  }]);

	  return Scales;
	}();

	exports.default = Scales;

/***/ },
/* 455 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! rangeslider.js - v2.2.1 | (c) 2016 @andreruffert | MIT license | https://github.com/andreruffert/rangeslider.js */
	(function(factory) {
	    'use strict';

	    if (true) {
	        // AMD. Register as an anonymous module.
	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__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__));
	    } else if (typeof exports === 'object') {
	        // CommonJS
	        module.exports = factory(require('jquery'));
	    } else {
	        // Browser globals
	        factory(jQuery);
	    }
	}(function($) {
	    'use strict';

	    // Polyfill Number.isNaN(value)
	    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
	    Number.isNaN = Number.isNaN || function(value) {
	        return typeof value === 'number' && value !== value;
	    };

	    /**
	     * Range feature detection
	     * @return {Boolean}
	     */
	    function supportsRange() {
	        var input = document.createElement('input');
	        input.setAttribute('type', 'range');
	        return input.type !== 'text';
	    }

	    var pluginName = 'rangeslider',
	        pluginIdentifier = 0,
	        hasInputRangeSupport = supportsRange(),
	        defaults = {
	            polyfill: true,
	            orientation: 'horizontal',
	            rangeClass: 'rangeslider',
	            disabledClass: 'rangeslider--disabled',
	            horizontalClass: 'rangeslider--horizontal',
	            verticalClass: 'rangeslider--vertical',
	            fillClass: 'rangeslider__fill',
	            handleClass: 'rangeslider__handle',
	            startEvent: ['mousedown', 'touchstart', 'pointerdown'],
	            moveEvent: ['mousemove', 'touchmove', 'pointermove'],
	            endEvent: ['mouseup', 'touchend', 'pointerup']
	        },
	        constants = {
	            orientation: {
	                horizontal: {
	                    dimension: 'width',
	                    direction: 'left',
	                    directionStyle: 'left',
	                    coordinate: 'x'
	                },
	                vertical: {
	                    dimension: 'height',
	                    direction: 'top',
	                    directionStyle: 'bottom',
	                    coordinate: 'y'
	                }
	            }
	        };

	    /**
	     * Delays a function for the given number of milliseconds, and then calls
	     * it with the arguments supplied.
	     *
	     * @param  {Function} fn   [description]
	     * @param  {Number}   wait [description]
	     * @return {Function}
	     */
	    function delay(fn, wait) {
	        var args = Array.prototype.slice.call(arguments, 2);
	        return setTimeout(function(){ return fn.apply(null, args); }, wait);
	    }

	    /**
	     * Returns a debounced function that will make sure the given
	     * function is not triggered too much.
	     *
	     * @param  {Function} fn Function to debounce.
	     * @param  {Number}   debounceDuration OPTIONAL. The amount of time in milliseconds for which we will debounce the function. (defaults to 100ms)
	     * @return {Function}
	     */
	    function debounce(fn, debounceDuration) {
	        debounceDuration = debounceDuration || 100;
	        return function() {
	            if (!fn.debouncing) {
	                var args = Array.prototype.slice.apply(arguments);
	                fn.lastReturnVal = fn.apply(window, args);
	                fn.debouncing = true;
	            }
	            clearTimeout(fn.debounceTimeout);
	            fn.debounceTimeout = setTimeout(function(){
	                fn.debouncing = false;
	            }, debounceDuration);
	            return fn.lastReturnVal;
	        };
	    }

	    /**
	     * Check if a `element` is visible in the DOM
	     *
	     * @param  {Element}  element
	     * @return {Boolean}
	     */
	    function isHidden(element) {
	        return (
	            element && (
	                element.offsetWidth === 0 ||
	                element.offsetHeight === 0 ||
	                // Also Consider native `<details>` elements.
	                element.open === false
	            )
	        );
	    }

	    /**
	     * Get hidden parentNodes of an `element`
	     *
	     * @param  {Element} element
	     * @return {[type]}
	     */
	    function getHiddenParentNodes(element) {
	        var parents = [],
	            node    = element.parentNode;

	        while (isHidden(node)) {
	            parents.push(node);
	            node = node.parentNode;
	        }
	        return parents;
	    }

	    /**
	     * Returns dimensions for an element even if it is not visible in the DOM.
	     *
	     * @param  {Element} element
	     * @param  {String}  key     (e.g. offsetWidth …)
	     * @return {Number}
	     */
	    function getDimension(element, key) {
	        var hiddenParentNodes       = getHiddenParentNodes(element),
	            hiddenParentNodesLength = hiddenParentNodes.length,
	            inlineStyle             = [],
	            dimension               = element[key];

	        // Used for native `<details>` elements
	        function toggleOpenProperty(element) {
	            if (typeof element.open !== 'undefined') {
	                element.open = (element.open) ? false : true;
	            }
	        }

	        if (hiddenParentNodesLength) {
	            for (var i = 0; i < hiddenParentNodesLength; i++) {

	                // Cache style attribute to restore it later.
	                inlineStyle[i] = hiddenParentNodes[i].style.cssText;

	                // visually hide
	                if (hiddenParentNodes[i].style.setProperty) {
	                    hiddenParentNodes[i].style.setProperty('display', 'block', 'important');
	                } else {
	                    hiddenParentNodes[i].style.cssText += ';display: block !important';
	                }
	                hiddenParentNodes[i].style.height = '0';
	                hiddenParentNodes[i].style.overflow = 'hidden';
	                hiddenParentNodes[i].style.visibility = 'hidden';
	                toggleOpenProperty(hiddenParentNodes[i]);
	            }

	            // Update dimension
	            dimension = element[key];

	            for (var j = 0; j < hiddenParentNodesLength; j++) {

	                // Restore the style attribute
	                hiddenParentNodes[j].style.cssText = inlineStyle[j];
	                toggleOpenProperty(hiddenParentNodes[j]);
	            }
	        }
	        return dimension;
	    }

	    /**
	     * Returns the parsed float or the default if it failed.
	     *
	     * @param  {String}  str
	     * @param  {Number}  defaultValue
	     * @return {Number}
	     */
	    function tryParseFloat(str, defaultValue) {
	        var value = parseFloat(str);
	        return Number.isNaN(value) ? defaultValue : value;
	    }

	    /**
	     * Capitalize the first letter of string
	     *
	     * @param  {String} str
	     * @return {String}
	     */
	    function ucfirst(str) {
	        return str.charAt(0).toUpperCase() + str.substr(1);
	    }

	    /**
	     * Plugin
	     * @param {String} element
	     * @param {Object} options
	     */
	    function Plugin(element, options) {
	        this.$window            = $(window);
	        this.$document          = $(document);
	        this.$element           = $(element);
	        this.options            = $.extend( {}, defaults, options );
	        this.polyfill           = this.options.polyfill;
	        this.orientation        = this.$element[0].getAttribute('data-orientation') || this.options.orientation;
	        this.onInit             = this.options.onInit;
	        this.onSlide            = this.options.onSlide;
	        this.onSlideEnd         = this.options.onSlideEnd;
	        this.DIMENSION          = constants.orientation[this.orientation].dimension;
	        this.DIRECTION          = constants.orientation[this.orientation].direction;
	        this.DIRECTION_STYLE    = constants.orientation[this.orientation].directionStyle;
	        this.COORDINATE         = constants.orientation[this.orientation].coordinate;

	        // Plugin should only be used as a polyfill
	        if (this.polyfill) {
	            // Input range support?
	            if (hasInputRangeSupport) { return false; }
	        }

	        this.identifier = 'js-' + pluginName + '-' +(pluginIdentifier++);
	        this.startEvent = this.options.startEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
	        this.moveEvent  = this.options.moveEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
	        this.endEvent   = this.options.endEvent.join('.' + this.identifier + ' ') + '.' + this.identifier;
	        this.toFixed    = (this.step + '').replace('.', '').length - 1;
	        this.$fill      = $('<div class="' + this.options.fillClass + '" />');
	        this.$handle    = $('<div class="' + this.options.handleClass + '" />');
	        this.$range     = $('<div class="' + this.options.rangeClass + ' ' + this.options[this.orientation + 'Class'] + '" id="' + this.identifier + '" />').insertAfter(this.$element).prepend(this.$fill, this.$handle);

	        // visually hide the input
	        this.$element.css({
	            'position': 'absolute',
	            'width': '1px',
	            'height': '1px',
	            'overflow': 'hidden',
	            'opacity': '0'
	        });

	        // Store context
	        this.handleDown = $.proxy(this.handleDown, this);
	        this.handleMove = $.proxy(this.handleMove, this);
	        this.handleEnd  = $.proxy(this.handleEnd, this);

	        this.init();

	        // Attach Events
	        var _this = this;
	        this.$window.on('resize.' + this.identifier, debounce(function() {
	            // Simulate resizeEnd event.
	            delay(function() { _this.update(false, false); }, 300);
	        }, 20));

	        this.$document.on(this.startEvent, '#' + this.identifier + ':not(.' + this.options.disabledClass + ')', this.handleDown);

	        // Listen to programmatic value changes
	        this.$element.on('change.' + this.identifier, function(e, data) {
	            if (data && data.origin === _this.identifier) {
	                return;
	            }

	            var value = e.target.value,
	                pos = _this.getPositionFromValue(value);
	            _this.setPosition(pos);
	        });
	    }

	    Plugin.prototype.init = function() {
	        this.update(true, false);

	        if (this.onInit && typeof this.onInit === 'function') {
	            this.onInit();
	        }
	    };

	    Plugin.prototype.update = function(updateAttributes, triggerSlide) {
	        updateAttributes = updateAttributes || false;

	        if (updateAttributes) {
	            this.min    = tryParseFloat(this.$element[0].getAttribute('min'), 0);
	            this.max    = tryParseFloat(this.$element[0].getAttribute('max'), 100);
	            this.value  = tryParseFloat(this.$element[0].value, Math.round(this.min + (this.max-this.min)/2));
	            this.step   = tryParseFloat(this.$element[0].getAttribute('step'), 1);
	        }

	        this.handleDimension    = getDimension(this.$handle[0], 'offset' + ucfirst(this.DIMENSION));
	        this.rangeDimension     = getDimension(this.$range[0], 'offset' + ucfirst(this.DIMENSION));
	        this.maxHandlePos       = this.rangeDimension - this.handleDimension;
	        this.grabPos            = this.handleDimension / 2;
	        this.position           = this.getPositionFromValue(this.value);

	        // Consider disabled state
	        if (this.$element[0].disabled) {
	            this.$range.addClass(this.options.disabledClass);
	        } else {
	            this.$range.removeClass(this.options.disabledClass);
	        }

	        this.setPosition(this.position, triggerSlide);
	    };

	    Plugin.prototype.handleDown = function(e) {
	        this.$document.on(this.moveEvent, this.handleMove);
	        this.$document.on(this.endEvent, this.handleEnd);

	        // If we click on the handle don't set the new position
	        if ((' ' + e.target.className + ' ').replace(/[\n\t]/g, ' ').indexOf(this.options.handleClass) > -1) {
	            return;
	        }

	        var pos         = this.getRelativePosition(e),
	            rangePos    = this.$range[0].getBoundingClientRect()[this.DIRECTION],
	            handlePos   = this.getPositionFromNode(this.$handle[0]) - rangePos,
	            setPos      = (this.orientation === 'vertical') ? (this.maxHandlePos - (pos - this.grabPos)) : (pos - this.grabPos);

	        this.setPosition(setPos);

	        if (pos >= handlePos && pos < handlePos + this.handleDimension) {
	            this.grabPos = pos - handlePos;
	        }
	    };

	    Plugin.prototype.handleMove = function(e) {
	        e.preventDefault();
	        var pos = this.getRelativePosition(e);
	        var setPos = (this.orientation === 'vertical') ? (this.maxHandlePos - (pos - this.grabPos)) : (pos - this.grabPos);
	        this.setPosition(setPos);
	    };

	    Plugin.prototype.handleEnd = function(e) {
	        e.preventDefault();
	        this.$document.off(this.moveEvent, this.handleMove);
	        this.$document.off(this.endEvent, this.handleEnd);

	        // Ok we're done fire the change event
	        this.$element.trigger('change', { origin: this.identifier });

	        if (this.onSlideEnd && typeof this.onSlideEnd === 'function') {
	            this.onSlideEnd(this.position, this.value);
	        }
	    };

	    Plugin.prototype.cap = function(pos, min, max) {
	        if (pos < min) { return min; }
	        if (pos > max) { return max; }
	        return pos;
	    };

	    Plugin.prototype.setPosition = function(pos, triggerSlide) {
	        var value, newPos;

	        if (triggerSlide === undefined) {
	            triggerSlide = true;
	        }

	        // Snapping steps
	        value = this.getValueFromPosition(this.cap(pos, 0, this.maxHandlePos));
	        newPos = this.getPositionFromValue(value);

	        // Update ui
	        this.$fill[0].style[this.DIMENSION] = (newPos + this.grabPos) + 'px';
	        this.$handle[0].style[this.DIRECTION_STYLE] = newPos + 'px';
	        this.setValue(value);

	        // Update globals
	        this.position = newPos;
	        this.value = value;

	        if (triggerSlide && this.onSlide && typeof this.onSlide === 'function') {
	            this.onSlide(newPos, value);
	        }
	    };

	    // Returns element position relative to the parent
	    Plugin.prototype.getPositionFromNode = function(node) {
	        var i = 0;
	        while (node !== null) {
	            i += node.offsetLeft;
	            node = node.offsetParent;
	        }
	        return i;
	    };

	    Plugin.prototype.getRelativePosition = function(e) {
	        // Get the offset DIRECTION relative to the viewport
	        var ucCoordinate = ucfirst(this.COORDINATE),
	            rangePos = this.$range[0].getBoundingClientRect()[this.DIRECTION],
	            pageCoordinate = 0;

	        if (typeof e['page' + ucCoordinate] !== 'undefined') {
	            pageCoordinate = e['page' + ucCoordinate];
	        }
	        // IE8 support :)
	        else if (typeof e.originalEvent['client' + ucCoordinate] !== 'undefined') {
	            pageCoordinate = e.originalEvent['client' + ucCoordinate];
	        }
	        else if (e.originalEvent.touches && e.originalEvent.touches[0] && typeof e.originalEvent.touches[0]['page' + ucCoordinate] !== 'undefined') {
	            pageCoordinate = e.originalEvent.touches[0]['page' + ucCoordinate];
	        }
	        else if(e.currentPoint && typeof e.currentPoint[this.COORDINATE] !== 'undefined') {
	            pageCoordinate = e.currentPoint[this.COORDINATE];
	        }

	        return pageCoordinate - rangePos;
	    };

	    Plugin.prototype.getPositionFromValue = function(value) {
	        var percentage, pos;
	        percentage = (value - this.min)/(this.max - this.min);
	        pos = (!Number.isNaN(percentage)) ? percentage * this.maxHandlePos : 0;
	        return pos;
	    };

	    Plugin.prototype.getValueFromPosition = function(pos) {
	        var percentage, value;
	        percentage = ((pos) / (this.maxHandlePos || 1));
	        value = this.step * Math.round(percentage * (this.max - this.min) / this.step) + this.min;
	        return Number((value).toFixed(this.toFixed));
	    };

	    Plugin.prototype.setValue = function(value) {
	        if (value === this.value && this.$element[0].value !== '') {
	            return;
	        }

	        // Set the new value and fire the `input` event
	        this.$element
	            .val(value)
	            .trigger('input', { origin: this.identifier });
	    };

	    Plugin.prototype.destroy = function() {
	        this.$document.off('.' + this.identifier);
	        this.$window.off('.' + this.identifier);

	        this.$element
	            .off('.' + this.identifier)
	            .removeAttr('style')
	            .removeData('plugin_' + pluginName);

	        // Remove the generated markup
	        if (this.$range && this.$range.length) {
	            this.$range[0].parentNode.removeChild(this.$range[0]);
	        }
	    };

	    // A really lightweight plugin wrapper around the constructor,
	    // preventing against multiple instantiations
	    $.fn[pluginName] = function(options) {
	        var args = Array.prototype.slice.call(arguments, 1);

	        return this.each(function() {
	            var $this = $(this),
	                data  = $this.data('plugin_' + pluginName);

	            // Create a new instance.
	            if (!data) {
	                $this.data('plugin_' + pluginName, (data = new Plugin(this, options)));
	            }

	            // Make it possible to access methods from public.
	            // e.g `$element.rangeslider('method');`
	            if (typeof options === 'string') {
	                data[options].apply(data, args);
	            }
	        });
	    };

	    return 'rangeslider.js is available in jQuery context e.g $(selector).rangeslider(options);';

	}));


/***/ },
/* 456 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	__webpack_require__(455);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Skills = function () {
	  function Skills() {
	    var _this = this;

	    _classCallCheck(this, Skills);

	    if (!(0, _jquery2.default)('[data-add-skill]').length) return;
	    this._$form = (0, _jquery2.default)('form');
	    this._rangeSlt = 'input[type="range"]:visible';
	    this._$difficulty = (0, _jquery2.default)('[data-difficulty]');
	    (0, _jquery2.default)('input[type="range"]').each(function (index, input) {
	      _this._initSlider((0, _jquery2.default)(input));
	    });
	    this._initLimits();
	    this._$difficulty.on('change', function (_) {
	      return _this._updateRanges((0, _jquery2.default)(_this._rangeSlt));
	    });

	    // when a skill is added or deleted
	    (0, _jquery2.default)(document).on('nested:fieldRemoved:projects_skills', function (_) {
	      return _this._updateLimits();
	    });
	    (0, _jquery2.default)(document).on('nested:fieldAdded:projects_skills', function (_) {
	      return _this._updateRanges((0, _jquery2.default)(_this._rangeSlt));
	    });

	    (0, _jquery2.default)(document).on('nested:fieldRemoved:partnerships_skills', function (_) {
	      return _this._updateLimits();
	    });
	    (0, _jquery2.default)(document).on('nested:fieldAdded:partnerships_skills', function (_) {
	      return _this._updateRanges((0, _jquery2.default)(_this._rangeSlt).not('.slided'));
	    });

	    (0, _jquery2.default)(document).on('cocoon:after-remove', function (_) {
	      return _this._updateLimits((0, _jquery2.default)(_this._rangeSlt));
	    });
	    (0, _jquery2.default)(document).on('cocoon:after-insert', function (_) {
	      return _this._updateRanges((0, _jquery2.default)(_this._rangeSlt));
	    });
	  }

	  // ugly but needed for the motherf**** slider lib


	  _createClass(Skills, [{
	    key: '_updateRanges',
	    value: function _updateRanges($range) {
	      var _this2 = this;

	      var total = (0, _jquery2.default)('[data-difficulty]').val() == "0" ? 100 : (0, _jquery2.default)('[data-difficulty]').val();

	      var newMax = parseFloat(total);
	      $range.each(function (index, skill) {
	        var $skill = (0, _jquery2.default)(skill);
	        var oldVal = parseFloat($skill.val());
	        var oldMax = parseFloat($skill.attr('max'));
	        var newVal = newMax * oldVal / oldMax;
	        var newStep = newMax / 100;

	        $skill.attr('max', newMax).attr('step', newStep);
	        $skill.rangeslider('destroy');
	        _this2._updateLimits();
	        $skill.val(newVal);
	        _this2._initSlider($skill);
	        //$skill.val(newVal)
	      });

	      this._updateLimits();
	    }

	    // Create Slider

	  }, {
	    key: '_initSlider',
	    value: function _initSlider($input) {
	      var _this3 = this;

	      $input.rangeslider({
	        polyfill: false,
	        onSlide: this._checkLimit,
	        onSlideEnd: function onSlideEnd(_) {
	          return _this3._updateLimits();
	        }
	      });
	      $input.addClass('slided');
	      $input.change();
	    }

	    // limit the slider position

	  }, {
	    key: '_checkLimit',
	    value: function _checkLimit(position, value) {
	      var total = (0, _jquery2.default)('[data-difficulty]').val() == "0" ? 100 : (0, _jquery2.default)('[data-difficulty]').val();
	      var percent = value * 100 / parseFloat(total);

	      this.$element.next().find('.rangeslider__handle').attr("data-percent", percent);
	      var limit = this.$element.data('rangeUntil');
	      if (value > limit) {
	        this.$element.val(limit).change();
	      }
	    }
	  }, {
	    key: '_initLimits',
	    value: function _initLimits() {
	      var total = (0, _jquery2.default)('[data-difficulty]').val() == "0" ? 100 : (0, _jquery2.default)('[data-difficulty]').val();
	      var limit = parseFloat(total);
	      (0, _jquery2.default)('input[type="range"]').each(function (index, skill) {
	        limit -= parseFloat((0, _jquery2.default)(skill).val());
	      });
	      if (limit < 0) limit = 0;
	      (0, _jquery2.default)('input[type="range"]').each(function (index, skill) {
	        (0, _jquery2.default)(skill).data('rangeUntil', parseFloat((0, _jquery2.default)(skill).val()) + limit);
	      });
	    }

	    // update the slider position limit

	  }, {
	    key: '_updateLimits',
	    value: function _updateLimits() {
	      var total = (0, _jquery2.default)('[data-difficulty]').val() == "0" ? 100 : (0, _jquery2.default)('[data-difficulty]').val();
	      var limit = parseFloat(total);
	      (0, _jquery2.default)(this._rangeSlt).each(function (index, skill) {
	        limit -= parseFloat((0, _jquery2.default)(skill).val());
	      });
	      if (limit < 0) limit = 0;
	      (0, _jquery2.default)(this._rangeSlt).each(function (index, skill) {
	        (0, _jquery2.default)(skill).data('rangeUntil', parseFloat((0, _jquery2.default)(skill).val()) + limit);
	      });
	    }
	  }, {
	    key: 'modalCondition',
	    value: function modalCondition() {
	      var total = 0;

	      (0, _jquery2.default)('' + this._rangeSlt).each(function (index, skillElement) {
	        total += (0, _jquery2.default)(skillElement).next().find('.rangeslider__handle').data('percent') >> 0;
	      });
	      return total != 100 && (0, _jquery2.default)('[data-difficulty]').val() != "0";
	    }
	  }, {
	    key: 'modalConfirmation',
	    value: function modalConfirmation() {
	      this._$form.submit();
	    }
	  }]);

	  return Skills;
	}();

	exports.default = Skills;

/***/ },
/* 457 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var ProjectShow = function () {
	  function ProjectShow() {
	    _classCallCheck(this, ProjectShow);

	    this.project_session_select();
	  }

	  _createClass(ProjectShow, [{
	    key: 'project_session_select',
	    value: function project_session_select() {
	      (0, _jquery2.default)('#other_project_session_id').on('change', function () {
	        (0, _jquery2.default)(this).parents('form').submit();
	        (0, _jquery2.default)(this).parent().css({
	          height: 34, padding: '6px 12px', fontSize: 14, lineHeight: 1.42857143,
	          color: '#555555', border: '1px solid #ccc', borderRadius: 4, margin: '0 15px'
	        }).text('Loading...');
	      });
	    }
	  }]);

	  return ProjectShow;
	}();

	exports.default = ProjectShow;

/***/ },
/* 458 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var QuestFormOptions = function () {
	  function QuestFormOptions() {
	    _classCallCheck(this, QuestFormOptions);

	    if ((0, _jquery2.default)("select#quest_kind").length === 0) return;
	    var self = this;
	    var parentForms = [];
	    var _iteratorNormalCompletion = true;
	    var _didIteratorError = false;
	    var _iteratorError = undefined;

	    try {
	      for (var _iterator = (0, _jquery2.default)("[data-hide-unless-form]")[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
	        var form = _step.value;

	        parentForms.push((0, _jquery2.default)("form #" + form.dataset.hideUnlessForm));
	      }
	    } catch (err) {
	      _didIteratorError = true;
	      _iteratorError = err;
	    } finally {
	      try {
	        if (!_iteratorNormalCompletion && _iterator.return) {
	          _iterator.return();
	        }
	      } finally {
	        if (_didIteratorError) {
	          throw _iteratorError;
	        }
	      }
	    }

	    var _iteratorNormalCompletion2 = true;
	    var _didIteratorError2 = false;
	    var _iteratorError2 = undefined;

	    try {
	      for (var _iterator2 = parentForms[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
	        var _form = _step2.value;

	        _form.on('change', self.hideForms);
	        _form.trigger('change');
	      }
	    } catch (err) {
	      _didIteratorError2 = true;
	      _iteratorError2 = err;
	    } finally {
	      try {
	        if (!_iteratorNormalCompletion2 && _iterator2.return) {
	          _iterator2.return();
	        }
	      } finally {
	        if (_didIteratorError2) {
	          throw _iteratorError2;
	        }
	      }
	    }

	    (0, _jquery2.default)('form.simple_form input[type=submit]').on('click', self.clearForm);
	  }

	  _createClass(QuestFormOptions, [{
	    key: "hideForms",
	    value: function hideForms() {
	      if ((0, _jquery2.default)(this).val() == "") (0, _jquery2.default)("[data-hide-unless-value]").closest(".form-group").addClass('hidden');else {
	        var id = (0, _jquery2.default)(this).attr("id");
	        var val = (0, _jquery2.default)(this).val();
	        (0, _jquery2.default)("[data-hide-unless-form=" + id + "]").closest(".form-group").addClass('hidden');
	        (0, _jquery2.default)("[data-hide-unless-value~=" + val + "]").closest(".form-group").removeClass('hidden');
	      }
	    }
	  }, {
	    key: "clearForm",
	    value: function clearForm() {
	      (0, _jquery2.default)('.form-group.hidden select').prop('selectedIndex', 0);
	      (0, _jquery2.default)('.form-group.hidden input').val('');
	      (0, _jquery2.default)('.form-group.hidden textarea').val('');
	      (0, _jquery2.default)('.form-group.hidden input').val('').removeAttr('checked').removeAttr('selected');
	      debugger;
	    }
	  }]);

	  return QuestFormOptions;
	}();

	exports.default = QuestFormOptions;

/***/ },
/* 459 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
		value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var QuestsUser = function () {
		function QuestsUser() {
			var _this = this;

			_classCallCheck(this, QuestsUser);

			(0, _jquery2.default)('[data-table-url]').on('keyup', '.filter-search-input', function (_) {
				_jquery2.default.getScript(_this.make_request((0, _jquery2.default)('.filter-search-input').val()));
			});
			(0, _jquery2.default)('[data-table-url]').on('click', '.filter-search-input ~ span button', function (_) {
				window.location.href = _this.make_request((0, _jquery2.default)('.filter-search-input').val()).replace('.js', ''); // yolooooo en attendant de voir pk le js marche pas
			});
		}

		_createClass(QuestsUser, [{
			key: 'make_request',
			value: function make_request(val) {
				var url = (0, _jquery2.default)('[data-table-url]').data('table-url');
				return url + (url.indexOf('?') == -1 ? "?search=" : "&search=") + encodeURI(val);
			}
		}]);

		return QuestsUser;
	}();

	exports.default = QuestsUser;

/***/ },
/* 460 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function answer() {
	  (0, _jquery2.default)(document).on('change', "[data-star-range]", function () {
	    (0, _jquery2.default)(this).attr("data-star-range", (0, _jquery2.default)(this).val());
	  });
	}

	exports.default = answer;

/***/ },
/* 461 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	(0, _jquery2.default)(document).ready(function () {
	  var gitId = (0, _jquery2.default)('[name="project[git_id]"]');
	  var repository = (0, _jquery2.default)('[name="project[repository]"]');
	  var commits = (0, _jquery2.default)('[name="project[project_sessions_attributes][0][commit]"]');
	  var objectives = (0, _jquery2.default)('.project_project_sessions_objectives');
	  // DIsable fields when a gitlab repository is selected
	  (0, _jquery2.default)('[name="project[git_id]"]').on('change', function () {
	    var versioned = !!(0, _jquery2.default)('[name="project[git_id]"]').val();
	    (0, _jquery2.default)('.not-versioned').prop('disabled', versioned); // not-versioned : field which is not needed when a git_id is specified
	    (0, _jquery2.default)('.versioned').prop('disabled', !versioned).find('.input_add_elem').removeClass('hidden'); // versioned: field which is needed when a git_id is specified
	    if (!versioned) {
	      objectives.find('textarea').prop('disabled', false);
	      objectives.find('.input_add_elem').removeClass('hidden');
	      (0, _jquery2.default)('.versioned-pane').removeClass('hidden');
	      (0, _jquery2.default)('.versioned').val('').trigger('change');
	    } else {
	      var switchPane = (0, _jquery2.default)('.main-project-nav-tabs').find('li.active').hasClass('versioned-pane');
	      if (switchPane) {
	        (0, _jquery2.default)('.main-project-nav-tabs').find('li').removeClass('active').first().addClass('active');
	        (0, _jquery2.default)('.tab-content.main-project-tab-content').find('.tab-pane').removeClass('active').first().addClass('active');
	      }
	      objectives.find('textarea').prop('disabled', true);
	      objectives.find('.input_add_elem').addClass('hidden');
	      (0, _jquery2.default)('.versioned-pane').addClass('hidden');
	      (0, _jquery2.default)('.not-versioned').val('').trigger('change');
	    }
	  }).trigger('change');

	  repository.on('change', function () {
	    var value = repository.val();
	    commits.prop('disabled', !value);
	    if (!value) commits.val('').trigger('change');
	  }).trigger('change');

	  gitId.select2();

	  repository.select2({
	    ajax: {
	      url: function url() {
	        var gitRepositoryId = gitId.val();
	        if (gitRepositoryId) return '/gits/' + gitId.val();else {
	          throw new Error("Can't get gitRepositoryId");
	        }
	      },
	      delay: 500,
	      dataType: 'json',
	      processResults: function processResults(git) {
	        return {
	          results: git.repositories.map(function (x) {
	            return { id: x.id, text: x.name };
	          })
	        };
	      }
	    }
	  });

	  commits.select2({
	    minimumResultsForSearch: -1,
	    ajax: {
	      url: function url() {
	        var gitProjectId = repository.val();
	        var gitRepositoryId = gitId.val();
	        if (gitRepositoryId && gitProjectId) {
	          return '/gits/' + gitId.val() + '/' + repository.val() + '/commits';
	        } else {
	          throw new Error("Can't get gitRepositoryId or GitProjectId");
	        }
	      },
	      dataType: 'json',
	      processResults: function processResults(commits) {
	        return {
	          results: commits.map(function (c) {
	            return { id: c.id, text: '[' + c.short_id + '] ' + c.title };
	          })
	        };
	      }
	    }
	  });
	});

/***/ },
/* 462 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	__webpack_require__(466);

	__webpack_require__(468);

	__webpack_require__(469);

	__webpack_require__(470);

	__webpack_require__(471);

	__webpack_require__(472);

	__webpack_require__(473);

	__webpack_require__(474);

	__webpack_require__(475);

	__webpack_require__(476);

	__webpack_require__(477);

	__webpack_require__(478);

	__webpack_require__(479);

	__webpack_require__(480);

	__webpack_require__(481);

	__webpack_require__(482);

	__webpack_require__(483);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var $window = (0, _jquery2.default)(window);
	var $navbar = (0, _jquery2.default)('.main-navbar');
	var $ctn = (0, _jquery2.default)('.view_ctn');
	var $canvas = (0, _jquery2.default)('canvas#view');
	var $cursus_selector = (0, _jquery2.default)('#graph_cursus');
	var $campus_selector = (0, _jquery2.default)('#graph_campus');
	var $layer_selector = (0, _jquery2.default)('#graph_layer');

	var ProjectGraph = function () {
	  function ProjectGraph(fetch_url) {
	    _classCallCheck(this, ProjectGraph);

	    this.fetch_url = fetch_url;
	    this.refresh_vars();
	    this.$canvas = $canvas;
	    this.$cursus_selector = $cursus_selector;
	    this.$campus_selector = $campus_selector;
	    this.$layer_selector = $layer_selector;
	    this.set_ctn_height();
	    // setup paper canvas
	    _paper2.default.setup($canvas[0]);
	    this.tool = new _paper2.default.Tool();
	    // create and saver layers
	    this.main_layer = _paper2.default.project.activeLayer;
	    this.links_layer = new _paper2.default.Layer();
	    this.internship_layer = new _paper2.default.Layer();
	    this.projects_layer = new _paper2.default.Layer();
	    // create and saver groups
	    // Setup the size
	    Graph.grid.draw(this.main_layer, Graph.WIDTH, Graph.HEIGHT);
	    // handle events
	    this.bind();
	    // start
	    $cursus_selector.trigger('change');
	  }

	  _createClass(ProjectGraph, [{
	    key: 'refresh_vars',
	    value: function refresh_vars() {
	      $window = (0, _jquery2.default)(window);
	      $navbar = (0, _jquery2.default)('.main-navbar');
	      $ctn = (0, _jquery2.default)('.view_ctn');
	      $canvas = (0, _jquery2.default)('canvas#view');
	      $cursus_selector = (0, _jquery2.default)('#graph_cursus');
	      $campus_selector = (0, _jquery2.default)('#graph_campus');
	      $layer_selector = (0, _jquery2.default)('#graph_layer');
	      Graph.description.refresh_vars();
	      Graph.help.refresh_vars();
	      Graph.search.refresh_vars();
	      Graph.layer.refresh_vars();
	      Graph.cursus.refresh_vars();
	      Graph.key_handler.refresh_vars();
	    }

	    // set correct height to canvas

	  }, {
	    key: 'set_ctn_height',
	    value: function set_ctn_height() {
	      $ctn.height($window.height() - $navbar.height());
	    }

	    // Populate the graph projects

	  }, {
	    key: 'populate',
	    value: function populate(projects, cursus, campus) {
	      var _this = this;

	      return new Promise(function (resolve, reject) {
	        // create layers
	        _this.links_layer.removeChildren();
	        _this.projects_layer.removeChildren();
	        _this.internship_layer.removeChildren();

	        Graph.hack.hack_it(projects, cursus, _this.projects_layer, _this.internship_layer);
	        _lodash2.default.each(projects, function (project) {
	          if (project.hacked === true) return;
	          Graph.link.draw(_this.links_layer, project);
	          Graph.project.draw(project, {
	            project: _this.projects_layer,
	            internship: _this.internship_layer
	          });
	        });
	        resolve();
	        $canvas.focus();
	      });
	    }
	  }, {
	    key: 'getData',
	    value: function getData() {
	      var _this2 = this;

	      return new Promise(function (resolve, reject) {
	        return _jquery2.default.ajax({
	          url: _this2.fetch_url.replace('%cursus_id', (0, _jquery2.default)("#graph_cursus").val()).replace('%campus_id', (0, _jquery2.default)("#graph_campus").val()),
	          success: resolve,
	          error: reject
	        });
	      });
	    }
	  }, {
	    key: 'bind',
	    value: function bind() {
	      $cursus_selector.on('change', this.on_cursus_selector_change.bind(this));
	      $campus_selector.on('change', this.on_cursus_selector_change.bind(this));
	      $window.on('resize', this.set_ctn_height);
	      Graph.zoom_handler.bind($canvas);
	      Graph.mouse_handler.bind(this);
	      Graph.key_handler.bind(this);
	      Graph.search.bind(this);
	      Graph.layer.bind(this);
	      Graph.help.bind(this);
	      Graph.animation_handler.bind();
	    }

	    // occur when the user has selected a cursus

	  }, {
	    key: 'on_cursus_selector_change',
	    value: function on_cursus_selector_change(e) {
	      var _this3 = this;

	      // set minimal zoom and center the graph
	      Graph.zoom_handler.reset_zoom(Graph.center_point);
	      // get projects from Ajax URL
	      this.getData(e.currentTarget.value).then(function (projects) {
	        Graph.data.cursus = parseInt($cursus_selector.val());
	        Graph.data.campus = parseInt($campus_selector.val());
	        Graph.data.projects = projects; // save the data (to shared this other modules)
	        _this3.populate(Graph.data.projects, Graph.data.cursus, Graph.data.campus); // create all the items
	        _this3.main_layer.activate(); // activate main layout (in order to zoom)
	        (0, _jquery2.default)('#graph_layer').val('');
	        _paper2.default.view.draw();
	      });
	    }
	  }]);

	  return ProjectGraph;
	}();

	exports.default = ProjectGraph;


	window.ProjectGraph = ProjectGraph;

/***/ },
/* 463 */
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
	 * Paper.js v0.10.2 - The Swiss Army Knife of Vector Graphics Scripting.
	 * http://paperjs.org/
	 *
	 * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
	 * http://scratchdisk.com/ & http://jonathanpuckey.com/
	 *
	 * Distributed under the MIT license. See LICENSE file for details.
	 *
	 * All rights reserved.
	 *
	 * Date: Sat Jul 9 20:14:37 2016 +0200
	 *
	 ***
	 *
	 * Straps.js - Class inheritance library with support for bean-style accessors
	 *
	 * Copyright (c) 2006 - 2016 Juerg Lehni
	 * http://scratchdisk.com/
	 *
	 * Distributed under the MIT license.
	 *
	 ***
	 *
	 * Acorn.js
	 * http://marijnhaverbeke.nl/acorn/
	 *
	 * Acorn is a tiny, fast JavaScript parser written in JavaScript,
	 * created by Marijn Haverbeke and released under an MIT license.
	 *
	 */

	var paper = function(self, undefined) {

	var window = self ? self.window : __webpack_require__(464),
		document = window && window.document;

	self = self || window;

	var Base = new function() {
		var hidden = /^(statics|enumerable|beans|preserve)$/,

			forEach = [].forEach || function(iter, bind) {
				for (var i = 0, l = this.length; i < l; i++)
					iter.call(bind, this[i], i, this);
			},

			forIn = function(iter, bind) {
				for (var i in this)
					if (this.hasOwnProperty(i))
						iter.call(bind, this[i], i, this);
			},

			create = Object.create || function(proto) {
				return { __proto__: proto };
			},

			describe = Object.getOwnPropertyDescriptor || function(obj, name) {
				var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
				return get
						? { get: get, set: obj.__lookupSetter__(name),
							enumerable: true, configurable: true }
						: obj.hasOwnProperty(name)
							? { value: obj[name], enumerable: true,
								configurable: true, writable: true }
							: null;
			},

			_define = Object.defineProperty || function(obj, name, desc) {
				if ((desc.get || desc.set) && obj.__defineGetter__) {
					if (desc.get)
						obj.__defineGetter__(name, desc.get);
					if (desc.set)
						obj.__defineSetter__(name, desc.set);
				} else {
					obj[name] = desc.value;
				}
				return obj;
			},

			define = function(obj, name, desc) {
				delete obj[name];
				return _define(obj, name, desc);
			};

		function inject(dest, src, enumerable, beans, preserve) {
			var beansNames = {};

			function field(name, val) {
				val = val || (val = describe(src, name))
						&& (val.get ? val : val.value);
				if (typeof val === 'string' && val[0] === '#')
					val = dest[val.substring(1)] || val;
				var isFunc = typeof val === 'function',
					res = val,
					prev = preserve || isFunc && !val.base
							? (val && val.get ? name in dest : dest[name])
							: null,
					bean;
				if (!preserve || !prev) {
					if (isFunc && prev)
						val.base = prev;
					if (isFunc && beans !== false
							&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))
						beansNames[bean[3].toLowerCase() + bean[4]] = bean[2];
					if (!res || isFunc || !res.get || typeof res.get !== 'function'
							|| !Base.isPlainObject(res))
						res = { value: res, writable: true };
					if ((describe(dest, name)
							|| { configurable: true }).configurable) {
						res.configurable = true;
						res.enumerable = enumerable;
					}
					define(dest, name, res);
				}
			}
			if (src) {
				for (var name in src) {
					if (src.hasOwnProperty(name) && !hidden.test(name))
						field(name);
				}
				for (var name in beansNames) {
					var part = beansNames[name],
						set = dest['set' + part],
						get = dest['get' + part] || set && dest['is' + part];
					if (get && (beans === true || get.length === 0))
						field(name, { get: get, set: set });
				}
			}
			return dest;
		}

		function each(obj, iter, bind) {
			if (obj)
				('length' in obj && !obj.getLength
						&& typeof obj.length === 'number'
					? forEach
					: forIn).call(obj, iter, bind = bind || obj);
			return bind;
		}

		function set(obj, args, start) {
			for (var i = start, l = args.length; i < l; i++) {
				var props = args[i];
				for (var key in props)
					if (props.hasOwnProperty(key))
						obj[key] = props[key];
			}
			return obj;
		}

		return inject(function Base() {
			set(this, arguments, 0);
		}, {
			inject: function(src) {
				if (src) {
					var statics = src.statics === true ? src : src.statics,
						beans = src.beans,
						preserve = src.preserve;
					if (statics !== src)
						inject(this.prototype, src, src.enumerable, beans, preserve);
					inject(this, statics, true, beans, preserve);
				}
				for (var i = 1, l = arguments.length; i < l; i++)
					this.inject(arguments[i]);
				return this;
			},

			extend: function() {
				var base = this,
					ctor,
					proto;
				for (var i = 0, obj, l = arguments.length;
						i < l && !(ctor && proto); i++) {
					obj = arguments[i];
					ctor = ctor || obj.initialize;
					proto = proto || obj.prototype;
				}
				ctor = ctor || function() {
					base.apply(this, arguments);
				};
				proto = ctor.prototype = proto || create(this.prototype);
				define(proto, 'constructor',
						{ value: ctor, writable: true, configurable: true });
				inject(ctor, this, true);
				if (arguments.length)
					this.inject.apply(ctor, arguments);
				ctor.base = base;
				return ctor;
			}
		}, true).inject({
			inject: function() {
				for (var i = 0, l = arguments.length; i < l; i++) {
					var src = arguments[i];
					if (src)
						inject(this, src, src.enumerable, src.beans, src.preserve);
				}
				return this;
			},

			extend: function() {
				var res = create(this);
				return res.inject.apply(res, arguments);
			},

			each: function(iter, bind) {
				return each(this, iter, bind);
			},

			set: function() {
				return set(this, arguments, 0);
			},

			clone: function() {
				return new this.constructor(this);
			},

			statics: {
				each: each,
				create: create,
				define: define,
				describe: describe,

				set: function(obj) {
					return set(obj, arguments, 1);
				},

				clone: function(obj) {
					return set(new obj.constructor(), arguments, 0);
				},

				isPlainObject: function(obj) {
					var ctor = obj != null && obj.constructor;
					return ctor && (ctor === Object || ctor === Base
							|| ctor.name === 'Object');
				},

				pick: function(a, b) {
					return a !== undefined ? a : b;
				}
			}
		});
	};

	if (true)
		module.exports = Base;

	Base.inject({
		toString: function() {
			return this._id != null
				?  (this._class || 'Object') + (this._name
					? " '" + this._name + "'"
					: ' @' + this._id)
				: '{ ' + Base.each(this, function(value, key) {
					if (!/^_/.test(key)) {
						var type = typeof value;
						this.push(key + ': ' + (type === 'number'
								? Formatter.instance.number(value)
								: type === 'string' ? "'" + value + "'" : value));
					}
				}, []).join(', ') + ' }';
		},

		getClassName: function() {
			return this._class || '';
		},

		importJSON: function(json) {
			return Base.importJSON(json, this);
		},

		exportJSON: function(options) {
			return Base.exportJSON(this, options);
		},

		toJSON: function() {
			return Base.serialize(this);
		},

		_set: function(props) {
			if (props && Base.isPlainObject(props))
				return Base.filter(this, props);
		},

		statics: {

			exports: {
				enumerable: true
			},

			extend: function extend() {
				var res = extend.base.apply(this, arguments),
					name = res.prototype._class;
				if (name && !Base.exports[name])
					Base.exports[name] = res;
				return res;
			},

			equals: function(obj1, obj2) {
				if (obj1 === obj2)
					return true;
				if (obj1 && obj1.equals)
					return obj1.equals(obj2);
				if (obj2 && obj2.equals)
					return obj2.equals(obj1);
				if (obj1 && obj2
						&& typeof obj1 === 'object' && typeof obj2 === 'object') {
					if (Array.isArray(obj1) && Array.isArray(obj2)) {
						var length = obj1.length;
						if (length !== obj2.length)
							return false;
						while (length--) {
							if (!Base.equals(obj1[length], obj2[length]))
								return false;
						}
					} else {
						var keys = Object.keys(obj1),
							length = keys.length;
						if (length !== Object.keys(obj2).length)
							return false;
						while (length--) {
							var key = keys[length];
							if (!(obj2.hasOwnProperty(key)
									&& Base.equals(obj1[key], obj2[key])))
								return false;
						}
					}
					return true;
				}
				return false;
			},

			read: function(list, start, options, length) {
				if (this === Base) {
					var value = this.peek(list, start);
					list.__index++;
					return value;
				}
				var proto = this.prototype,
					readIndex = proto._readIndex,
					index = start || readIndex && list.__index || 0;
				if (!length)
					length = list.length - index;
				var obj = list[index];
				if (obj instanceof this
					|| options && options.readNull && obj == null && length <= 1) {
					if (readIndex)
						list.__index = index + 1;
					return obj && options && options.clone ? obj.clone() : obj;
				}
				obj = Base.create(this.prototype);
				if (readIndex)
					obj.__read = true;
				obj = obj.initialize.apply(obj, index > 0 || length < list.length
					? Array.prototype.slice.call(list, index, index + length)
					: list) || obj;
				if (readIndex) {
					list.__index = index + obj.__read;
					obj.__read = undefined;
				}
				return obj;
			},

			peek: function(list, start) {
				return list[list.__index = start || list.__index || 0];
			},

			remain: function(list) {
				return list.length - (list.__index || 0);
			},

			readAll: function(list, start, options) {
				var res = [],
					entry;
				for (var i = start || 0, l = list.length; i < l; i++) {
					res.push(Array.isArray(entry = list[i])
							? this.read(entry, 0, options)
							: this.read(list, i, options, 1));
				}
				return res;
			},

			readNamed: function(list, name, start, options, length) {
				var value = this.getNamed(list, name),
					hasObject = value !== undefined;
				if (hasObject) {
					var filtered = list._filtered;
					if (!filtered) {
						filtered = list._filtered = Base.create(list[0]);
						filtered._filtering = list[0];
					}
					filtered[name] = undefined;
				}
				return this.read(hasObject ? [value] : list, start, options, length);
			},

			getNamed: function(list, name) {
				var arg = list[0];
				if (list._hasObject === undefined)
					list._hasObject = list.length === 1 && Base.isPlainObject(arg);
				if (list._hasObject)
					return name ? arg[name] : list._filtered || arg;
			},

			hasNamed: function(list, name) {
				return !!this.getNamed(list, name);
			},

			filter: function(dest, source, exclude) {
				var keys = Object.keys(source._filtering || source);
				for (var i = 0, l = keys.length; i < l; i++) {
					var key = keys[i];
					if (!(exclude && exclude[key])) {
						var value = source[key];
						if (value !== undefined)
							dest[key] = value;
					}
				}
				return dest;
			},

			isPlainValue: function(obj, asString) {
				return this.isPlainObject(obj) || Array.isArray(obj)
						|| asString && typeof obj === 'string';
			},

			serialize: function(obj, options, compact, dictionary) {
				options = options || {};

				var isRoot = !dictionary,
					res;
				if (isRoot) {
					options.formatter = new Formatter(options.precision);
					dictionary = {
						length: 0,
						definitions: {},
						references: {},
						add: function(item, create) {
							var id = '#' + item._id,
								ref = this.references[id];
							if (!ref) {
								this.length++;
								var res = create.call(item),
									name = item._class;
								if (name && res[0] !== name)
									res.unshift(name);
								this.definitions[id] = res;
								ref = this.references[id] = [id];
							}
							return ref;
						}
					};
				}
				if (obj && obj._serialize) {
					res = obj._serialize(options, dictionary);
					var name = obj._class;
					if (name && !obj._compactSerialize && (isRoot || !compact)
							&& res[0] !== name) {
						res.unshift(name);
					}
				} else if (Array.isArray(obj)) {
					res = [];
					for (var i = 0, l = obj.length; i < l; i++)
						res[i] = Base.serialize(obj[i], options, compact,
								dictionary);
				} else if (Base.isPlainObject(obj)) {
					res = {};
					var keys = Object.keys(obj);
					for (var i = 0, l = keys.length; i < l; i++) {
						var key = keys[i];
						res[key] = Base.serialize(obj[key], options, compact,
								dictionary);
					}
				} else if (typeof obj === 'number') {
					res = options.formatter.number(obj, options.precision);
				} else {
					res = obj;
				}
				return isRoot && dictionary.length > 0
						? [['dictionary', dictionary.definitions], res]
						: res;
			},

			deserialize: function(json, create, _data, _setDictionary, _isRoot) {
				var res = json,
					isFirst = !_data,
					hasDictionary = isFirst && json && json.length
						&& json[0][0] === 'dictionary';
				_data = _data || {};
				if (Array.isArray(json)) {
					var type = json[0],
						isDictionary = type === 'dictionary';
					if (json.length == 1 && /^#/.test(type)) {
						return _data.dictionary[type];
					}
					type = Base.exports[type];
					res = [];
					for (var i = type ? 1 : 0, l = json.length; i < l; i++) {
						res.push(Base.deserialize(json[i], create, _data,
								isDictionary, hasDictionary));
					}
					if (type) {
						var args = res;
						if (create) {
							res = create(type, args, isFirst || _isRoot);
						} else {
							res = Base.create(type.prototype);
							type.apply(res, args);
						}
					}
				} else if (Base.isPlainObject(json)) {
					res = {};
					if (_setDictionary)
						_data.dictionary = res;
					for (var key in json)
						res[key] = Base.deserialize(json[key], create, _data);
				}
				return hasDictionary ? res[1] : res;
			},

			exportJSON: function(obj, options) {
				var json = Base.serialize(obj, options);
				return options && options.asString === false
						? json
						: JSON.stringify(json);
			},

			importJSON: function(json, target) {
				return Base.deserialize(
						typeof json === 'string' ? JSON.parse(json) : json,
						function(ctor, args, isRoot) {
							var useTarget = isRoot && target
									&& target.constructor === ctor,
								obj = useTarget ? target
									: Base.create(ctor.prototype);
							if (args.length === 1 && obj instanceof Item
									&& (useTarget || !(obj instanceof Layer))) {
								var arg = args[0];
								if (Base.isPlainObject(arg))
									arg.insert = false;
							}
							(useTarget ? obj._set : ctor).apply(obj, args);
							if (useTarget)
								target = null;
							return obj;
						});
			},

			splice: function(list, items, index, remove) {
				var amount = items && items.length,
					append = index === undefined;
				index = append ? list.length : index;
				if (index > list.length)
					index = list.length;
				for (var i = 0; i < amount; i++)
					items[i]._index = index + i;
				if (append) {
					list.push.apply(list, items);
					return [];
				} else {
					var args = [index, remove];
					if (items)
						args.push.apply(args, items);
					var removed = list.splice.apply(list, args);
					for (var i = 0, l = removed.length; i < l; i++)
						removed[i]._index = undefined;
					for (var i = index + amount, l = list.length; i < l; i++)
						list[i]._index = i;
					return removed;
				}
			},

			capitalize: function(str) {
				return str.replace(/\b[a-z]/g, function(match) {
					return match.toUpperCase();
				});
			},

			camelize: function(str) {
				return str.replace(/-(.)/g, function(all, chr) {
					return chr.toUpperCase();
				});
			},

			hyphenate: function(str) {
				return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
			}
		}
	});

	var Emitter = {
		on: function(type, func) {
			if (typeof type !== 'string') {
				Base.each(type, function(value, key) {
					this.on(key, value);
				}, this);
			} else {
				var types = this._eventTypes,
					entry = types && types[type],
					handlers = this._callbacks = this._callbacks || {};
				handlers = handlers[type] = handlers[type] || [];
				if (handlers.indexOf(func) === -1) {
					handlers.push(func);
					if (entry && entry.install && handlers.length === 1)
						entry.install.call(this, type);
				}
			}
			return this;
		},

		off: function(type, func) {
			if (typeof type !== 'string') {
				Base.each(type, function(value, key) {
					this.off(key, value);
				}, this);
				return;
			}
			var types = this._eventTypes,
				entry = types && types[type],
				handlers = this._callbacks && this._callbacks[type],
				index;
			if (handlers) {
				if (!func || (index = handlers.indexOf(func)) !== -1
						&& handlers.length === 1) {
					if (entry && entry.uninstall)
						entry.uninstall.call(this, type);
					delete this._callbacks[type];
				} else if (index !== -1) {
					handlers.splice(index, 1);
				}
			}
			return this;
		},

		once: function(type, func) {
			return this.on(type, function() {
				func.apply(this, arguments);
				this.off(type, func);
			});
		},

		emit: function(type, event) {
			var handlers = this._callbacks && this._callbacks[type];
			if (!handlers)
				return false;
			var args = [].slice.call(arguments, 1),
				setTarget = event && event.target && !event.currentTarget;
			handlers = handlers.slice();
			if (setTarget)
				event.currentTarget = this;
			for (var i = 0, l = handlers.length; i < l; i++) {
				if (handlers[i].apply(this, args) === false) {
					if (event && event.stop)
						event.stop();
					break;
			   }
			}
			if (setTarget)
				delete event.currentTarget;
			return true;
		},

		responds: function(type) {
			return !!(this._callbacks && this._callbacks[type]);
		},

		attach: '#on',
		detach: '#off',
		fire: '#emit',

		_installEvents: function(install) {
			var types = this._eventTypes,
				handlers = this._callbacks,
				key = install ? 'install' : 'uninstall';
			if (types) {
				for (var type in handlers) {
					if (handlers[type].length > 0) {
						var entry = types[type],
							func = entry && entry[key];
						if (func)
							func.call(this, type);
					}
			}
			}
		},

		statics: {
			inject: function inject(src) {
				var events = src._events;
				if (events) {
					var types = {};
					Base.each(events, function(entry, key) {
						var isString = typeof entry === 'string',
							name = isString ? entry : key,
							part = Base.capitalize(name),
							type = name.substring(2).toLowerCase();
						types[type] = isString ? {} : entry;
						name = '_' + name;
						src['get' + part] = function() {
							return this[name];
						};
						src['set' + part] = function(func) {
							var prev = this[name];
							if (prev)
								this.off(type, prev);
							if (func)
								this.on(type, func);
							this[name] = func;
						};
					});
					src._eventTypes = types;
				}
				return inject.base.apply(this, arguments);
			}
		}
	};

	var PaperScope = Base.extend({
		_class: 'PaperScope',

		initialize: function PaperScope() {
			paper = this;
			this.settings = new Base({
				applyMatrix: true,
				insertItems: true,
				handleSize: 4,
				hitTolerance: 0
			});
			this.project = null;
			this.projects = [];
			this.tools = [];
			this.palettes = [];
			this._id = PaperScope._id++;
			PaperScope._scopes[this._id] = this;
			var proto = PaperScope.prototype;
			if (!this.support) {
				var ctx = CanvasProvider.getContext(1, 1) || {};
				proto.support = {
					nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
					nativeBlendModes: BlendMode.nativeModes
				};
				CanvasProvider.release(ctx);
			}
			if (!this.agent) {
				var user = self.navigator.userAgent.toLowerCase(),
					os = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],
					platform = os === 'darwin' ? 'mac' : os,
					agent = proto.agent = proto.browser = { platform: platform };
				if (platform)
					agent[platform] = true;
				user.replace(
					/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g,
					function(all, n, v1, v2, rv) {
						if (!agent.chrome) {
							var v = n === 'opera' ? v2 :
									/^(node|trident)$/.test(n) ? rv : v1;
							agent.version = v;
							agent.versionNumber = parseFloat(v);
							n = n === 'trident' ? 'msie' : n;
							agent.name = n;
							agent[n] = true;
						}
					}
				);
				if (agent.chrome)
					delete agent.webkit;
				if (agent.atom)
					delete agent.chrome;
			}
		},

		version: "0.10.2",

		getView: function() {
			var project = this.project;
			return project && project._view;
		},

		getPaper: function() {
			return this;
		},

		execute: function(code, options) {
			paper.PaperScript.execute(code, this, options);
			View.updateFocus();
		},

		install: function(scope) {
			var that = this;
			Base.each(['project', 'view', 'tool'], function(key) {
				Base.define(scope, key, {
					configurable: true,
					get: function() {
						return that[key];
					}
				});
			});
			for (var key in this)
				if (!/^_/.test(key) && this[key])
					scope[key] = this[key];
		},

		setup: function(element) {
			paper = this;
			this.project = new Project(element);
			return this;
		},

		createCanvas: function(width, height) {
			return CanvasProvider.getCanvas(width, height);
		},

		activate: function() {
			paper = this;
		},

		clear: function() {
			var projects = this.projects,
				tools = this.tools,
				palettes = this.palettes;
			for (var i = projects.length - 1; i >= 0; i--)
				projects[i].remove();
			for (var i = tools.length - 1; i >= 0; i--)
				tools[i].remove();
			for (var i = palettes.length - 1; i >= 0; i--)
				palettes[i].remove();
		},

		remove: function() {
			this.clear();
			delete PaperScope._scopes[this._id];
		},

		statics: new function() {
			function handleAttribute(name) {
				name += 'Attribute';
				return function(el, attr) {
					return el[name](attr) || el[name]('data-paper-' + attr);
				};
			}

			return {
				_scopes: {},
				_id: 0,

				get: function(id) {
					return this._scopes[id] || null;
				},

				getAttribute: handleAttribute('get'),
				hasAttribute: handleAttribute('has')
			};
		}
	});

	var PaperScopeItem = Base.extend(Emitter, {

		initialize: function(activate) {
			this._scope = paper;
			this._index = this._scope[this._list].push(this) - 1;
			if (activate || !this._scope[this._reference])
				this.activate();
		},

		activate: function() {
			if (!this._scope)
				return false;
			var prev = this._scope[this._reference];
			if (prev && prev !== this)
				prev.emit('deactivate');
			this._scope[this._reference] = this;
			this.emit('activate', prev);
			return true;
		},

		isActive: function() {
			return this._scope[this._reference] === this;
		},

		remove: function() {
			if (this._index == null)
				return false;
			Base.splice(this._scope[this._list], null, this._index, 1);
			if (this._scope[this._reference] == this)
				this._scope[this._reference] = null;
			this._scope = null;
			return true;
		},

		getView: function() {
			return this._scope.getView();
		}
	});

	var Formatter = Base.extend({
		initialize: function(precision) {
			this.precision = Base.pick(precision, 5);
			this.multiplier = Math.pow(10, this.precision);
		},

		number: function(val) {
			return this.precision < 16
					? Math.round(val * this.multiplier) / this.multiplier : val;
		},

		pair: function(val1, val2, separator) {
			return this.number(val1) + (separator || ',') + this.number(val2);
		},

		point: function(val, separator) {
			return this.number(val.x) + (separator || ',') + this.number(val.y);
		},

		size: function(val, separator) {
			return this.number(val.width) + (separator || ',')
					+ this.number(val.height);
		},

		rectangle: function(val, separator) {
			return this.point(val, separator) + (separator || ',')
					+ this.size(val, separator);
		}
	});

	Formatter.instance = new Formatter();

	var Numerical = new function() {

		var abscissas = [
			[  0.5773502691896257645091488],
			[0,0.7745966692414833770358531],
			[  0.3399810435848562648026658,0.8611363115940525752239465],
			[0,0.5384693101056830910363144,0.9061798459386639927976269],
			[  0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],
			[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],
			[  0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],
			[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],
			[  0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],
			[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],
			[  0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],
			[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],
			[  0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],
			[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],
			[  0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]
		];

		var weights = [
			[1],
			[0.8888888888888888888888889,0.5555555555555555555555556],
			[0.6521451548625461426269361,0.3478548451374538573730639],
			[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],
			[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],
			[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],
			[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],
			[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],
			[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],
			[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],
			[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],
			[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],
			[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],
			[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],
			[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]
		];

		var abs = Math.abs,
			sqrt = Math.sqrt,
			pow = Math.pow,
			log2 = Math.log2 || function(x) {
				return Math.log(x) * Math.LOG2E;
			},
			EPSILON = 1e-12,
			MACHINE_EPSILON = 1.12e-16;

		function clamp(value, min, max) {
			return value < min ? min : value > max ? max : value;
		}

		function getDiscriminant(a, b, c) {
			function split(v) {
				var x = v * 134217729,
					y = v - x,
					hi = y + x,
					lo = v - hi;
				return [hi, lo];
			}

			var D = b * b - a * c,
				E = b * b + a * c;
			if (abs(D) * 3 < E) {
				var ad = split(a),
					bd = split(b),
					cd = split(c),
					p = b * b,
					dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],
					q = a * c,
					dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])
							+ ad[1] * cd[1];
				D = (p - q) + (dp - dq);
			}
			return D;
		}

		function getNormalizationFactor() {
			var norm = Math.max.apply(Math, arguments);
			return norm && (norm < 1e-8 || norm > 1e8)
					? pow(2, -Math.round(log2(norm)))
					: 0;
		}

		return {
			TOLERANCE: 1e-6,
			EPSILON: EPSILON,
			MACHINE_EPSILON: MACHINE_EPSILON,
			CURVETIME_EPSILON: 4e-7,
			GEOMETRIC_EPSILON: 2e-7,
			WINDING_EPSILON: 2e-7,
			TRIGONOMETRIC_EPSILON: 1e-7,
			CLIPPING_EPSILON: 1e-9,
			KAPPA: 4 * (sqrt(2) - 1) / 3,

			isZero: function(val) {
				return val >= -EPSILON && val <= EPSILON;
			},

			clamp: clamp,

			integrate: function(f, a, b, n) {
				var x = abscissas[n - 2],
					w = weights[n - 2],
					A = (b - a) * 0.5,
					B = A + a,
					i = 0,
					m = (n + 1) >> 1,
					sum = n & 1 ? w[i++] * f(B) : 0;
				while (i < m) {
					var Ax = A * x[i];
					sum += w[i++] * (f(B + Ax) + f(B - Ax));
				}
				return A * sum;
			},

			findRoot: function(f, df, x, a, b, n, tolerance) {
				for (var i = 0; i < n; i++) {
					var fx = f(x),
						dx = fx / df(x),
						nx = x - dx;
					if (abs(dx) < tolerance)
						return nx;
					if (fx > 0) {
						b = x;
						x = nx <= a ? (a + b) * 0.5 : nx;
					} else {
						a = x;
						x = nx >= b ? (a + b) * 0.5 : nx;
					}
				}
				return x;
			},

			solveQuadratic: function(a, b, c, roots, min, max) {
				var x1, x2 = Infinity;
				if (abs(a) < EPSILON) {
					if (abs(b) < EPSILON)
						return abs(c) < EPSILON ? -1 : 0;
					x1 = -c / b;
				} else {
					b *= -0.5;
					var D = getDiscriminant(a, b, c);
					if (D && abs(D) < MACHINE_EPSILON) {
						var f = getNormalizationFactor(abs(a), abs(b), abs(c));
						if (f) {
							a *= f;
							b *= f;
							c *= f;
							D = getDiscriminant(a, b, c);
						}
					}
					if (D >= -MACHINE_EPSILON) {
						var Q = D < 0 ? 0 : sqrt(D),
							R = b + (b < 0 ? -Q : Q);
						if (R === 0) {
							x1 = c / a;
							x2 = -x1;
						} else {
							x1 = R / a;
							x2 = c / R;
						}
					}
				}
				var count = 0,
					boundless = min == null,
					minB = min - EPSILON,
					maxB = max + EPSILON;
				if (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))
					roots[count++] = boundless ? x1 : clamp(x1, min, max);
				if (x2 !== x1
						&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))
					roots[count++] = boundless ? x2 : clamp(x2, min, max);
				return count;
			},

			solveCubic: function(a, b, c, d, roots, min, max) {
				var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),
					x, b1, c2, qd, q;
				if (f) {
					a *= f;
					b *= f;
					c *= f;
					d *= f;
				}

				function evaluate(x0) {
					x = x0;
					var tmp = a * x;
					b1 = tmp + b;
					c2 = b1 * x + c;
					qd = (tmp + b1) * x + c2;
					q = c2 * x + d;
				}

				if (abs(a) < EPSILON) {
					a = b;
					b1 = c;
					c2 = d;
					x = Infinity;
				} else if (abs(d) < EPSILON) {
					b1 = b;
					c2 = c;
					x = 0;
				} else {
					evaluate(-(b / a) / 3);
					var t = q / a,
						r = pow(abs(t), 1/3),
						s = t < 0 ? -1 : 1,
						td = -qd / a,
						rd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,
						x0 = x - s * rd;
					if (x0 !== x) {
						do {
							evaluate(x0);
							x0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);
						} while (s * x0 > s * x);
						if (abs(a) * x * x > abs(d / x)) {
							c2 = -d / x;
							b1 = (c2 - c) / x;
						}
					}
				}
				var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),
					boundless = min == null;
				if (isFinite(x) && (count === 0
						|| count > 0 && x !== roots[0] && x !== roots[1])
						&& (boundless || x > min - EPSILON && x < max + EPSILON))
					roots[count++] = boundless ? x : clamp(x, min, max);
				return count;
			}
		};
	};

	var UID = {
		_id: 1,
		_pools: {},

		get: function(name) {
			if (name) {
				var pool = this._pools[name];
				if (!pool)
					pool = this._pools[name] = { _id: 1 };
				return pool._id++;
			} else {
				return this._id++;
			}
		}
	};

	var Point = Base.extend({
		_class: 'Point',
		_readIndex: true,

		initialize: function Point(arg0, arg1) {
			var type = typeof arg0;
			if (type === 'number') {
				var hasY = typeof arg1 === 'number';
				this.x = arg0;
				this.y = hasY ? arg1 : arg0;
				if (this.__read)
					this.__read = hasY ? 2 : 1;
			} else if (type === 'undefined' || arg0 === null) {
				this.x = this.y = 0;
				if (this.__read)
					this.__read = arg0 === null ? 1 : 0;
			} else {
				var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
				if (Array.isArray(obj)) {
					this.x = obj[0];
					this.y = obj.length > 1 ? obj[1] : obj[0];
				} else if ('x' in obj) {
					this.x = obj.x;
					this.y = obj.y;
				} else if ('width' in obj) {
					this.x = obj.width;
					this.y = obj.height;
				} else if ('angle' in obj) {
					this.x = obj.length;
					this.y = 0;
					this.setAngle(obj.angle);
				} else {
					this.x = this.y = 0;
					if (this.__read)
						this.__read = 0;
				}
				if (this.__read)
					this.__read = 1;
			}
		},

		set: function(x, y) {
			this.x = x;
			this.y = y;
			return this;
		},

		equals: function(point) {
			return this === point || point
					&& (this.x === point.x && this.y === point.y
						|| Array.isArray(point)
							&& this.x === point[0] && this.y === point[1])
					|| false;
		},

		clone: function() {
			return new Point(this.x, this.y);
		},

		toString: function() {
			var f = Formatter.instance;
			return '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';
		},

		_serialize: function(options) {
			var f = options.formatter;
			return [f.number(this.x), f.number(this.y)];
		},

		getLength: function() {
			return Math.sqrt(this.x * this.x + this.y * this.y);
		},

		setLength: function(length) {
			if (this.isZero()) {
				var angle = this._angle || 0;
				this.set(
					Math.cos(angle) * length,
					Math.sin(angle) * length
				);
			} else {
				var scale = length / this.getLength();
				if (Numerical.isZero(scale))
					this.getAngle();
				this.set(
					this.x * scale,
					this.y * scale
				);
			}
		},
		getAngle: function() {
			return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;
		},

		setAngle: function(angle) {
			this.setAngleInRadians.call(this, angle * Math.PI / 180);
		},

		getAngleInDegrees: '#getAngle',
		setAngleInDegrees: '#setAngle',

		getAngleInRadians: function() {
			if (!arguments.length) {
				return this.isZero()
						? this._angle || 0
						: this._angle = Math.atan2(this.y, this.x);
			} else {
				var point = Point.read(arguments),
					div = this.getLength() * point.getLength();
				if (Numerical.isZero(div)) {
					return NaN;
				} else {
					var a = this.dot(point) / div;
					return Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);
				}
			}
		},

		setAngleInRadians: function(angle) {
			this._angle = angle;
			if (!this.isZero()) {
				var length = this.getLength();
				this.set(
					Math.cos(angle) * length,
					Math.sin(angle) * length
				);
			}
		},

		getQuadrant: function() {
			return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;
		}
	}, {
		beans: false,

		getDirectedAngle: function() {
			var point = Point.read(arguments);
			return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;
		},

		getDistance: function() {
			var point = Point.read(arguments),
				x = point.x - this.x,
				y = point.y - this.y,
				d = x * x + y * y,
				squared = Base.read(arguments);
			return squared ? d : Math.sqrt(d);
		},

		normalize: function(length) {
			if (length === undefined)
				length = 1;
			var current = this.getLength(),
				scale = current !== 0 ? length / current : 0,
				point = new Point(this.x * scale, this.y * scale);
			if (scale >= 0)
				point._angle = this._angle;
			return point;
		},

		rotate: function(angle, center) {
			if (angle === 0)
				return this.clone();
			angle = angle * Math.PI / 180;
			var point = center ? this.subtract(center) : this,
				sin = Math.sin(angle),
				cos = Math.cos(angle);
			point = new Point(
				point.x * cos - point.y * sin,
				point.x * sin + point.y * cos
			);
			return center ? point.add(center) : point;
		},

		transform: function(matrix) {
			return matrix ? matrix._transformPoint(this) : this;
		},

		add: function() {
			var point = Point.read(arguments);
			return new Point(this.x + point.x, this.y + point.y);
		},

		subtract: function() {
			var point = Point.read(arguments);
			return new Point(this.x - point.x, this.y - point.y);
		},

		multiply: function() {
			var point = Point.read(arguments);
			return new Point(this.x * point.x, this.y * point.y);
		},

		divide: function() {
			var point = Point.read(arguments);
			return new Point(this.x / point.x, this.y / point.y);
		},

		modulo: function() {
			var point = Point.read(arguments);
			return new Point(this.x % point.x, this.y % point.y);
		},

		negate: function() {
			return new Point(-this.x, -this.y);
		},

		isInside: function() {
			return Rectangle.read(arguments).contains(this);
		},

		isClose: function() {
			var point = Point.read(arguments),
				tolerance = Base.read(arguments);
			return this.getDistance(point) <= tolerance;
		},

		isCollinear: function() {
			var point = Point.read(arguments);
			return Point.isCollinear(this.x, this.y, point.x, point.y);
		},

		isColinear: '#isCollinear',

		isOrthogonal: function() {
			var point = Point.read(arguments);
			return Point.isOrthogonal(this.x, this.y, point.x, point.y);
		},

		isZero: function() {
			return Numerical.isZero(this.x) && Numerical.isZero(this.y);
		},

		isNaN: function() {
			return isNaN(this.x) || isNaN(this.y);
		},

		dot: function() {
			var point = Point.read(arguments);
			return this.x * point.x + this.y * point.y;
		},

		cross: function() {
			var point = Point.read(arguments);
			return this.x * point.y - this.y * point.x;
		},

		project: function() {
			var point = Point.read(arguments),
				scale = point.isZero() ? 0 : this.dot(point) / point.dot(point);
			return new Point(
				point.x * scale,
				point.y * scale
			);
		},

		statics: {
			min: function() {
				var point1 = Point.read(arguments),
					point2 = Point.read(arguments);
				return new Point(
					Math.min(point1.x, point2.x),
					Math.min(point1.y, point2.y)
				);
			},

			max: function() {
				var point1 = Point.read(arguments),
					point2 = Point.read(arguments);
				return new Point(
					Math.max(point1.x, point2.x),
					Math.max(point1.y, point2.y)
				);
			},

			random: function() {
				return new Point(Math.random(), Math.random());
			},

			isCollinear: function(x1, y1, x2, y2) {
				return Math.abs(x1 * y2 - y1 * x2)
						<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
							* 1e-7;
			},

			isOrthogonal: function(x1, y1, x2, y2) {
				return Math.abs(x1 * x2 + y1 * y2)
						<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
							* 1e-7;
			}
		}
	}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
		var op = Math[key];
		this[key] = function() {
			return new Point(op(this.x), op(this.y));
		};
	}, {}));

	var LinkedPoint = Point.extend({
		initialize: function Point(x, y, owner, setter) {
			this._x = x;
			this._y = y;
			this._owner = owner;
			this._setter = setter;
		},

		set: function(x, y, _dontNotify) {
			this._x = x;
			this._y = y;
			if (!_dontNotify)
				this._owner[this._setter](this);
			return this;
		},

		getX: function() {
			return this._x;
		},

		setX: function(x) {
			this._x = x;
			this._owner[this._setter](this);
		},

		getY: function() {
			return this._y;
		},

		setY: function(y) {
			this._y = y;
			this._owner[this._setter](this);
		},

		isSelected: function() {
			return !!(this._owner._selection & this._getSelection());
		},

		setSelected: function(selected) {
			this._owner.changeSelection(this._getSelection(), selected);
		},

		_getSelection: function() {
			return this._setter === 'setPosition' ? 4 : 0;
		}
	});

	var Size = Base.extend({
		_class: 'Size',
		_readIndex: true,

		initialize: function Size(arg0, arg1) {
			var type = typeof arg0;
			if (type === 'number') {
				var hasHeight = typeof arg1 === 'number';
				this.width = arg0;
				this.height = hasHeight ? arg1 : arg0;
				if (this.__read)
					this.__read = hasHeight ? 2 : 1;
			} else if (type === 'undefined' || arg0 === null) {
				this.width = this.height = 0;
				if (this.__read)
					this.__read = arg0 === null ? 1 : 0;
			} else {
				var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0;
				if (Array.isArray(obj)) {
					this.width = obj[0];
					this.height = obj.length > 1 ? obj[1] : obj[0];
				} else if ('width' in obj) {
					this.width = obj.width;
					this.height = obj.height;
				} else if ('x' in obj) {
					this.width = obj.x;
					this.height = obj.y;
				} else {
					this.width = this.height = 0;
					if (this.__read)
						this.__read = 0;
				}
				if (this.__read)
					this.__read = 1;
			}
		},

		set: function(width, height) {
			this.width = width;
			this.height = height;
			return this;
		},

		equals: function(size) {
			return size === this || size && (this.width === size.width
					&& this.height === size.height
					|| Array.isArray(size) && this.width === size[0]
						&& this.height === size[1]) || false;
		},

		clone: function() {
			return new Size(this.width, this.height);
		},

		toString: function() {
			var f = Formatter.instance;
			return '{ width: ' + f.number(this.width)
					+ ', height: ' + f.number(this.height) + ' }';
		},

		_serialize: function(options) {
			var f = options.formatter;
			return [f.number(this.width),
					f.number(this.height)];
		},

		add: function() {
			var size = Size.read(arguments);
			return new Size(this.width + size.width, this.height + size.height);
		},

		subtract: function() {
			var size = Size.read(arguments);
			return new Size(this.width - size.width, this.height - size.height);
		},

		multiply: function() {
			var size = Size.read(arguments);
			return new Size(this.width * size.width, this.height * size.height);
		},

		divide: function() {
			var size = Size.read(arguments);
			return new Size(this.width / size.width, this.height / size.height);
		},

		modulo: function() {
			var size = Size.read(arguments);
			return new Size(this.width % size.width, this.height % size.height);
		},

		negate: function() {
			return new Size(-this.width, -this.height);
		},

		isZero: function() {
			return Numerical.isZero(this.width) && Numerical.isZero(this.height);
		},

		isNaN: function() {
			return isNaN(this.width) || isNaN(this.height);
		},

		statics: {
			min: function(size1, size2) {
				return new Size(
					Math.min(size1.width, size2.width),
					Math.min(size1.height, size2.height));
			},

			max: function(size1, size2) {
				return new Size(
					Math.max(size1.width, size2.width),
					Math.max(size1.height, size2.height));
			},

			random: function() {
				return new Size(Math.random(), Math.random());
			}
		}
	}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
		var op = Math[key];
		this[key] = function() {
			return new Size(op(this.width), op(this.height));
		};
	}, {}));

	var LinkedSize = Size.extend({
		initialize: function Size(width, height, owner, setter) {
			this._width = width;
			this._height = height;
			this._owner = owner;
			this._setter = setter;
		},

		set: function(width, height, _dontNotify) {
			this._width = width;
			this._height = height;
			if (!_dontNotify)
				this._owner[this._setter](this);
			return this;
		},

		getWidth: function() {
			return this._width;
		},

		setWidth: function(width) {
			this._width = width;
			this._owner[this._setter](this);
		},

		getHeight: function() {
			return this._height;
		},

		setHeight: function(height) {
			this._height = height;
			this._owner[this._setter](this);
		}
	});

	var Rectangle = Base.extend({
		_class: 'Rectangle',
		_readIndex: true,
		beans: true,

		initialize: function Rectangle(arg0, arg1, arg2, arg3) {
			var type = typeof arg0,
				read = 0;
			if (type === 'number') {
				this.x = arg0;
				this.y = arg1;
				this.width = arg2;
				this.height = arg3;
				read = 4;
			} else if (type === 'undefined' || arg0 === null) {
				this.x = this.y = this.width = this.height = 0;
				read = arg0 === null ? 1 : 0;
			} else if (arguments.length === 1) {
				if (Array.isArray(arg0)) {
					this.x = arg0[0];
					this.y = arg0[1];
					this.width = arg0[2];
					this.height = arg0[3];
					read = 1;
				} else if (arg0.x !== undefined || arg0.width !== undefined) {
					this.x = arg0.x || 0;
					this.y = arg0.y || 0;
					this.width = arg0.width || 0;
					this.height = arg0.height || 0;
					read = 1;
				} else if (arg0.from === undefined && arg0.to === undefined) {
					this.x = this.y = this.width = this.height = 0;
					this._set(arg0);
					read = 1;
				}
			}
			if (!read) {
				var point = Point.readNamed(arguments, 'from'),
					next = Base.peek(arguments);
				this.x = point.x;
				this.y = point.y;
				if (next && next.x !== undefined || Base.hasNamed(arguments, 'to')) {
					var to = Point.readNamed(arguments, 'to');
					this.width = to.x - point.x;
					this.height = to.y - point.y;
					if (this.width < 0) {
						this.x = to.x;
						this.width = -this.width;
					}
					if (this.height < 0) {
						this.y = to.y;
						this.height = -this.height;
					}
				} else {
					var size = Size.read(arguments);
					this.width = size.width;
					this.height = size.height;
				}
				read = arguments.__index;
			}
			if (this.__read)
				this.__read = read;
		},

		set: function(x, y, width, height) {
			this.x = x;
			this.y = y;
			this.width = width;
			this.height = height;
			return this;
		},

		clone: function() {
			return new Rectangle(this.x, this.y, this.width, this.height);
		},

		equals: function(rect) {
			var rt = Base.isPlainValue(rect)
					? Rectangle.read(arguments)
					: rect;
			return rt === this
					|| rt && this.x === rt.x && this.y === rt.y
						&& this.width === rt.width && this.height === rt.height
					|| false;
		},

		toString: function() {
			var f = Formatter.instance;
			return '{ x: ' + f.number(this.x)
					+ ', y: ' + f.number(this.y)
					+ ', width: ' + f.number(this.width)
					+ ', height: ' + f.number(this.height)
					+ ' }';
		},

		_serialize: function(options) {
			var f = options.formatter;
			return [f.number(this.x),
					f.number(this.y),
					f.number(this.width),
					f.number(this.height)];
		},

		getPoint: function(_dontLink) {
			var ctor = _dontLink ? Point : LinkedPoint;
			return new ctor(this.x, this.y, this, 'setPoint');
		},

		setPoint: function() {
			var point = Point.read(arguments);
			this.x = point.x;
			this.y = point.y;
		},

		getSize: function(_dontLink) {
			var ctor = _dontLink ? Size : LinkedSize;
			return new ctor(this.width, this.height, this, 'setSize');
		},

		setSize: function() {
			var size = Size.read(arguments);
			if (this._fixX)
				this.x += (this.width - size.width) * this._fixX;
			if (this._fixY)
				this.y += (this.height - size.height) * this._fixY;
			this.width = size.width;
			this.height = size.height;
			this._fixW = 1;
			this._fixH = 1;
		},

		getLeft: function() {
			return this.x;
		},

		setLeft: function(left) {
			if (!this._fixW)
				this.width -= left - this.x;
			this.x = left;
			this._fixX = 0;
		},

		getTop: function() {
			return this.y;
		},

		setTop: function(top) {
			if (!this._fixH)
				this.height -= top - this.y;
			this.y = top;
			this._fixY = 0;
		},

		getRight: function() {
			return this.x + this.width;
		},

		setRight: function(right) {
			if (this._fixX !== undefined && this._fixX !== 1)
				this._fixW = 0;
			if (this._fixW)
				this.x = right - this.width;
			else
				this.width = right - this.x;
			this._fixX = 1;
		},

		getBottom: function() {
			return this.y + this.height;
		},

		setBottom: function(bottom) {
			if (this._fixY !== undefined && this._fixY !== 1)
				this._fixH = 0;
			if (this._fixH)
				this.y = bottom - this.height;
			else
				this.height = bottom - this.y;
			this._fixY = 1;
		},

		getCenterX: function() {
			return this.x + this.width * 0.5;
		},

		setCenterX: function(x) {
			this.x = x - this.width * 0.5;
			this._fixX = 0.5;
		},

		getCenterY: function() {
			return this.y + this.height * 0.5;
		},

		setCenterY: function(y) {
			this.y = y - this.height * 0.5;
			this._fixY = 0.5;
		},

		getCenter: function(_dontLink) {
			var ctor = _dontLink ? Point : LinkedPoint;
			return new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');
		},

		setCenter: function() {
			var point = Point.read(arguments);
			this.setCenterX(point.x);
			this.setCenterY(point.y);
			return this;
		},

		getArea: function() {
			return this.width * this.height;
		},

		isEmpty: function() {
			return this.width === 0 || this.height === 0;
		},

		contains: function(arg) {
			return arg && arg.width !== undefined
					|| (Array.isArray(arg) ? arg : arguments).length === 4
					? this._containsRectangle(Rectangle.read(arguments))
					: this._containsPoint(Point.read(arguments));
		},

		_containsPoint: function(point) {
			var x = point.x,
				y = point.y;
			return x >= this.x && y >= this.y
					&& x <= this.x + this.width
					&& y <= this.y + this.height;
		},

		_containsRectangle: function(rect) {
			var x = rect.x,
				y = rect.y;
			return x >= this.x && y >= this.y
					&& x + rect.width <= this.x + this.width
					&& y + rect.height <= this.y + this.height;
		},

		intersects: function() {
			var rect = Rectangle.read(arguments);
			return rect.x + rect.width > this.x
					&& rect.y + rect.height > this.y
					&& rect.x < this.x + this.width
					&& rect.y < this.y + this.height;
		},

		touches: function() {
			var rect = Rectangle.read(arguments);
			return rect.x + rect.width >= this.x
					&& rect.y + rect.height >= this.y
					&& rect.x <= this.x + this.width
					&& rect.y <= this.y + this.height;
		},

		intersect: function() {
			var rect = Rectangle.read(arguments),
				x1 = Math.max(this.x, rect.x),
				y1 = Math.max(this.y, rect.y),
				x2 = Math.min(this.x + this.width, rect.x + rect.width),
				y2 = Math.min(this.y + this.height, rect.y + rect.height);
			return new Rectangle(x1, y1, x2 - x1, y2 - y1);
		},

		unite: function() {
			var rect = Rectangle.read(arguments),
				x1 = Math.min(this.x, rect.x),
				y1 = Math.min(this.y, rect.y),
				x2 = Math.max(this.x + this.width, rect.x + rect.width),
				y2 = Math.max(this.y + this.height, rect.y + rect.height);
			return new Rectangle(x1, y1, x2 - x1, y2 - y1);
		},

		include: function() {
			var point = Point.read(arguments);
			var x1 = Math.min(this.x, point.x),
				y1 = Math.min(this.y, point.y),
				x2 = Math.max(this.x + this.width, point.x),
				y2 = Math.max(this.y + this.height, point.y);
			return new Rectangle(x1, y1, x2 - x1, y2 - y1);
		},

		expand: function() {
			var amount = Size.read(arguments),
				hor = amount.width,
				ver = amount.height;
			return new Rectangle(this.x - hor / 2, this.y - ver / 2,
					this.width + hor, this.height + ver);
		},

		scale: function(hor, ver) {
			return this.expand(this.width * hor - this.width,
					this.height * (ver === undefined ? hor : ver) - this.height);
		}
	}, Base.each([
			['Top', 'Left'], ['Top', 'Right'],
			['Bottom', 'Left'], ['Bottom', 'Right'],
			['Left', 'Center'], ['Top', 'Center'],
			['Right', 'Center'], ['Bottom', 'Center']
		],
		function(parts, index) {
			var part = parts.join(''),
				xFirst = /^[RL]/.test(part);
			if (index >= 4)
				parts[1] += xFirst ? 'Y' : 'X';
			var x = parts[xFirst ? 0 : 1],
				y = parts[xFirst ? 1 : 0],
				getX = 'get' + x,
				getY = 'get' + y,
				setX = 'set' + x,
				setY = 'set' + y,
				get = 'get' + part,
				set = 'set' + part;
			this[get] = function(_dontLink) {
				var ctor = _dontLink ? Point : LinkedPoint;
				return new ctor(this[getX](), this[getY](), this, set);
			};
			this[set] = function() {
				var point = Point.read(arguments);
				this[setX](point.x);
				this[setY](point.y);
			};
		}, {
			beans: true
		}
	));

	var LinkedRectangle = Rectangle.extend({
		initialize: function Rectangle(x, y, width, height, owner, setter) {
			this.set(x, y, width, height, true);
			this._owner = owner;
			this._setter = setter;
		},

		set: function(x, y, width, height, _dontNotify) {
			this._x = x;
			this._y = y;
			this._width = width;
			this._height = height;
			if (!_dontNotify)
				this._owner[this._setter](this);
			return this;
		}
	},
	new function() {
		var proto = Rectangle.prototype;

		return Base.each(['x', 'y', 'width', 'height'], function(key) {
			var part = Base.capitalize(key),
				internal = '_' + key;
			this['get' + part] = function() {
				return this[internal];
			};

			this['set' + part] = function(value) {
				this[internal] = value;
				if (!this._dontNotify)
					this._owner[this._setter](this);
			};
		}, Base.each(['Point', 'Size', 'Center',
				'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',
				'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
				'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],
			function(key) {
				var name = 'set' + key;
				this[name] = function() {
					this._dontNotify = true;
					proto[name].apply(this, arguments);
					this._dontNotify = false;
					this._owner[this._setter](this);
				};
			}, {
				isSelected: function() {
					return !!(this._owner._selection & 2);
				},

				setSelected: function(selected) {
					var owner = this._owner;
					if (owner.changeSelection) {
						owner.changeSelection(2, selected);
					}
				}
			})
		);
	});

	var Matrix = Base.extend({
		_class: 'Matrix',

		initialize: function Matrix(arg) {
			var count = arguments.length,
				ok = true;
			if (count === 6) {
				this.set.apply(this, arguments);
			} else if (count === 1) {
				if (arg instanceof Matrix) {
					this.set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty);
				} else if (Array.isArray(arg)) {
					this.set.apply(this, arg);
				} else {
					ok = false;
				}
			} else if (count === 0) {
				this.reset();
			} else {
				ok = false;
			}
			if (!ok) {
				throw new Error('Unsupported matrix parameters');
			}
		},

		set: function(a, b, c, d, tx, ty, _dontNotify) {
			this._a = a;
			this._b = b;
			this._c = c;
			this._d = d;
			this._tx = tx;
			this._ty = ty;
			if (!_dontNotify)
				this._changed();
			return this;
		},

		_serialize: function(options, dictionary) {
			return Base.serialize(this.getValues(), options, true, dictionary);
		},

		_changed: function() {
			var owner = this._owner;
			if (owner) {
				if (owner._applyMatrix) {
					owner.transform(null, true);
				} else {
					owner._changed(9);
				}
			}
		},

		clone: function() {
			return new Matrix(this._a, this._b, this._c, this._d,
					this._tx, this._ty);
		},

		equals: function(mx) {
			return mx === this || mx && this._a === mx._a && this._b === mx._b
					&& this._c === mx._c && this._d === mx._d
					&& this._tx === mx._tx && this._ty === mx._ty;
		},

		toString: function() {
			var f = Formatter.instance;
			return '[[' + [f.number(this._a), f.number(this._c),
						f.number(this._tx)].join(', ') + '], ['
					+ [f.number(this._b), f.number(this._d),
						f.number(this._ty)].join(', ') + ']]';
		},

		reset: function(_dontNotify) {
			this._a = this._d = 1;
			this._b = this._c = this._tx = this._ty = 0;
			if (!_dontNotify)
				this._changed();
			return this;
		},

		apply: function(recursively, _setApplyMatrix) {
			var owner = this._owner;
			if (owner) {
				owner.transform(null, true, Base.pick(recursively, true),
						_setApplyMatrix);
				return this.isIdentity();
			}
			return false;
		},

		translate: function() {
			var point = Point.read(arguments),
				x = point.x,
				y = point.y;
			this._tx += x * this._a + y * this._c;
			this._ty += x * this._b + y * this._d;
			this._changed();
			return this;
		},

		scale: function() {
			var scale = Point.read(arguments),
				center = Point.read(arguments, 0, { readNull: true });
			if (center)
				this.translate(center);
			this._a *= scale.x;
			this._b *= scale.x;
			this._c *= scale.y;
			this._d *= scale.y;
			if (center)
				this.translate(center.negate());
			this._changed();
			return this;
		},

		rotate: function(angle ) {
			angle *= Math.PI / 180;
			var center = Point.read(arguments, 1),
				x = center.x,
				y = center.y,
				cos = Math.cos(angle),
				sin = Math.sin(angle),
				tx = x - x * cos + y * sin,
				ty = y - x * sin - y * cos,
				a = this._a,
				b = this._b,
				c = this._c,
				d = this._d;
			this._a = cos * a + sin * c;
			this._b = cos * b + sin * d;
			this._c = -sin * a + cos * c;
			this._d = -sin * b + cos * d;
			this._tx += tx * a + ty * c;
			this._ty += tx * b + ty * d;
			this._changed();
			return this;
		},

		shear: function() {
			var shear = Point.read(arguments),
				center = Point.read(arguments, 0, { readNull: true });
			if (center)
				this.translate(center);
			var a = this._a,
				b = this._b;
			this._a += shear.y * this._c;
			this._b += shear.y * this._d;
			this._c += shear.x * a;
			this._d += shear.x * b;
			if (center)
				this.translate(center.negate());
			this._changed();
			return this;
		},

		skew: function() {
			var skew = Point.read(arguments),
				center = Point.read(arguments, 0, { readNull: true }),
				toRadians = Math.PI / 180,
				shear = new Point(Math.tan(skew.x * toRadians),
					Math.tan(skew.y * toRadians));
			return this.shear(shear, center);
		},

		append: function(mx) {
			if (mx) {
				var a1 = this._a,
					b1 = this._b,
					c1 = this._c,
					d1 = this._d,
					a2 = mx._a,
					b2 = mx._c,
					c2 = mx._b,
					d2 = mx._d,
					tx2 = mx._tx,
					ty2 = mx._ty;
				this._a = a2 * a1 + c2 * c1;
				this._c = b2 * a1 + d2 * c1;
				this._b = a2 * b1 + c2 * d1;
				this._d = b2 * b1 + d2 * d1;
				this._tx += tx2 * a1 + ty2 * c1;
				this._ty += tx2 * b1 + ty2 * d1;
				this._changed();
			}
			return this;
		},

		prepend: function(mx) {
			if (mx) {
				var a1 = this._a,
					b1 = this._b,
					c1 = this._c,
					d1 = this._d,
					tx1 = this._tx,
					ty1 = this._ty,
					a2 = mx._a,
					b2 = mx._c,
					c2 = mx._b,
					d2 = mx._d,
					tx2 = mx._tx,
					ty2 = mx._ty;
				this._a = a2 * a1 + b2 * b1;
				this._c = a2 * c1 + b2 * d1;
				this._b = c2 * a1 + d2 * b1;
				this._d = c2 * c1 + d2 * d1;
				this._tx = a2 * tx1 + b2 * ty1 + tx2;
				this._ty = c2 * tx1 + d2 * ty1 + ty2;
				this._changed();
			}
			return this;
		},

		appended: function(mx) {
			return this.clone().append(mx);
		},

		prepended: function(mx) {
			return this.clone().prepend(mx);
		},

		invert: function() {
			var a = this._a,
				b = this._b,
				c = this._c,
				d = this._d,
				tx = this._tx,
				ty = this._ty,
				det = a * d - b * c,
				res = null;
			if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
				this._a = d / det;
				this._b = -b / det;
				this._c = -c / det;
				this._d = a / det;
				this._tx = (c * ty - d * tx) / det;
				this._ty = (b * tx - a * ty) / det;
				res = this;
			}
			return res;
		},

		inverted: function() {
			return this.clone().invert();
		},

		concatenate: '#append',
		preConcatenate: '#prepend',
		chain: '#appended',

		_shiftless: function() {
			return new Matrix(this._a, this._b, this._c, this._d, 0, 0);
		},

		_orNullIfIdentity: function() {
			return this.isIdentity() ? null : this;
		},

		isIdentity: function() {
			return this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1
					&& this._tx === 0 && this._ty === 0;
		},

		isInvertible: function() {
			var det = this._a * this._d - this._c * this._b;
			return det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);
		},

		isSingular: function() {
			return !this.isInvertible();
		},

		transform: function( src, dst, count) {
			return arguments.length < 3
				? this._transformPoint(Point.read(arguments))
				: this._transformCoordinates(src, dst, count);
		},

		_transformPoint: function(point, dest, _dontNotify) {
			var x = point.x,
				y = point.y;
			if (!dest)
				dest = new Point();
			return dest.set(
					x * this._a + y * this._c + this._tx,
					x * this._b + y * this._d + this._ty,
					_dontNotify);
		},

		_transformCoordinates: function(src, dst, count) {
			for (var i = 0, max = 2 * count; i < max; i += 2) {
				var x = src[i],
					y = src[i + 1];
				dst[i] = x * this._a + y * this._c + this._tx;
				dst[i + 1] = x * this._b + y * this._d + this._ty;
			}
			return dst;
		},

		_transformCorners: function(rect) {
			var x1 = rect.x,
				y1 = rect.y,
				x2 = x1 + rect.width,
				y2 = y1 + rect.height,
				coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];
			return this._transformCoordinates(coords, coords, 4);
		},

		_transformBounds: function(bounds, dest, _dontNotify) {
			var coords = this._transformCorners(bounds),
				min = coords.slice(0, 2),
				max = min.slice();
			for (var i = 2; i < 8; i++) {
				var val = coords[i],
					j = i & 1;
				if (val < min[j]) {
					min[j] = val;
				} else if (val > max[j]) {
					max[j] = val;
				}
			}
			if (!dest)
				dest = new Rectangle();
			return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1],
					_dontNotify);
		},

		inverseTransform: function() {
			return this._inverseTransform(Point.read(arguments));
		},

		_inverseTransform: function(point, dest, _dontNotify) {
			var a = this._a,
				b = this._b,
				c = this._c,
				d = this._d,
				tx = this._tx,
				ty = this._ty,
				det = a * d - b * c,
				res = null;
			if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {
				var x = point.x - this._tx,
					y = point.y - this._ty;
				if (!dest)
					dest = new Point();
				res = dest.set(
						(x * d - y * c) / det,
						(y * a - x * b) / det,
						_dontNotify);
			}
			return res;
		},

		decompose: function() {
			var a = this._a,
				b = this._b,
				c = this._c,
				d = this._d,
				det = a * d - b * c,
				sqrt = Math.sqrt,
				atan2 = Math.atan2,
				degrees = 180 / Math.PI,
				rotate,
				scale,
				skew;
			if (a !== 0 || b !== 0) {
				var r = sqrt(a * a + b * b);
				rotate = Math.acos(a / r) * (b > 0 ? 1 : -1);
				scale = [r, det / r];
				skew = [atan2(a * c + b * d, r * r), 0];
			} else if (c !== 0 || d !== 0) {
				var s = sqrt(c * c + d * d);
				rotate = Math.asin(c / s)  * (d > 0 ? 1 : -1);
				scale = [det / s, s];
				skew = [0, atan2(a * c + b * d, s * s)];
			} else {
				rotate = 0;
				skew = scale = [0, 0];
			}
			return {
				translation: this.getTranslation(),
				rotation: rotate * degrees,
				scaling: new Point(scale),
				skewing: new Point(skew[0] * degrees, skew[1] * degrees)
			};
		},

		getValues: function() {
			return [ this._a, this._b, this._c, this._d, this._tx, this._ty ];
		},

		getTranslation: function() {
			return new Point(this._tx, this._ty);
		},

		getScaling: function() {
			return (this.decompose() || {}).scaling;
		},

		getRotation: function() {
			return (this.decompose() || {}).rotation;
		},

		applyToContext: function(ctx) {
			if (!this.isIdentity()) {
				ctx.transform(this._a, this._b, this._c, this._d,
						this._tx, this._ty);
			}
		}
	}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {
		var part = Base.capitalize(key),
			prop = '_' + key;
		this['get' + part] = function() {
			return this[prop];
		};
		this['set' + part] = function(value) {
			this[prop] = value;
			this._changed();
		};
	}, {}));

	var Line = Base.extend({
		_class: 'Line',

		initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
			var asVector = false;
			if (arguments.length >= 4) {
				this._px = arg0;
				this._py = arg1;
				this._vx = arg2;
				this._vy = arg3;
				asVector = arg4;
			} else {
				this._px = arg0.x;
				this._py = arg0.y;
				this._vx = arg1.x;
				this._vy = arg1.y;
				asVector = arg2;
			}
			if (!asVector) {
				this._vx -= this._px;
				this._vy -= this._py;
			}
		},

		getPoint: function() {
			return new Point(this._px, this._py);
		},

		getVector: function() {
			return new Point(this._vx, this._vy);
		},

		getLength: function() {
			return this.getVector().getLength();
		},

		intersect: function(line, isInfinite) {
			return Line.intersect(
					this._px, this._py, this._vx, this._vy,
					line._px, line._py, line._vx, line._vy,
					true, isInfinite);
		},

		getSide: function(point, isInfinite) {
			return Line.getSide(
					this._px, this._py, this._vx, this._vy,
					point.x, point.y, true, isInfinite);
		},

		getDistance: function(point) {
			return Math.abs(Line.getSignedDistance(
					this._px, this._py, this._vx, this._vy,
					point.x, point.y, true));
		},

		isCollinear: function(line) {
			return Point.isCollinear(this._vx, this._vy, line._vx, line._vy);
		},

		isOrthogonal: function(line) {
			return Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);
		},

		statics: {
			intersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,
					isInfinite) {
				if (!asVector) {
					v1x -= p1x;
					v1y -= p1y;
					v2x -= p2x;
					v2y -= p2y;
				}
				var cross = v1x * v2y - v1y * v2x;
				if (!Numerical.isZero(cross)) {
					var dx = p1x - p2x,
						dy = p1y - p2y,
						u1 = (v2x * dy - v2y * dx) / cross,
						u2 = (v1x * dy - v1y * dx) / cross,
						epsilon = 1e-12,
						uMin = -epsilon,
						uMax = 1 + epsilon;
					if (isInfinite
							|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {
						if (!isInfinite) {
							u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;
						}
						return new Point(
								p1x + u1 * v1x,
								p1y + u1 * v1y);
					}
				}
			},

			getSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {
				if (!asVector) {
					vx -= px;
					vy -= py;
				}
				var v2x = x - px,
					v2y = y - py,
					ccw = v2x * vy - v2y * vx;
				if (ccw === 0 && !isInfinite) {
					ccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);
					if (ccw >= 0 && ccw <= 1)
						ccw = 0;
				}
				return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
			},

			getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
				if (!asVector) {
					vx -= px;
					vy -= py;
				}
				return vx === 0 ? vy > 0 ? x - px : px - x
					 : vy === 0 ? vx < 0 ? y - py : py - y
					 : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);
			}
		}
	});

	var Project = PaperScopeItem.extend({
		_class: 'Project',
		_list: 'projects',
		_reference: 'project',
		_compactSerialize: true,

		initialize: function Project(element) {
			PaperScopeItem.call(this, true);
			this._children = [];
			this._namedChildren = {};
			this._activeLayer = null;
			this._currentStyle = new Style(null, null, this);
			this._view = View.create(this,
					element || CanvasProvider.getCanvas(1, 1));
			this._selectionItems = {};
			this._selectionCount = 0;
			this._updateVersion = 0;
		},

		_serialize: function(options, dictionary) {
			return Base.serialize(this._children, options, true, dictionary);
		},

		_changed: function(flags, item) {
			if (flags & 1) {
				var view = this._view;
				if (view) {
					view._needsUpdate = true;
					if (!view._requested && view._autoUpdate)
						view.requestUpdate();
				}
			}
			var changes = this._changes;
			if (changes && item) {
				var changesById = this._changesById,
					id = item._id,
					entry = changesById[id];
				if (entry) {
					entry.flags |= flags;
				} else {
					changes.push(changesById[id] = { item: item, flags: flags });
				}
			}
		},

		clear: function() {
			var children = this._children;
			for (var i = children.length - 1; i >= 0; i--)
				children[i].remove();
		},

		isEmpty: function() {
			return this._children.length === 0;
		},

		remove: function remove() {
			if (!remove.base.call(this))
				return false;
			if (this._view)
				this._view.remove();
			return true;
		},

		getView: function() {
			return this._view;
		},

		getCurrentStyle: function() {
			return this._currentStyle;
		},

		setCurrentStyle: function(style) {
			this._currentStyle.initialize(style);
		},

		getIndex: function() {
			return this._index;
		},

		getOptions: function() {
			return this._scope.settings;
		},

		getLayers: function() {
			return this._children;
		},

		getActiveLayer: function() {
			return this._activeLayer || new Layer({ project: this, insert: true });
		},

		getSymbolDefinitions: function() {
			var definitions = [],
				ids = {};
			this.getItems({
				class: SymbolItem,
				match: function(item) {
					var definition = item._definition,
						id = definition._id;
					if (!ids[id]) {
						ids[id] = true;
						definitions.push(definition);
					}
					return false;
				}
			});
			return definitions;
		},

		getSymbols: 'getSymbolDefinitions',

		getSelectedItems: function() {
			var selectionItems = this._selectionItems,
				items = [];
			for (var id in selectionItems) {
				var item = selectionItems[id],
					selection = item._selection;
				if (selection & 1 && item.isInserted()) {
					items.push(item);
				} else if (!selection) {
					this._updateSelection(item);
				}
			}
			return items;
		},

		_updateSelection: function(item) {
			var id = item._id,
				selectionItems = this._selectionItems;
			if (item._selection) {
				if (selectionItems[id] !== item) {
					this._selectionCount++;
					selectionItems[id] = item;
				}
			} else if (selectionItems[id] === item) {
				this._selectionCount--;
				delete selectionItems[id];
			}
		},

		selectAll: function() {
			var children = this._children;
			for (var i = 0, l = children.length; i < l; i++)
				children[i].setFullySelected(true);
		},

		deselectAll: function() {
			var selectionItems = this._selectionItems;
			for (var i in selectionItems)
				selectionItems[i].setFullySelected(false);
		},

		addLayer: function(layer) {
			return this.insertLayer(undefined, layer);
		},

		insertLayer: function(index, layer) {
			if (layer instanceof Layer) {
				layer._remove(false, true);
				Base.splice(this._children, [layer], index, 0);
				layer._setProject(this, true);
				var name = layer._name;
				if (name)
					layer.setName(name);
				if (this._changes)
					layer._changed(5);
				if (!this._activeLayer)
					this._activeLayer = layer;
			} else {
				layer = null;
			}
			return layer;
		},

		_insertItem: function(index, item, _preserve, _created) {
			item = this.insertLayer(index, item)
					|| (this._activeLayer || this._insertItem(undefined,
							new Layer(Item.NO_INSERT), true, true))
							.insertChild(index, item, _preserve);
			if (_created && item.activate)
				item.activate();
			return item;
		},

		getItems: function(options) {
			return Item._getItems(this, options);
		},

		getItem: function(options) {
			return Item._getItems(this, options, null, null, true)[0] || null;
		},

		importJSON: function(json) {
			this.activate();
			var layer = this._activeLayer;
			return Base.importJSON(json, layer && layer.isEmpty() && layer);
		},

		removeOn: function(type) {
			var sets = this._removeSets;
			if (sets) {
				if (type === 'mouseup')
					sets.mousedrag = null;
				var set = sets[type];
				if (set) {
					for (var id in set) {
						var item = set[id];
						for (var key in sets) {
							var other = sets[key];
							if (other && other != set)
								delete other[item._id];
						}
						item.remove();
					}
					sets[type] = null;
				}
			}
		},

		draw: function(ctx, matrix, pixelRatio) {
			this._updateVersion++;
			ctx.save();
			matrix.applyToContext(ctx);
			var children = this._children,
				param = new Base({
					offset: new Point(0, 0),
					pixelRatio: pixelRatio,
					viewMatrix: matrix.isIdentity() ? null : matrix,
					matrices: [new Matrix()],
					updateMatrix: true
				});
			for (var i = 0, l = children.length; i < l; i++) {
				children[i].draw(ctx, param);
			}
			ctx.restore();

			if (this._selectionCount > 0) {
				ctx.save();
				ctx.strokeWidth = 1;
				var items = this._selectionItems,
					size = this._scope.settings.handleSize,
					version = this._updateVersion;
				for (var id in items) {
					items[id]._drawSelection(ctx, matrix, size, items, version);
				}
				ctx.restore();
			}
		}
	});

	var Item = Base.extend(Emitter, {
		statics: {
			extend: function extend(src) {
				if (src._serializeFields)
					src._serializeFields = Base.set({},
						this.prototype._serializeFields, src._serializeFields);
				return extend.base.apply(this, arguments);
			},

			NO_INSERT: { insert: false }
		},

		_class: 'Item',
		_name: null,
		_applyMatrix: true,
		_canApplyMatrix: true,
		_canScaleStroke: false,
		_pivot: null,
		_visible: true,
		_blendMode: 'normal',
		_opacity: 1,
		_locked: false,
		_guide: false,
		_clipMask: false,
		_selection: 0,
		_selectBounds: true,
		_selectChildren: false,
		_serializeFields: {
			name: null,
			applyMatrix: null,
			matrix: new Matrix(),
			pivot: null,
			visible: true,
			blendMode: 'normal',
			opacity: 1,
			locked: false,
			guide: false,
			clipMask: false,
			selected: false,
			data: {}
		}
	},
	new function() {
		var handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',
				'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];
		return Base.each(handlers,
			function(name) {
				this._events[name] = {
					install: function(type) {
						this.getView()._countItemEvent(type, 1);
					},

					uninstall: function(type) {
						this.getView()._countItemEvent(type, -1);
					}
				};
			}, {
				_events: {
					onFrame: {
						install: function() {
							this.getView()._animateItem(this, true);
						},

						uninstall: function() {
							this.getView()._animateItem(this, false);
						}
					},

					onLoad: {},
					onError: {}
				},
				statics: {
					_itemHandlers: handlers
				}
			}
		);
	}, {
		initialize: function Item() {
		},

		_initialize: function(props, point) {
			var hasProps = props && Base.isPlainObject(props),
				internal = hasProps && props.internal === true,
				matrix = this._matrix = new Matrix(),
				project = hasProps && props.project || paper.project,
				settings = paper.settings;
			this._id = internal ? null : UID.get();
			this._parent = this._index = null;
			this._applyMatrix = this._canApplyMatrix && settings.applyMatrix;
			if (point)
				matrix.translate(point);
			matrix._owner = this;
			this._style = new Style(project._currentStyle, this, project);
			if (internal || hasProps && props.insert === false
				|| !settings.insertItems && !(hasProps && props.insert === true)) {
				this._setProject(project);
			} else {
				(hasProps && props.parent || project)
						._insertItem(undefined, this, true, true);
			}
			if (hasProps && props !== Item.NO_INSERT) {
				Base.filter(this, props, {
					internal: true, insert: true, project: true, parent: true
				});
			}
			return hasProps;
		},

		_serialize: function(options, dictionary) {
			var props = {},
				that = this;

			function serialize(fields) {
				for (var key in fields) {
					var value = that[key];
					if (!Base.equals(value, key === 'leading'
							? fields.fontSize * 1.2 : fields[key])) {
						props[key] = Base.serialize(value, options,
								key !== 'data', dictionary);
					}
				}
			}

			serialize(this._serializeFields);
			if (!(this instanceof Group))
				serialize(this._style._defaults);
			return [ this._class, props ];
		},

		_changed: function(flags) {
			var symbol = this._symbol,
				cacheParent = this._parent || symbol,
				project = this._project;
			if (flags & 8) {
				this._bounds = this._position = this._decomposed =
						this._globalMatrix = undefined;
			}
			if (cacheParent
					&& (flags & 40)) {
				Item._clearBoundsCache(cacheParent);
			}
			if (flags & 2) {
				Item._clearBoundsCache(this);
			}
			if (project)
				project._changed(flags, this);
			if (symbol)
				symbol._changed(flags);
		},

		set: function(props) {
			if (props)
				this._set(props);
			return this;
		},

		getId: function() {
			return this._id;
		},

		getName: function() {
			return this._name;
		},

		setName: function(name) {

			if (this._name)
				this._removeNamed();
			if (name === (+name) + '')
				throw new Error(
						'Names consisting only of numbers are not supported.');
			var owner = this._getOwner();
			if (name && owner) {
				var children = owner._children,
					namedChildren = owner._namedChildren;
				(namedChildren[name] = namedChildren[name] || []).push(this);
				if (!(name in children))
					children[name] = this;
			}
			this._name = name || undefined;
			this._changed(128);
		},

		getStyle: function() {
			return this._style;
		},

		setStyle: function(style) {
			this.getStyle().set(style);
		}
	}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],
		function(name) {
			var part = Base.capitalize(name),
				name = '_' + name;
			this['get' + part] = function() {
				return this[name];
			};
			this['set' + part] = function(value) {
				if (value != this[name]) {
					this[name] = value;
					this._changed(name === '_locked'
							? 128 : 129);
				}
			};
		},
	{}), {
		beans: true,

		getSelection: function() {
			return this._selection;
		},

		setSelection: function(selection) {
			if (selection !== this._selection) {
				this._selection = selection;
				var project = this._project;
				if (project) {
					project._updateSelection(this);
					this._changed(129);
				}
			}
		},

		changeSelection: function(flag, selected) {
			var selection = this._selection;
			this.setSelection(selected ? selection | flag : selection & ~flag);
		},

		isSelected: function() {
			if (this._selectChildren) {
				var children = this._children;
				for (var i = 0, l = children.length; i < l; i++)
					if (children[i].isSelected())
						return true;
			}
			return !!(this._selection & 1);
		},

		setSelected: function(selected) {
			if (this._selectChildren) {
				var children = this._children;
				for (var i = 0, l = children.length; i < l; i++)
					children[i].setSelected(selected);
			}
			this.changeSelection(1, selected);
		},

		isFullySelected: function() {
			var children = this._children,
				selected = !!(this._selection & 1);
			if (children && selected) {
				for (var i = 0, l = children.length; i < l; i++)
					if (!children[i].isFullySelected())
						return false;
				return true;
			}
			return selected;
		},

		setFullySelected: function(selected) {
			var children = this._children;
			if (children) {
				for (var i = 0, l = children.length; i < l; i++)
					children[i].setFullySelected(selected);
			}
			this.changeSelection(1, selected);
		},

		isClipMask: function() {
			return this._clipMask;
		},

		setClipMask: function(clipMask) {
			if (this._clipMask != (clipMask = !!clipMask)) {
				this._clipMask = clipMask;
				if (clipMask) {
					this.setFillColor(null);
					this.setStrokeColor(null);
				}
				this._changed(129);
				if (this._parent)
					this._parent._changed(1024);
			}
		},

		getData: function() {
			if (!this._data)
				this._data = {};
			return this._data;
		},

		setData: function(data) {
			this._data = data;
		},

		getPosition: function(_dontLink) {
			var position = this._position,
				ctor = _dontLink ? Point : LinkedPoint;
			if (!position) {
				var pivot = this._pivot;
				position = this._position = pivot
						? this._matrix._transformPoint(pivot)
						: this.getBounds().getCenter(true);
			}
			return new ctor(position.x, position.y, this, 'setPosition');
		},

		setPosition: function() {
			this.translate(Point.read(arguments).subtract(this.getPosition(true)));
		},

		getPivot: function(_dontLink) {
			var pivot = this._pivot;
			if (pivot) {
				var ctor = _dontLink ? Point : LinkedPoint;
				pivot = new ctor(pivot.x, pivot.y, this, 'setPivot');
			}
			return pivot;
		},

		setPivot: function() {
			this._pivot = Point.read(arguments, 0, { clone: true, readNull: true });
			this._position = undefined;
		}
	}, Base.each({
			getStrokeBounds: { stroke: true },
			getHandleBounds: { handle: true },
			getInternalBounds: { internal: true }
		},
		function(options, key) {
			this[key] = function(matrix) {
				return this.getBounds(matrix, options);
			};
		},
	{
		beans: true,

		getBounds: function(matrix, options) {
			var hasMatrix = options || matrix instanceof Matrix,
				opts = Base.set({}, hasMatrix ? options : matrix,
						this._boundsOptions);
			if (!opts.stroke || this.getStrokeScaling())
				opts.cacheItem = this;
			var bounds = this._getCachedBounds(hasMatrix && matrix, opts);
			return arguments.length === 0
					? new LinkedRectangle(bounds.x, bounds.y, bounds.width,
							bounds.height, this, 'setBounds')
					: bounds;
		},

		setBounds: function() {
			var rect = Rectangle.read(arguments),
				bounds = this.getBounds(),
				_matrix = this._matrix,
				matrix = new Matrix(),
				center = rect.getCenter();
			matrix.translate(center);
			if (rect.width != bounds.width || rect.height != bounds.height) {
				if (!_matrix.isInvertible()) {
					_matrix.initialize(_matrix._backup
							|| new Matrix().translate(_matrix.getTranslation()));
					bounds = this.getBounds();
				}
				matrix.scale(
						bounds.width !== 0 ? rect.width / bounds.width : 0,
						bounds.height !== 0 ? rect.height / bounds.height : 0);
			}
			center = bounds.getCenter();
			matrix.translate(-center.x, -center.y);
			this.transform(matrix);
		},

		_getBounds: function(matrix, options) {
			var children = this._children;
			if (!children || children.length === 0)
				return new Rectangle();
			Item._updateBoundsCache(this, options.cacheItem);
			return Item._getBounds(children, matrix, options);
		},

		_getCachedBounds: function(matrix, options) {
			matrix = matrix && matrix._orNullIfIdentity();
			var internal = options.internal,
				cacheItem = options.cacheItem,
				_matrix = internal ? null : this._matrix._orNullIfIdentity(),
				cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [
					options.stroke ? 1 : 0,
					options.handle ? 1 : 0,
					internal ? 1 : 0
				].join('');
			Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
			if (cacheKey && this._bounds && cacheKey in this._bounds)
				return this._bounds[cacheKey].rect.clone();
			var bounds = this._getBounds(matrix || _matrix, options);
			if (cacheKey) {
				if (!this._bounds)
					this._bounds = {};
				var cached = this._bounds[cacheKey] = {
					rect: bounds.clone(),
					internal: options.internal
				};
			}
			return bounds;
		},

		_getStrokeMatrix: function(matrix, options) {
			var parent = this.getStrokeScaling() ? null
					: options && options.internal ? this
						: this._parent || this._symbol && this._symbol._item,
				mx = parent ? parent.getViewMatrix().invert() : matrix;
			return mx && mx._shiftless();
		},

		statics: {
			_updateBoundsCache: function(parent, item) {
				if (parent && item) {
					var id = item._id,
						ref = parent._boundsCache = parent._boundsCache || {
							ids: {},
							list: []
						};
					if (!ref.ids[id]) {
						ref.list.push(item);
						ref.ids[id] = item;
					}
				}
			},

			_clearBoundsCache: function(item) {
				var cache = item._boundsCache;
				if (cache) {
					item._bounds = item._position = item._boundsCache = undefined;
					for (var i = 0, list = cache.list, l = list.length; i < l; i++){
						var other = list[i];
						if (other !== item) {
							other._bounds = other._position = undefined;
							if (other._boundsCache)
								Item._clearBoundsCache(other);
						}
					}
				}
			},

			_getBounds: function(items, matrix, options) {
				var x1 = Infinity,
					x2 = -x1,
					y1 = x1,
					y2 = x2;
				options = options || {};
				for (var i = 0, l = items.length; i < l; i++) {
					var item = items[i];
					if (item._visible && !item.isEmpty()) {
						var rect = item._getCachedBounds(
							matrix && matrix.appended(item._matrix), options);
						x1 = Math.min(rect.x, x1);
						y1 = Math.min(rect.y, y1);
						x2 = Math.max(rect.x + rect.width, x2);
						y2 = Math.max(rect.y + rect.height, y2);
					}
				}
				return isFinite(x1)
						? new Rectangle(x1, y1, x2 - x1, y2 - y1)
						: new Rectangle();
			}
		}

	}), {
		beans: true,

		_decompose: function() {
			return this._decomposed || (this._decomposed = this._matrix.decompose());
		},

		getRotation: function() {
			var decomposed = this._decompose();
			return decomposed && decomposed.rotation;
		},

		setRotation: function(rotation) {
			var current = this.getRotation();
			if (current != null && rotation != null) {
				this.rotate(rotation - current);
			}
		},

		getScaling: function(_dontLink) {
			var decomposed = this._decompose(),
				scaling = decomposed && decomposed.scaling,
				ctor = _dontLink ? Point : LinkedPoint;
			return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling');
		},

		setScaling: function() {
			var current = this.getScaling(),
				scaling = Point.read(arguments, 0, { clone: true, readNull: true });
			if (current && scaling) {
				this.scale(scaling.x / current.x, scaling.y / current.y);
			}
		},

		getMatrix: function() {
			return this._matrix;
		},

		setMatrix: function() {
			var matrix = this._matrix;
			matrix.initialize.apply(matrix, arguments);
		},

		getGlobalMatrix: function(_dontClone) {
			var matrix = this._globalMatrix,
				updateVersion = this._project._updateVersion;
			if (matrix && matrix._updateVersion !== updateVersion)
				matrix = null;
			if (!matrix) {
				matrix = this._globalMatrix = this._matrix.clone();
				var parent = this._parent;
				if (parent)
					matrix.prepend(parent.getGlobalMatrix(true));
				matrix._updateVersion = updateVersion;
			}
			return _dontClone ? matrix : matrix.clone();
		},

		getViewMatrix: function() {
			return this.getGlobalMatrix().prepend(this.getView()._matrix);
		},

		getApplyMatrix: function() {
			return this._applyMatrix;
		},

		setApplyMatrix: function(apply) {
			if (this._applyMatrix = this._canApplyMatrix && !!apply)
				this.transform(null, true);
		},

		getTransformContent: '#getApplyMatrix',
		setTransformContent: '#setApplyMatrix',
	}, {
		getProject: function() {
			return this._project;
		},

		_setProject: function(project, installEvents) {
			if (this._project !== project) {
				if (this._project)
					this._installEvents(false);
				this._project = project;
				var children = this._children;
				for (var i = 0, l = children && children.length; i < l; i++)
					children[i]._setProject(project);
				installEvents = true;
			}
			if (installEvents)
				this._installEvents(true);
		},

		getView: function() {
			return this._project._view;
		},

		_installEvents: function _installEvents(install) {
			_installEvents.base.call(this, install);
			var children = this._children;
			for (var i = 0, l = children && children.length; i < l; i++)
				children[i]._installEvents(install);
		},

		getLayer: function() {
			var parent = this;
			while (parent = parent._parent) {
				if (parent instanceof Layer)
					return parent;
			}
			return null;
		},

		getParent: function() {
			return this._parent;
		},

		setParent: function(item) {
			return item.addChild(this);
		},

		_getOwner: '#getParent',

		getChildren: function() {
			return this._children;
		},

		setChildren: function(items, _preserve) {
			this.removeChildren();
			this.addChildren(items, _preserve);
		},

		getFirstChild: function() {
			return this._children && this._children[0] || null;
		},

		getLastChild: function() {
			return this._children && this._children[this._children.length - 1]
					|| null;
		},

		getNextSibling: function() {
			var owner = this._getOwner();
			return owner && owner._children[this._index + 1] || null;
		},

		getPreviousSibling: function() {
			var owner = this._getOwner();
			return owner && owner._children[this._index - 1] || null;
		},

		getIndex: function() {
			return this._index;
		},

		equals: function(item) {
			return item === this || item && this._class === item._class
					&& this._style.equals(item._style)
					&& this._matrix.equals(item._matrix)
					&& this._locked === item._locked
					&& this._visible === item._visible
					&& this._blendMode === item._blendMode
					&& this._opacity === item._opacity
					&& this._clipMask === item._clipMask
					&& this._guide === item._guide
					&& this._equals(item)
					|| false;
		},

		_equals: function(item) {
			return Base.equals(this._children, item._children);
		},

		clone: function(options) {
			var copy = new this.constructor(Item.NO_INSERT),
				children = this._children,
				insert = Base.pick(options ? options.insert : undefined,
						options === undefined || options === true),
				deep = Base.pick(options ? options.deep : undefined, true);
			if (children)
				copy.copyAttributes(this);
			if (!children || deep)
				copy.copyContent(this);
			if (!children)
				copy.copyAttributes(this);
			if (insert)
				copy.insertAbove(this);
			var name = this._name,
				parent = this._parent;
			if (name && parent) {
				var children = parent._children,
					orig = name,
					i = 1;
				while (children[name])
					name = orig + ' ' + (i++);
				if (name !== orig)
					copy.setName(name);
			}
			return copy;
		},

		copyContent: function(source) {
			var children = source._children;
			for (var i = 0, l = children && children.length; i < l; i++) {
				this.addChild(children[i].clone(false), true);
			}
		},

		copyAttributes: function(source, excludeMatrix) {
			this.setStyle(source._style);
			var keys = ['_locked', '_visible', '_blendMode', '_opacity',
					'_clipMask', '_guide'];
			for (var i = 0, l = keys.length; i < l; i++) {
				var key = keys[i];
				if (source.hasOwnProperty(key))
					this[key] = source[key];
			}
			if (!excludeMatrix)
				this._matrix.initialize(source._matrix);
			this.setApplyMatrix(source._applyMatrix);
			this.setPivot(source._pivot);
			this.setSelection(source._selection);
			var data = source._data,
				name = source._name;
			this._data = data ? Base.clone(data) : null;
			if (name)
				this.setName(name);
		},

		rasterize: function(resolution, insert) {
			var bounds = this.getStrokeBounds(),
				scale = (resolution || this.getView().getResolution()) / 72,
				topLeft = bounds.getTopLeft().floor(),
				bottomRight = bounds.getBottomRight().ceil(),
				size = new Size(bottomRight.subtract(topLeft)),
				raster = new Raster(Item.NO_INSERT);
			if (!size.isZero()) {
				var canvas = CanvasProvider.getCanvas(size.multiply(scale)),
					ctx = canvas.getContext('2d'),
					matrix = new Matrix().scale(scale).translate(topLeft.negate());
				ctx.save();
				matrix.applyToContext(ctx);
				this.draw(ctx, new Base({ matrices: [matrix] }));
				ctx.restore();
				raster.setCanvas(canvas);
			}
			raster.transform(new Matrix().translate(topLeft.add(size.divide(2)))
					.scale(1 / scale));
			if (insert === undefined || insert)
				raster.insertAbove(this);
			return raster;
		},

		contains: function() {
			return !!this._contains(
					this._matrix._inverseTransform(Point.read(arguments)));
		},

		_contains: function(point) {
			var children = this._children;
			if (children) {
				for (var i = children.length - 1; i >= 0; i--) {
					if (children[i].contains(point))
						return true;
				}
				return false;
			}
			return point.isInside(this.getInternalBounds());
		},

		isInside: function() {
			return Rectangle.read(arguments).contains(this.getBounds());
		},

		_asPathItem: function() {
			return new Path.Rectangle({
				rectangle: this.getInternalBounds(),
				matrix: this._matrix,
				insert: false,
			});
		},

		intersects: function(item, _matrix) {
			if (!(item instanceof Item))
				return false;
			return this._asPathItem().getIntersections(item._asPathItem(), null,
					_matrix, true).length > 0;
		}
	},
	new function() {
		function hitTest() {
			return this._hitTest(
					Point.read(arguments),
					HitResult.getOptions(arguments));
		}

		function hitTestAll() {
			var point = Point.read(arguments),
				options = HitResult.getOptions(arguments),
				callback = options.match,
				results = [];
			options = Base.set({}, options, {
				match: function(hit) {
					if (!callback || callback(hit))
						results.push(hit);
				}
			});
			this._hitTest(point, options);
			return results;
		}

		function hitTestChildren(point, options, viewMatrix, _exclude) {
			var children = this._children;
			if (children) {
				for (var i = children.length - 1; i >= 0; i--) {
					var child = children[i];
					var res = child !== _exclude && child._hitTest(point, options,
							viewMatrix);
					if (res)
						return res;
				}
			}
			return null;
		}

		Project.inject({
			hitTest: hitTest,
			hitTestAll: hitTestAll,
			_hitTest: hitTestChildren
		});

		return {
			hitTest: hitTest,
			hitTestAll: hitTestAll,
			_hitTestChildren: hitTestChildren,
		};
	}, {

		_hitTest: function(point, options, parentViewMatrix) {
			if (this._locked || !this._visible || this._guide && !options.guides
					|| this.isEmpty()) {
				return null;
			}

			var matrix = this._matrix,
				viewMatrix = parentViewMatrix
						? parentViewMatrix.appended(matrix)
						: this.getGlobalMatrix().prepend(this.getView()._matrix),
				strokeMatrix = this.getStrokeScaling()
						? null
						: viewMatrix.inverted()._shiftless(),
				tolerance = Math.max(options.tolerance, 1e-6),
				tolerancePadding = options._tolerancePadding = new Size(
						Path._getStrokePadding(tolerance, strokeMatrix));
			point = matrix._inverseTransform(point);
			if (!point || !this._children &&
				!this.getBounds({ internal: true, stroke: true, handle: true })
					.expand(tolerancePadding.multiply(2))._containsPoint(point)) {
				return null;
			}

			var checkSelf = !(options.guides && !this._guide
					|| options.selected && !this.isSelected()
					|| options.type && options.type !== Base.hyphenate(this._class)
					|| options.class && !(this instanceof options.class)),
				callback = options.match,
				that = this,
				bounds,
				res;

			function match(hit) {
				return !callback || hit && callback(hit) ? hit : null;
			}

			function checkBounds(type, part) {
				var pt = bounds['get' + part]();
				if (point.subtract(pt).divide(tolerancePadding).length <= 1) {
					return new HitResult(type, that,
							{ name: Base.hyphenate(part), point: pt });
				}
			}

			if (checkSelf && (options.center || options.bounds) && this._parent) {
				bounds = this.getInternalBounds();
				if (options.center) {
					res = checkBounds('center', 'Center');
				}
				if (!res && options.bounds) {
					var points = [
						'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',
						'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'
					];
					for (var i = 0; i < 8 && !res; i++) {
						res = checkBounds('bounds', points[i]);
					}
				}
				res = match(res);
			}

			if (!res) {
				res = this._hitTestChildren(point, options, viewMatrix)
					|| checkSelf
						&& match(this._hitTestSelf(point, options, viewMatrix,
							strokeMatrix))
					|| null;
			}
			if (res && res.point) {
				res.point = matrix.transform(res.point);
			}
			return res;
		},

		_hitTestSelf: function(point, options) {
			if (options.fill && this.hasFill() && this._contains(point))
				return new HitResult('fill', this);
		},

		matches: function(name, compare) {
			function matchObject(obj1, obj2) {
				for (var i in obj1) {
					if (obj1.hasOwnProperty(i)) {
						var val1 = obj1[i],
							val2 = obj2[i];
						if (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {
							if (!matchObject(val1, val2))
								return false;
						} else if (!Base.equals(val1, val2)) {
							return false;
						}
					}
				}
				return true;
			}
			var type = typeof name;
			if (type === 'object') {
				for (var key in name) {
					if (name.hasOwnProperty(key) && !this.matches(key, name[key]))
						return false;
				}
				return true;
			} else if (type === 'function') {
				return name(this);
			} else if (name === 'match') {
				return compare(this);
			} else {
				var value = /^(empty|editable)$/.test(name)
						? this['is' + Base.capitalize(name)]()
						: name === 'type'
							? Base.hyphenate(this._class)
							: this[name];
				if (name === 'class') {
					if (typeof compare === 'function')
						return this instanceof compare;
					value = this._class;
				}
				if (typeof compare === 'function') {
					return !!compare(value);
				} else if (compare) {
					if (compare.test) {
						return compare.test(value);
					} else if (Base.isPlainObject(compare)) {
						return matchObject(compare, value);
					}
				}
				return Base.equals(value, compare);
			}
		},

		getItems: function(options) {
			return Item._getItems(this, options, this._matrix);
		},

		getItem: function(options) {
			return Item._getItems(this, options, this._matrix, null, true)[0]
					|| null;
		},

		statics: {
			_getItems: function _getItems(item, options, matrix, param, firstOnly) {
				if (!param) {
					var obj = typeof options === 'object' && options,
						overlapping = obj && obj.overlapping,
						inside = obj && obj.inside,
						bounds = overlapping || inside,
						rect = bounds && Rectangle.read([bounds]);
					param = {
						items: [],
						recursive: obj && obj.recursive !== false,
						inside: !!inside,
						overlapping: !!overlapping,
						rect: rect,
						path: overlapping && new Path.Rectangle({
							rectangle: rect,
							insert: false
						})
					};
					if (obj) {
						options = Base.filter({}, options, {
							recursive: true, inside: true, overlapping: true
						});
					}
				}
				var children = item._children,
					items = param.items,
					rect = param.rect;
				matrix = rect && (matrix || new Matrix());
				for (var i = 0, l = children && children.length; i < l; i++) {
					var child = children[i],
						childMatrix = matrix && matrix.appended(child._matrix),
						add = true;
					if (rect) {
						var bounds = child.getBounds(childMatrix);
						if (!rect.intersects(bounds))
							continue;
						if (!(rect.contains(bounds)
								|| param.overlapping && (bounds.contains(rect)
									|| param.path.intersects(child, childMatrix))))
							add = false;
					}
					if (add && child.matches(options)) {
						items.push(child);
						if (firstOnly)
							break;
					}
					if (param.recursive !== false) {
						_getItems(child, options, childMatrix, param, firstOnly);
					}
					if (firstOnly && items.length > 0)
						break;
				}
				return items;
			}
		}
	}, {

		importJSON: function(json) {
			var res = Base.importJSON(json, this);
			return res !== this ? this.addChild(res) : res;
		},

		addChild: function(item, _preserve) {
			return this.insertChild(undefined, item, _preserve);
		},

		insertChild: function(index, item, _preserve) {
			var res = item ? this.insertChildren(index, [item], _preserve) : null;
			return res && res[0];
		},

		addChildren: function(items, _preserve) {
			return this.insertChildren(this._children.length, items, _preserve);
		},

		insertChildren: function(index, items, _preserve, _proto) {
			var children = this._children;
			if (children && items && items.length > 0) {
				items = Array.prototype.slice.apply(items);
				for (var i = items.length - 1; i >= 0; i--) {
					var item = items[i];
					if (!item || _proto && !(item instanceof _proto)) {
						items.splice(i, 1);
					} else {
						item._remove(false, true);
					}
				}
				Base.splice(children, items, index, 0);
				var project = this._project,
					notifySelf = project._changes;
				for (var i = 0, l = items.length; i < l; i++) {
					var item = items[i],
						name = item._name;
					item._parent = this;
					item._setProject(project, true);
					if (name)
						item.setName(name);
					if (notifySelf)
						this._changed(5);
				}
				this._changed(11);
			} else {
				items = null;
			}
			return items;
		},

		_insertItem: '#insertChild',

		_insertAt: function(item, offset, _preserve) {
			var res = this;
			if (res !== item) {
				var owner = item && item._getOwner();
				if (owner) {
					res._remove(false, true);
					owner._insertItem(item._index + offset, res, _preserve);
				} else {
					res = null;
				}
			}
			return res;
		},

		insertAbove: function(item, _preserve) {
			return this._insertAt(item, 1, _preserve);
		},

		insertBelow: function(item, _preserve) {
			return this._insertAt(item, 0, _preserve);
		},

		sendToBack: function() {
			var owner = this._getOwner();
			return owner ? owner._insertItem(0, this) : null;
		},

		bringToFront: function() {
			var owner = this._getOwner();
			return owner ? owner._insertItem(undefined, this) : null;
		},

		appendTop: '#addChild',

		appendBottom: function(item) {
			return this.insertChild(0, item);
		},

		moveAbove: '#insertAbove',

		moveBelow: '#insertBelow',

		copyTo: function(owner) {
			return owner._insertItem(undefined, this.clone(false));
		},

		reduce: function(options) {
			var children = this._children;
			if (children && children.length === 1) {
				var child = children[0].reduce(options);
				if (this._parent) {
					child.insertAbove(this);
					this.remove();
				} else {
					child.remove();
				}
				return child;
			}
			return this;
		},

		_removeNamed: function() {
			var owner = this._getOwner();
			if (owner) {
				var children = owner._children,
					namedChildren = owner._namedChildren,
					name = this._name,
					namedArray = namedChildren[name],
					index = namedArray ? namedArray.indexOf(this) : -1;
				if (index !== -1) {
					if (children[name] == this)
						delete children[name];
					namedArray.splice(index, 1);
					if (namedArray.length) {
						children[name] = namedArray[0];
					} else {
						delete namedChildren[name];
					}
				}
			}
		},

		_remove: function(notifySelf, notifyParent) {
			var owner = this._getOwner(),
				project = this._project,
				index = this._index;
			if (owner) {
				if (index != null) {
					if (project._activeLayer === this)
						project._activeLayer = this.getNextSibling()
								|| this.getPreviousSibling();
					Base.splice(owner._children, null, index, 1);
				}
				if (this._name)
					this._removeNamed();
				this._installEvents(false);
				if (notifySelf && project._changes)
					this._changed(5);
				if (notifyParent)
					owner._changed(11, this);
				this._parent = null;
				return true;
			}
			return false;
		},

		remove: function() {
			return this._remove(true, true);
		},

		replaceWith: function(item) {
			var ok = item && item.insertBelow(this);
			if (ok)
				this.remove();
			return ok;
		},

		removeChildren: function(start, end) {
			if (!this._children)
				return null;
			start = start || 0;
			end = Base.pick(end, this._children.length);
			var removed = Base.splice(this._children, null, start, end - start);
			for (var i = removed.length - 1; i >= 0; i--) {
				removed[i]._remove(true, false);
			}
			if (removed.length > 0)
				this._changed(11);
			return removed;
		},

		clear: '#removeChildren',

		reverseChildren: function() {
			if (this._children) {
				this._children.reverse();
				for (var i = 0, l = this._children.length; i < l; i++)
					this._children[i]._index = i;
				this._changed(11);
			}
		},

		isEmpty: function() {
			return !this._children || this._children.length === 0;
		},

		isEditable: function() {
			var item = this;
			while (item) {
				if (!item._visible || item._locked)
					return false;
				item = item._parent;
			}
			return true;
		},

		hasFill: function() {
			return this.getStyle().hasFill();
		},

		hasStroke: function() {
			return this.getStyle().hasStroke();
		},

		hasShadow: function() {
			return this.getStyle().hasShadow();
		},

		_getOrder: function(item) {
			function getList(item) {
				var list = [];
				do {
					list.unshift(item);
				} while (item = item._parent);
				return list;
			}
			var list1 = getList(this),
				list2 = getList(item);
			for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {
				if (list1[i] != list2[i]) {
					return list1[i]._index < list2[i]._index ? 1 : -1;
				}
			}
			return 0;
		},

		hasChildren: function() {
			return this._children && this._children.length > 0;
		},

		isInserted: function() {
			return this._parent ? this._parent.isInserted() : false;
		},

		isAbove: function(item) {
			return this._getOrder(item) === -1;
		},

		isBelow: function(item) {
			return this._getOrder(item) === 1;
		},

		isParent: function(item) {
			return this._parent === item;
		},

		isChild: function(item) {
			return item && item._parent === this;
		},

		isDescendant: function(item) {
			var parent = this;
			while (parent = parent._parent) {
				if (parent === item)
					return true;
			}
			return false;
		},

		isAncestor: function(item) {
			return item ? item.isDescendant(this) : false;
		},

		isSibling: function(item) {
			return this._parent === item._parent;
		},

		isGroupedWith: function(item) {
			var parent = this._parent;
			while (parent) {
				if (parent._parent
					&& /^(Group|Layer|CompoundPath)$/.test(parent._class)
					&& item.isDescendant(parent))
						return true;
				parent = parent._parent;
			}
			return false;
		},

	}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
		var rotate = key === 'rotate';
		this[key] = function() {
			var value = (rotate ? Base : Point).read(arguments),
				center = Point.read(arguments, 0, { readNull: true });
			return this.transform(new Matrix()[key](value,
					center || this.getPosition(true)));
		};
	}, {
		translate: function() {
			var mx = new Matrix();
			return this.transform(mx.translate.apply(mx, arguments));
		},

		transform: function(matrix, _applyMatrix, _applyRecursively,
				_setApplyMatrix) {
			if (matrix && matrix.isIdentity())
				matrix = null;
			var _matrix = this._matrix,
				applyMatrix = (_applyMatrix || this._applyMatrix)
						&& ((!_matrix.isIdentity() || matrix)
							|| _applyMatrix && _applyRecursively && this._children);
			if (!matrix && !applyMatrix)
				return this;
			if (matrix) {
				if (!matrix.isInvertible() && _matrix.isInvertible())
					_matrix._backup = _matrix.getValues();
				_matrix.prepend(matrix);
			}
			if (applyMatrix = applyMatrix && this._transformContent(_matrix,
						_applyRecursively, _setApplyMatrix)) {
				var pivot = this._pivot,
					style = this._style,
					fillColor = style.getFillColor(true),
					strokeColor = style.getStrokeColor(true);
				if (pivot)
					_matrix._transformPoint(pivot, pivot, true);
				if (fillColor)
					fillColor.transform(_matrix);
				if (strokeColor)
					strokeColor.transform(_matrix);
				_matrix.reset(true);
				if (_setApplyMatrix && this._canApplyMatrix)
					this._applyMatrix = true;
			}
			var bounds = this._bounds,
				position = this._position;
			this._changed(9);
			var decomp = bounds && matrix && matrix.decompose();
			if (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {
				for (var key in bounds) {
					var cache = bounds[key];
					if (applyMatrix || !cache.internal) {
						var rect = cache.rect;
						matrix._transformBounds(rect, rect);
					}
				}
				var getter = this._boundsGetter,
					rect = bounds[getter && getter.getBounds || getter || 'getBounds'];
				if (rect)
					this._position = rect.getCenter(true);
				this._bounds = bounds;
			} else if (matrix && position) {
				this._position = matrix._transformPoint(position, position);
			}
			return this;
		},

		_transformContent: function(matrix, applyRecursively, setApplyMatrix) {
			var children = this._children;
			if (children) {
				for (var i = 0, l = children.length; i < l; i++)
					children[i].transform(matrix, true, applyRecursively,
							setApplyMatrix);
				return true;
			}
		},

		globalToLocal: function() {
			return this.getGlobalMatrix(true)._inverseTransform(
					Point.read(arguments));
		},

		localToGlobal: function() {
			return this.getGlobalMatrix(true)._transformPoint(
					Point.read(arguments));
		},

		parentToLocal: function() {
			return this._matrix._inverseTransform(Point.read(arguments));
		},

		localToParent: function() {
			return this._matrix._transformPoint(Point.read(arguments));
		},

		fitBounds: function(rectangle, fill) {
			rectangle = Rectangle.read(arguments);
			var bounds = this.getBounds(),
				itemRatio = bounds.height / bounds.width,
				rectRatio = rectangle.height / rectangle.width,
				scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
						? rectangle.width / bounds.width
						: rectangle.height / bounds.height,
				newBounds = new Rectangle(new Point(),
						new Size(bounds.width * scale, bounds.height * scale));
			newBounds.setCenter(rectangle.getCenter());
			this.setBounds(newBounds);
		}
	}), {

		_setStyles: function(ctx, param, viewMatrix) {
			var style = this._style;
			if (style.hasFill()) {
				ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx);
			}
			if (style.hasStroke()) {
				ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx);
				ctx.lineWidth = style.getStrokeWidth();
				var strokeJoin = style.getStrokeJoin(),
					strokeCap = style.getStrokeCap(),
					miterLimit = style.getMiterLimit();
				if (strokeJoin)
					ctx.lineJoin = strokeJoin;
				if (strokeCap)
					ctx.lineCap = strokeCap;
				if (miterLimit)
					ctx.miterLimit = miterLimit;
				if (paper.support.nativeDash) {
					var dashArray = style.getDashArray(),
						dashOffset = style.getDashOffset();
					if (dashArray && dashArray.length) {
						if ('setLineDash' in ctx) {
							ctx.setLineDash(dashArray);
							ctx.lineDashOffset = dashOffset;
						} else {
							ctx.mozDash = dashArray;
							ctx.mozDashOffset = dashOffset;
						}
					}
				}
			}
			if (style.hasShadow()) {
				var pixelRatio = param.pixelRatio || 1,
					mx = viewMatrix._shiftless().prepend(
						new Matrix().scale(pixelRatio, pixelRatio)),
					blur = mx.transform(new Point(style.getShadowBlur(), 0)),
					offset = mx.transform(this.getShadowOffset());
				ctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);
				ctx.shadowBlur = blur.getLength();
				ctx.shadowOffsetX = offset.x;
				ctx.shadowOffsetY = offset.y;
			}
		},

		draw: function(ctx, param, parentStrokeMatrix) {
			var updateVersion = this._updateVersion = this._project._updateVersion;
			if (!this._visible || this._opacity === 0)
				return;
			var matrices = param.matrices,
				viewMatrix = param.viewMatrix,
				matrix = this._matrix,
				globalMatrix = matrices[matrices.length - 1].appended(matrix);
			if (!globalMatrix.isInvertible())
				return;

			viewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)
					: globalMatrix;

			matrices.push(globalMatrix);
			if (param.updateMatrix) {
				globalMatrix._updateVersion = updateVersion;
				this._globalMatrix = globalMatrix;
			}

			var blendMode = this._blendMode,
				opacity = this._opacity,
				normalBlend = blendMode === 'normal',
				nativeBlend = BlendMode.nativeModes[blendMode],
				direct = normalBlend && opacity === 1
						|| param.dontStart
						|| param.clip
						|| (nativeBlend || normalBlend && opacity < 1)
							&& this._canComposite(),
				pixelRatio = param.pixelRatio || 1,
				mainCtx, itemOffset, prevOffset;
			if (!direct) {
				var bounds = this.getStrokeBounds(viewMatrix);
				if (!bounds.width || !bounds.height)
					return;
				prevOffset = param.offset;
				itemOffset = param.offset = bounds.getTopLeft().floor();
				mainCtx = ctx;
				ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)
						.multiply(pixelRatio));
				if (pixelRatio !== 1)
					ctx.scale(pixelRatio, pixelRatio);
			}
			ctx.save();
			var strokeMatrix = parentStrokeMatrix
					? parentStrokeMatrix.appended(matrix)
					: this._canScaleStroke && !this.getStrokeScaling(true)
						&& viewMatrix,
				clip = !direct && param.clipItem,
				transform = !strokeMatrix || clip;
			if (direct) {
				ctx.globalAlpha = opacity;
				if (nativeBlend)
					ctx.globalCompositeOperation = blendMode;
			} else if (transform) {
				ctx.translate(-itemOffset.x, -itemOffset.y);
			}
			if (transform) {
				(direct ? matrix : viewMatrix).applyToContext(ctx);
			}
			if (clip) {
				param.clipItem.draw(ctx, param.extend({ clip: true }));
			}
			if (strokeMatrix) {
				ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
				var offset = param.offset;
				if (offset)
					ctx.translate(-offset.x, -offset.y);
			}
			this._draw(ctx, param, viewMatrix, strokeMatrix);
			ctx.restore();
			matrices.pop();
			if (param.clip && !param.dontFinish)
				ctx.clip();
			if (!direct) {
				BlendMode.process(blendMode, ctx, mainCtx, opacity,
						itemOffset.subtract(prevOffset).multiply(pixelRatio));
				CanvasProvider.release(ctx);
				param.offset = prevOffset;
			}
		},

		_isUpdated: function(updateVersion) {
			var parent = this._parent;
			if (parent instanceof CompoundPath)
				return parent._isUpdated(updateVersion);
			var updated = this._updateVersion === updateVersion;
			if (!updated && parent && parent._visible
					&& parent._isUpdated(updateVersion)) {
				this._updateVersion = updateVersion;
				updated = true;
			}
			return updated;
		},

		_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {
			var selection = this._selection,
				itemSelected = selection & 1,
				boundsSelected = selection & 2
						|| itemSelected && this._selectBounds,
				positionSelected = selection & 4;
			if (!this._drawSelected)
				itemSelected = false;
			if ((itemSelected || boundsSelected || positionSelected)
					&& this._isUpdated(updateVersion)) {
				var layer,
					color = this.getSelectedColor(true) || (layer = this.getLayer())
						&& layer.getSelectedColor(true),
					mx = matrix.appended(this.getGlobalMatrix(true)),
					half = size / 2;
				ctx.strokeStyle = ctx.fillStyle = color
						? color.toCanvasStyle(ctx) : '#009dec';
				if (itemSelected)
					this._drawSelected(ctx, mx, selectionItems);
				if (positionSelected) {
					var point = this.getPosition(true),
						x = point.x,
						y = point.y;
					ctx.beginPath();
					ctx.arc(x, y, half, 0, Math.PI * 2, true);
					ctx.stroke();
					var deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],
						start = half,
						end = size + 1;
					for (var i = 0; i < 4; i++) {
						var delta = deltas[i],
							dx = delta[0],
							dy = delta[1];
						ctx.moveTo(x + dx * start, y + dy * start);
						ctx.lineTo(x + dx * end, y + dy * end);
						ctx.stroke();
					}
				}
				if (boundsSelected) {
					var coords = mx._transformCorners(this.getInternalBounds());
					ctx.beginPath();
					for (var i = 0; i < 8; i++) {
						ctx[i === 0 ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);
					}
					ctx.closePath();
					ctx.stroke();
					for (var i = 0; i < 8; i++) {
						ctx.fillRect(coords[i] - half, coords[++i] - half,
								size, size);
					}
				}
			}
		},

		_canComposite: function() {
			return false;
		}
	}, Base.each(['down', 'drag', 'up', 'move'], function(key) {
		this['removeOn' + Base.capitalize(key)] = function() {
			var hash = {};
			hash[key] = true;
			return this.removeOn(hash);
		};
	}, {

		removeOn: function(obj) {
			for (var name in obj) {
				if (obj[name]) {
					var key = 'mouse' + name,
						project = this._project,
						sets = project._removeSets = project._removeSets || {};
					sets[key] = sets[key] || {};
					sets[key][this._id] = this;
				}
			}
			return this;
		}
	}));

	var Group = Item.extend({
		_class: 'Group',
		_selectBounds: false,
		_selectChildren: true,
		_serializeFields: {
			children: []
		},

		initialize: function Group(arg) {
			this._children = [];
			this._namedChildren = {};
			if (!this._initialize(arg))
				this.addChildren(Array.isArray(arg) ? arg : arguments);
		},

		_changed: function _changed(flags) {
			_changed.base.call(this, flags);
			if (flags & 1026) {
				this._clipItem = undefined;
			}
		},

		_getClipItem: function() {
			var clipItem = this._clipItem;
			if (clipItem === undefined) {
				clipItem = null;
				var children = this._children;
				for (var i = 0, l = children.length; i < l; i++) {
					if (children[i]._clipMask) {
						clipItem = children[i];
						break;
					}
				}
				this._clipItem = clipItem;
			}
			return clipItem;
		},

		isClipped: function() {
			return !!this._getClipItem();
		},

		setClipped: function(clipped) {
			var child = this.getFirstChild();
			if (child)
				child.setClipMask(clipped);
		},

		_getBounds: function _getBounds(matrix, options) {
			var clipItem = this._getClipItem();
			return clipItem
				? clipItem._getCachedBounds(
					matrix && matrix.appended(clipItem._matrix),
					Base.set({}, options, { stroke: false }))
				: _getBounds.base.call(this, matrix, options);
		},

		_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
			var clipItem = this._getClipItem();
			return (!clipItem || clipItem.contains(point))
					&& _hitTestChildren.base.call(this, point, options, viewMatrix,
						clipItem);
		},

		_draw: function(ctx, param) {
			var clip = param.clip,
				clipItem = !clip && this._getClipItem();
			param = param.extend({ clipItem: clipItem, clip: false });
			if (clip) {
				ctx.beginPath();
				param.dontStart = param.dontFinish = true;
			} else if (clipItem) {
				clipItem.draw(ctx, param.extend({ clip: true }));
			}
			var children = this._children;
			for (var i = 0, l = children.length; i < l; i++) {
				var item = children[i];
				if (item !== clipItem)
					item.draw(ctx, param);
			}
		}
	});

	var Layer = Group.extend({
		_class: 'Layer',

		initialize: function Layer() {
			Group.apply(this, arguments);
		},

		_getOwner: function() {
			return this._parent || this._index != null && this._project;
		},

		isInserted: function isInserted() {
			return this._parent ? isInserted.base.call(this) : this._index != null;
		},

		activate: function() {
			this._project._activeLayer = this;
		},

		_hitTestSelf: function() {
		}
	});

	var Shape = Item.extend({
		_class: 'Shape',
		_applyMatrix: false,
		_canApplyMatrix: false,
		_canScaleStroke: true,
		_serializeFields: {
			type: null,
			size: null,
			radius: null
		},

		initialize: function Shape(props) {
			this._initialize(props);
		},

		_equals: function(item) {
			return this._type === item._type
				&& this._size.equals(item._size)
				&& Base.equals(this._radius, item._radius);
		},

		copyContent: function(source) {
			this.setType(source._type);
			this.setSize(source._size);
			this.setRadius(source._radius);
		},

		getType: function() {
			return this._type;
		},

		setType: function(type) {
			this._type = type;
		},

		getShape: '#getType',
		setShape: '#setType',

		getSize: function() {
			var size = this._size;
			return new LinkedSize(size.width, size.height, this, 'setSize');
		},

		setSize: function() {
			var size = Size.read(arguments);
			if (!this._size) {
				this._size = size.clone();
			} else if (!this._size.equals(size)) {
				var type = this._type,
					width = size.width,
					height = size.height;
				if (type === 'rectangle') {
					var radius = Size.min(this._radius, size.divide(2));
					this._radius.set(radius.width, radius.height);
				} else if (type === 'circle') {
					width = height = (width + height) / 2;
					this._radius = width / 2;
				} else if (type === 'ellipse') {
					this._radius.set(width / 2, height / 2);
				}
				this._size.set(width, height);
				this._changed(9);
			}
		},

		getRadius: function() {
			var rad = this._radius;
			return this._type === 'circle'
					? rad
					: new LinkedSize(rad.width, rad.height, this, 'setRadius');
		},

		setRadius: function(radius) {
			var type = this._type;
			if (type === 'circle') {
				if (radius === this._radius)
					return;
				var size = radius * 2;
				this._radius = radius;
				this._size.set(size, size);
			} else {
				radius = Size.read(arguments);
				if (!this._radius) {
					this._radius = radius.clone();
				} else {
					if (this._radius.equals(radius))
						return;
					this._radius.set(radius.width, radius.height);
					if (type === 'rectangle') {
						var size = Size.max(this._size, radius.multiply(2));
						this._size.set(size.width, size.height);
					} else if (type === 'ellipse') {
						this._size.set(radius.width * 2, radius.height * 2);
					}
				}
			}
			this._changed(9);
		},

		isEmpty: function() {
			return false;
		},

		toPath: function(insert) {
			var path = new Path[Base.capitalize(this._type)]({
				center: new Point(),
				size: this._size,
				radius: this._radius,
				insert: false
			});
			path.copyAttributes(this);
			if (paper.settings.applyMatrix)
				path.setApplyMatrix(true);
			if (insert === undefined || insert)
				path.insertAbove(this);
			return path;
		},

		toShape: '#clone',

		_draw: function(ctx, param, viewMatrix, strokeMatrix) {
			var style = this._style,
				hasFill = style.hasFill(),
				hasStroke = style.hasStroke(),
				dontPaint = param.dontFinish || param.clip,
				untransformed = !strokeMatrix;
			if (hasFill || hasStroke || dontPaint) {
				var type = this._type,
					radius = this._radius,
					isCircle = type === 'circle';
				if (!param.dontStart)
					ctx.beginPath();
				if (untransformed && isCircle) {
					ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
				} else {
					var rx = isCircle ? radius : radius.width,
						ry = isCircle ? radius : radius.height,
						size = this._size,
						width = size.width,
						height = size.height;
					if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {
						ctx.rect(-width / 2, -height / 2, width, height);
					} else {
						var x = width / 2,
							y = height / 2,
							kappa = 1 - 0.5522847498307936,
							cx = rx * kappa,
							cy = ry * kappa,
							c = [
								-x, -y + ry,
								-x, -y + cy,
								-x + cx, -y,
								-x + rx, -y,
								x - rx, -y,
								x - cx, -y,
								x, -y + cy,
								x, -y + ry,
								x, y - ry,
								x, y - cy,
								x - cx, y,
								x - rx, y,
								-x + rx, y,
								-x + cx, y,
								-x, y - cy,
								-x, y - ry
							];
						if (strokeMatrix)
							strokeMatrix.transform(c, c, 32);
						ctx.moveTo(c[0], c[1]);
						ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);
						if (x !== rx)
							ctx.lineTo(c[8], c[9]);
						ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);
						if (y !== ry)
							ctx.lineTo(c[16], c[17]);
						ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);
						if (x !== rx)
							ctx.lineTo(c[24], c[25]);
						ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);
					}
				}
				ctx.closePath();
			}
			if (!dontPaint && (hasFill || hasStroke)) {
				this._setStyles(ctx, param, viewMatrix);
				if (hasFill) {
					ctx.fill(style.getFillRule());
					ctx.shadowColor = 'rgba(0,0,0,0)';
				}
				if (hasStroke)
					ctx.stroke();
			}
		},

		_canComposite: function() {
			return !(this.hasFill() && this.hasStroke());
		},

		_getBounds: function(matrix, options) {
			var rect = new Rectangle(this._size).setCenter(0, 0),
				style = this._style,
				strokeWidth = options.stroke && style.hasStroke()
						&& style.getStrokeWidth();
			if (matrix)
				rect = matrix._transformBounds(rect);
			return strokeWidth
					? rect.expand(Path._getStrokePadding(strokeWidth,
						this._getStrokeMatrix(matrix, options)))
					: rect;
		}
	},
	new function() {
		function getCornerCenter(that, point, expand) {
			var radius = that._radius;
			if (!radius.isZero()) {
				var halfSize = that._size.divide(2);
				for (var i = 0; i < 4; i++) {
					var dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),
						corner = dir.multiply(halfSize),
						center = corner.subtract(dir.multiply(radius)),
						rect = new Rectangle(corner, center);
					if ((expand ? rect.expand(expand) : rect).contains(point))
						return center;
				}
			}
		}

		function isOnEllipseStroke(point, radius, padding, quadrant) {
			var vector = point.divide(radius);
			return (!quadrant || vector.quadrant === quadrant) &&
					vector.subtract(vector.normalize()).multiply(radius)
						.divide(padding).length <= 1;
		}

		return {
			_contains: function _contains(point) {
				if (this._type === 'rectangle') {
					var center = getCornerCenter(this, point);
					return center
							? point.subtract(center).divide(this._radius)
								.getLength() <= 1
							: _contains.base.call(this, point);
				} else {
					return point.divide(this.size).getLength() <= 0.5;
				}
			},

			_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,
					strokeMatrix) {
				var hit = false,
					style = this._style,
					hitStroke = options.stroke && style.hasStroke(),
					hitFill = options.fill && style.hasFill();
				if (hitStroke || hitFill) {
					var type = this._type,
						radius = this._radius,
						strokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,
						strokePadding = options._tolerancePadding.add(
							Path._getStrokePadding(strokeRadius,
								!style.getStrokeScaling() && strokeMatrix));
					if (type === 'rectangle') {
						var padding = strokePadding.multiply(2),
							center = getCornerCenter(this, point, padding);
						if (center) {
							hit = isOnEllipseStroke(point.subtract(center), radius,
									strokePadding, center.getQuadrant());
						} else {
							var rect = new Rectangle(this._size).setCenter(0, 0),
								outer = rect.expand(padding),
								inner = rect.expand(padding.negate());
							hit = outer._containsPoint(point)
									&& !inner._containsPoint(point);
						}
					} else {
						hit = isOnEllipseStroke(point, radius, strokePadding);
					}
				}
				return hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)
						: _hitTestSelf.base.apply(this, arguments);
			}
		};
	}, {

	statics: new function() {
		function createShape(type, point, size, radius, args) {
			var item = new Shape(Base.getNamed(args));
			item._type = type;
			item._size = size;
			item._radius = radius;
			return item.translate(point);
		}

		return {
			Circle: function() {
				var center = Point.readNamed(arguments, 'center'),
					radius = Base.readNamed(arguments, 'radius');
				return createShape('circle', center, new Size(radius * 2), radius,
						arguments);
			},

			Rectangle: function() {
				var rect = Rectangle.readNamed(arguments, 'rectangle'),
					radius = Size.min(Size.readNamed(arguments, 'radius'),
							rect.getSize(true).divide(2));
				return createShape('rectangle', rect.getCenter(true),
						rect.getSize(true), radius, arguments);
			},

			Ellipse: function() {
				var ellipse = Shape._readEllipse(arguments),
					radius = ellipse.radius;
				return createShape('ellipse', ellipse.center, radius.multiply(2),
						radius, arguments);
			},

			_readEllipse: function(args) {
				var center,
					radius;
				if (Base.hasNamed(args, 'radius')) {
					center = Point.readNamed(args, 'center');
					radius = Size.readNamed(args, 'radius');
				} else {
					var rect = Rectangle.readNamed(args, 'rectangle');
					center = rect.getCenter(true);
					radius = rect.getSize(true).divide(2);
				}
				return { center: center, radius: radius };
			}
		};
	}});

	var Raster = Item.extend({
		_class: 'Raster',
		_applyMatrix: false,
		_canApplyMatrix: false,
		_boundsOptions: { stroke: false, handle: false },
		_serializeFields: {
			crossOrigin: null,
			source: null
		},

		initialize: function Raster(object, position) {
			if (!this._initialize(object,
					position !== undefined && Point.read(arguments, 1))) {
				var image = typeof object === 'string'
						? document.getElementById(object) : object;
				if (image) {
					this.setImage(image);
				} else {
					this.setSource(object);
				}
			}
			if (!this._size) {
				this._size = new Size();
				this._loaded = false;
			}
		},

		_equals: function(item) {
			return this.getSource() === item.getSource();
		},

		copyContent: function(source) {
			var image = source._image,
				canvas = source._canvas;
			if (image) {
				this._setImage(image);
			} else if (canvas) {
				var copyCanvas = CanvasProvider.getCanvas(source._size);
				copyCanvas.getContext('2d').drawImage(canvas, 0, 0);
				this._setImage(copyCanvas);
			}
			this._crossOrigin = source._crossOrigin;
		},

		getSize: function() {
			var size = this._size;
			return new LinkedSize(size ? size.width : 0, size ? size.height : 0,
					this, 'setSize');
		},

		setSize: function() {
			var size = Size.read(arguments);
			if (!size.equals(this._size)) {
				if (size.width > 0 && size.height > 0) {
					var element = this.getElement();
					this._setImage(CanvasProvider.getCanvas(size));
					if (element)
						this.getContext(true).drawImage(element, 0, 0,
								size.width, size.height);
				} else {
					if (this._canvas)
						CanvasProvider.release(this._canvas);
					this._size = size.clone();
				}
			}
		},

		getWidth: function() {
			return this._size ? this._size.width : 0;
		},

		setWidth: function(width) {
			this.setSize(width, this.getHeight());
		},

		getHeight: function() {
			return this._size ? this._size.height : 0;
		},

		setHeight: function(height) {
			this.setSize(this.getWidth(), height);
		},

		getLoaded: function() {
			return this._loaded;
		},

		isEmpty: function() {
			var size = this._size;
			return !size || size.width === 0 && size.height === 0;
		},

		getResolution: function() {
			var matrix = this._matrix,
				orig = new Point(0, 0).transform(matrix),
				u = new Point(1, 0).transform(matrix).subtract(orig),
				v = new Point(0, 1).transform(matrix).subtract(orig);
			return new Size(
				72 / u.getLength(),
				72 / v.getLength()
			);
		},

		getPpi: '#getResolution',

		getImage: function() {
			return this._image;
		},

		setImage: function(image) {
			var that = this;

			function emit(event) {
				var view = that.getView(),
					type = event && event.type || 'load';
				if (view && that.responds(type)) {
					paper = view._scope;
					that.emit(type, new Event(event));
				}
			}

			this._setImage(image);
			if (this._loaded) {
				setTimeout(emit, 0);
			} else if (image) {
				DomEvent.add(image, {
					load: function(event) {
						that._setImage(image);
						emit(event);
					},
					error: emit
				});
			}
		},

		_setImage: function(image) {
			if (this._canvas)
				CanvasProvider.release(this._canvas);
			if (image && image.getContext) {
				this._image = null;
				this._canvas = image;
				this._loaded = true;
			} else {
				this._image = image;
				this._canvas = null;
				this._loaded = !!(image && image.src && image.complete);
			}
			this._size = new Size(
					image ? image.naturalWidth || image.width : 0,
					image ? image.naturalHeight || image.height : 0);
			this._context = null;
			this._changed(521);
		},

		getCanvas: function() {
			if (!this._canvas) {
				var ctx = CanvasProvider.getContext(this._size);
				try {
					if (this._image)
						ctx.drawImage(this._image, 0, 0);
					this._canvas = ctx.canvas;
				} catch (e) {
					CanvasProvider.release(ctx);
				}
			}
			return this._canvas;
		},

		setCanvas: '#setImage',

		getContext: function(modify) {
			if (!this._context)
				this._context = this.getCanvas().getContext('2d');
			if (modify) {
				this._image = null;
				this._changed(513);
			}
			return this._context;
		},

		setContext: function(context) {
			this._context = context;
		},

		getSource: function() {
			var image = this._image;
			return image && image.src || this.toDataURL();
		},

		setSource: function(src) {
			var image = new window.Image(),
				crossOrigin = this._crossOrigin;
			if (crossOrigin)
				image.crossOrigin = crossOrigin;
			image.src = src;
			this.setImage(image);
		},

		getCrossOrigin: function() {
			var image = this._image;
			return image && image.crossOrigin || this._crossOrigin || '';
		},

		setCrossOrigin: function(crossOrigin) {
			this._crossOrigin = crossOrigin;
			var image = this._image;
			if (image)
				image.crossOrigin = crossOrigin;
		},

		getElement: function() {
			return this._canvas || this._loaded && this._image;
		}
	}, {
		beans: false,

		getSubCanvas: function() {
			var rect = Rectangle.read(arguments),
				ctx = CanvasProvider.getContext(rect.getSize());
			ctx.drawImage(this.getCanvas(), rect.x, rect.y,
					rect.width, rect.height, 0, 0, rect.width, rect.height);
			return ctx.canvas;
		},

		getSubRaster: function() {
			var rect = Rectangle.read(arguments),
				raster = new Raster(Item.NO_INSERT);
			raster._setImage(this.getSubCanvas(rect));
			raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
			raster._matrix.prepend(this._matrix);
			raster.insertAbove(this);
			return raster;
		},

		toDataURL: function() {
			var image = this._image,
				src = image && image.src;
			if (/^data:/.test(src))
				return src;
			var canvas = this.getCanvas();
			return canvas ? canvas.toDataURL.apply(canvas, arguments) : null;
		},

		drawImage: function(image ) {
			var point = Point.read(arguments, 1);
			this.getContext(true).drawImage(image, point.x, point.y);
		},

		getAverageColor: function(object) {
			var bounds, path;
			if (!object) {
				bounds = this.getBounds();
			} else if (object instanceof PathItem) {
				path = object;
				bounds = object.getBounds();
			} else if (typeof object === 'object') {
				if ('width' in object) {
					bounds = new Rectangle(object);
				} else if ('x' in object) {
					bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
				}
			}
			if (!bounds)
				return null;
			var sampleSize = 32,
				width = Math.min(bounds.width, sampleSize),
				height = Math.min(bounds.height, sampleSize);
			var ctx = Raster._sampleContext;
			if (!ctx) {
				ctx = Raster._sampleContext = CanvasProvider.getContext(
						new Size(sampleSize));
			} else {
				ctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);
			}
			ctx.save();
			var matrix = new Matrix()
					.scale(width / bounds.width, height / bounds.height)
					.translate(-bounds.x, -bounds.y);
			matrix.applyToContext(ctx);
			if (path)
				path.draw(ctx, new Base({ clip: true, matrices: [matrix] }));
			this._matrix.applyToContext(ctx);
			var element = this.getElement(),
				size = this._size;
			if (element)
				ctx.drawImage(element, -size.width / 2, -size.height / 2);
			ctx.restore();
			var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),
					Math.ceil(height)).data,
				channels = [0, 0, 0],
				total = 0;
			for (var i = 0, l = pixels.length; i < l; i += 4) {
				var alpha = pixels[i + 3];
				total += alpha;
				alpha /= 255;
				channels[0] += pixels[i] * alpha;
				channels[1] += pixels[i + 1] * alpha;
				channels[2] += pixels[i + 2] * alpha;
			}
			for (var i = 0; i < 3; i++)
				channels[i] /= total;
			return total ? Color.read(channels) : null;
		},

		getPixel: function() {
			var point = Point.read(arguments);
			var data = this.getContext().getImageData(point.x, point.y, 1, 1).data;
			return new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],
					data[3] / 255);
		},

		setPixel: function() {
			var point = Point.read(arguments),
				color = Color.read(arguments),
				components = color._convert('rgb'),
				alpha = color._alpha,
				ctx = this.getContext(true),
				imageData = ctx.createImageData(1, 1),
				data = imageData.data;
			data[0] = components[0] * 255;
			data[1] = components[1] * 255;
			data[2] = components[2] * 255;
			data[3] = alpha != null ? alpha * 255 : 255;
			ctx.putImageData(imageData, point.x, point.y);
		},

		createImageData: function() {
			var size = Size.read(arguments);
			return this.getContext().createImageData(size.width, size.height);
		},

		getImageData: function() {
			var rect = Rectangle.read(arguments);
			if (rect.isEmpty())
				rect = new Rectangle(this._size);
			return this.getContext().getImageData(rect.x, rect.y,
					rect.width, rect.height);
		},

		setImageData: function(data ) {
			var point = Point.read(arguments, 1);
			this.getContext(true).putImageData(data, point.x, point.y);
		},

		_getBounds: function(matrix, options) {
			var rect = new Rectangle(this._size).setCenter(0, 0);
			return matrix ? matrix._transformBounds(rect) : rect;
		},

		_hitTestSelf: function(point) {
			if (this._contains(point)) {
				var that = this;
				return new HitResult('pixel', that, {
					offset: point.add(that._size.divide(2)).round(),
					color: {
						get: function() {
							return that.getPixel(this.offset);
						}
					}
				});
			}
		},

		_draw: function(ctx) {
			var element = this.getElement();
			if (element) {
				ctx.globalAlpha = this._opacity;
				ctx.drawImage(element,
						-this._size.width / 2, -this._size.height / 2);
			}
		},

		_canComposite: function() {
			return true;
		}
	});

	var SymbolItem = Item.extend({
		_class: 'SymbolItem',
		_applyMatrix: false,
		_canApplyMatrix: false,
		_boundsOptions: { stroke: true },
		_serializeFields: {
			symbol: null
		},

		initialize: function SymbolItem(arg0, arg1) {
			if (!this._initialize(arg0,
					arg1 !== undefined && Point.read(arguments, 1)))
				this.setDefinition(arg0 instanceof SymbolDefinition ?
						arg0 : new SymbolDefinition(arg0));
		},

		_equals: function(item) {
			return this._definition === item._definition;
		},

		copyContent: function(source) {
			this.setDefinition(source._definition);
		},

		getDefinition: function() {
			return this._definition;
		},

		setDefinition: function(definition) {
			this._definition = definition;
			this._changed(9);
		},

		getSymbol: '#getDefinition',
		setSymbol: '#setDefinition',

		isEmpty: function() {
			return this._definition._item.isEmpty();
		},

		_getBounds: function(matrix, options) {
			var item = this._definition._item;
			return item._getCachedBounds(item._matrix.prepended(matrix), options);
		},

		_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
			var res = this._definition._item._hitTest(point, options, viewMatrix);
			if (res)
				res.item = this;
			return res;
		},

		_draw: function(ctx, param) {
			this._definition._item.draw(ctx, param);
		}

	});

	var SymbolDefinition = Base.extend({
		_class: 'SymbolDefinition',

		initialize: function SymbolDefinition(item, dontCenter) {
			this._id = UID.get();
			this.project = paper.project;
			if (item)
				this.setItem(item, dontCenter);
		},

		_serialize: function(options, dictionary) {
			return dictionary.add(this, function() {
				return Base.serialize([this._class, this._item],
						options, false, dictionary);
			});
		},

		_changed: function(flags) {
			if (flags & 8)
				Item._clearBoundsCache(this);
			if (flags & 1)
				this.project._changed(flags);
		},

		getItem: function() {
			return this._item;
		},

		setItem: function(item, _dontCenter) {
			if (item._symbol)
				item = item.clone();
			if (this._item)
				this._item._symbol = null;
			this._item = item;
			item.remove();
			item.setSelected(false);
			if (!_dontCenter)
				item.setPosition(new Point());
			item._symbol = this;
			this._changed(9);
		},

		getDefinition: '#getItem',
		setDefinition: '#setItem',

		place: function(position) {
			return new SymbolItem(this, position);
		},

		clone: function() {
			return new SymbolDefinition(this._item.clone(false));
		},

		equals: function(symbol) {
			return symbol === this
					|| symbol && this._item.equals(symbol._item)
					|| false;
		}
	});

	var HitResult = Base.extend({
		_class: 'HitResult',

		initialize: function HitResult(type, item, values) {
			this.type = type;
			this.item = item;
			if (values) {
				values.enumerable = true;
				this.inject(values);
			}
		},

		statics: {
			getOptions: function(args) {
				var options = args && Base.read(args);
				return Base.set({
					type: null,
					tolerance: paper.settings.hitTolerance,
					fill: !options,
					stroke: !options,
					segments: !options,
					handles: false,
					ends: false,
					center: false,
					bounds: false,
					guides: false,
					selected: false
				}, options);
			}
		}
	});

	var Segment = Base.extend({
		_class: 'Segment',
		beans: true,
		_selection: 0,

		initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
			var count = arguments.length,
				point, handleIn, handleOut,
				selection;
			if (count === 0) {
			} else if (count === 1) {
				if (arg0 && 'point' in arg0) {
					point = arg0.point;
					handleIn = arg0.handleIn;
					handleOut = arg0.handleOut;
					selection = arg0.selection;
				} else {
					point = arg0;
				}
			} else if (arg0 == null || typeof arg0 === 'object') {
				point = arg0;
				handleIn = arg1;
				handleOut = arg2;
				selection = arg3;
			} else {
				point = arg0 !== undefined ? [ arg0, arg1 ] : null;
				handleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;
				handleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;
			}
			new SegmentPoint(point, this, '_point');
			new SegmentPoint(handleIn, this, '_handleIn');
			new SegmentPoint(handleOut, this, '_handleOut');
			if (selection)
				this.setSelection(selection);
		},

		_serialize: function(options, dictionary) {
			var point = this._point,
				selection = this._selection,
				obj = selection || this.hasHandles()
						? [point, this._handleIn, this._handleOut]
						: point;
			if (selection)
				obj.push(selection);
			return Base.serialize(obj, options, true, dictionary);
		},

		_changed: function(point) {
			var path = this._path;
			if (!path)
				return;
			var curves = path._curves,
				index = this._index,
				curve;
			if (curves) {
				if ((!point || point === this._point || point === this._handleIn)
						&& (curve = index > 0 ? curves[index - 1] : path._closed
							? curves[curves.length - 1] : null))
					curve._changed();
				if ((!point || point === this._point || point === this._handleOut)
						&& (curve = curves[index]))
					curve._changed();
			}
			path._changed(25);
		},

		getPoint: function() {
			return this._point;
		},

		setPoint: function() {
			var point = Point.read(arguments);
			this._point.set(point.x, point.y);
		},

		getHandleIn: function() {
			return this._handleIn;
		},

		setHandleIn: function() {
			var point = Point.read(arguments);
			this._handleIn.set(point.x, point.y);
		},

		getHandleOut: function() {
			return this._handleOut;
		},

		setHandleOut: function() {
			var point = Point.read(arguments);
			this._handleOut.set(point.x, point.y);
		},

		hasHandles: function() {
			return !this._handleIn.isZero() || !this._handleOut.isZero();
		},

		clearHandles: function() {
			this._handleIn.set(0, 0);
			this._handleOut.set(0, 0);
		},

		getSelection: function() {
			return this._selection;
		},

		setSelection: function(selection) {
			var oldSelection = this._selection,
				path = this._path;
			this._selection = selection = selection || 0;
			if (path && selection !== oldSelection) {
				path._updateSelection(this, oldSelection, selection);
				path._changed(129);
			}
		},

		changeSelection: function(flag, selected) {
			var selection = this._selection;
			this.setSelection(selected ? selection | flag : selection & ~flag);
		},

		isSelected: function() {
			return !!(this._selection & 7);
		},

		setSelected: function(selected) {
			this.changeSelection(7, selected);
		},

		getIndex: function() {
			return this._index !== undefined ? this._index : null;
		},

		getPath: function() {
			return this._path || null;
		},

		getCurve: function() {
			var path = this._path,
				index = this._index;
			if (path) {
				if (index > 0 && !path._closed
						&& index === path._segments.length - 1)
					index--;
				return path.getCurves()[index] || null;
			}
			return null;
		},

		getLocation: function() {
			var curve = this.getCurve();
			return curve
					? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)
					: null;
		},

		getNext: function() {
			var segments = this._path && this._path._segments;
			return segments && (segments[this._index + 1]
					|| this._path._closed && segments[0]) || null;
		},

		smooth: function(options, _first, _last) {
			var opts = options || {},
				type = opts.type,
				factor = opts.factor,
				prev = this.getPrevious(),
				next = this.getNext(),
				p0 = (prev || this)._point,
				p1 = this._point,
				p2 = (next || this)._point,
				d1 = p0.getDistance(p1),
				d2 = p1.getDistance(p2);
			if (!type || type === 'catmull-rom') {
				var a = factor === undefined ? 0.5 : factor,
					d1_a = Math.pow(d1, a),
					d1_2a = d1_a * d1_a,
					d2_a = Math.pow(d2, a),
					d2_2a = d2_a * d2_a;
				if (!_first && prev) {
					var A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,
						N = 3 * d2_a * (d2_a + d1_a);
					this.setHandleIn(N !== 0
						? new Point(
							(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,
							(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)
						: new Point());
				}
				if (!_last && next) {
					var A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,
						N = 3 * d1_a * (d1_a + d2_a);
					this.setHandleOut(N !== 0
						? new Point(
							(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,
							(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)
						: new Point());
				}
			} else if (type === 'geometric') {
				if (prev && next) {
					var vector = p0.subtract(p2),
						t = factor === undefined ? 0.4 : factor,
						k = t * d1 / (d1 + d2);
					if (!_first)
						this.setHandleIn(vector.multiply(k));
					if (!_last)
						this.setHandleOut(vector.multiply(k - t));
				}
			} else {
				throw new Error('Smoothing method \'' + type + '\' not supported.');
			}
		},

		getPrevious: function() {
			var segments = this._path && this._path._segments;
			return segments && (segments[this._index - 1]
					|| this._path._closed && segments[segments.length - 1]) || null;
		},

		isFirst: function() {
			return this._index === 0;
		},

		isLast: function() {
			var path = this._path;
			return path && this._index === path._segments.length - 1 || false;
		},

		reverse: function() {
			var handleIn = this._handleIn,
				handleOut = this._handleOut,
				inX = handleIn._x,
				inY = handleIn._y;
			handleIn.set(handleOut._x, handleOut._y);
			handleOut.set(inX, inY);
		},

		reversed: function() {
			return new Segment(this._point, this._handleOut, this._handleIn);
		},

		remove: function() {
			return this._path ? !!this._path.removeSegment(this._index) : false;
		},

		clone: function() {
			return new Segment(this._point, this._handleIn, this._handleOut);
		},

		equals: function(segment) {
			return segment === this || segment && this._class === segment._class
					&& this._point.equals(segment._point)
					&& this._handleIn.equals(segment._handleIn)
					&& this._handleOut.equals(segment._handleOut)
					|| false;
		},

		toString: function() {
			var parts = [ 'point: ' + this._point ];
			if (!this._handleIn.isZero())
				parts.push('handleIn: ' + this._handleIn);
			if (!this._handleOut.isZero())
				parts.push('handleOut: ' + this._handleOut);
			return '{ ' + parts.join(', ') + ' }';
		},

		transform: function(matrix) {
			this._transformCoordinates(matrix, new Array(6), true);
			this._changed();
		},

		interpolate: function(from, to, factor) {
			var u = 1 - factor,
				v = factor,
				point1 = from._point,
				point2 = to._point,
				handleIn1 = from._handleIn,
				handleIn2 = to._handleIn,
				handleOut2 = to._handleOut,
				handleOut1 = from._handleOut;
			this._point.set(
					u * point1._x + v * point2._x,
					u * point1._y + v * point2._y, true);
			this._handleIn.set(
					u * handleIn1._x + v * handleIn2._x,
					u * handleIn1._y + v * handleIn2._y, true);
			this._handleOut.set(
					u * handleOut1._x + v * handleOut2._x,
					u * handleOut1._y + v * handleOut2._y, true);
			this._changed();
		},

		_transformCoordinates: function(matrix, coords, change) {
			var point = this._point,
				handleIn = !change || !this._handleIn.isZero()
						? this._handleIn : null,
				handleOut = !change || !this._handleOut.isZero()
						? this._handleOut : null,
				x = point._x,
				y = point._y,
				i = 2;
			coords[0] = x;
			coords[1] = y;
			if (handleIn) {
				coords[i++] = handleIn._x + x;
				coords[i++] = handleIn._y + y;
			}
			if (handleOut) {
				coords[i++] = handleOut._x + x;
				coords[i++] = handleOut._y + y;
			}
			if (matrix) {
				matrix._transformCoordinates(coords, coords, i / 2);
				x = coords[0];
				y = coords[1];
				if (change) {
					point._x = x;
					point._y = y;
					i = 2;
					if (handleIn) {
						handleIn._x = coords[i++] - x;
						handleIn._y = coords[i++] - y;
					}
					if (handleOut) {
						handleOut._x = coords[i++] - x;
						handleOut._y = coords[i++] - y;
					}
				} else {
					if (!handleIn) {
						coords[i++] = x;
						coords[i++] = y;
					}
					if (!handleOut) {
						coords[i++] = x;
						coords[i++] = y;
					}
				}
			}
			return coords;
		}
	});

	var SegmentPoint = Point.extend({
		initialize: function SegmentPoint(point, owner, key) {
			var x, y,
				selected;
			if (!point) {
				x = y = 0;
			} else if ((x = point[0]) !== undefined) {
				y = point[1];
			} else {
				var pt = point;
				if ((x = pt.x) === undefined) {
					pt = Point.read(arguments);
					x = pt.x;
				}
				y = pt.y;
				selected = pt.selected;
			}
			this._x = x;
			this._y = y;
			this._owner = owner;
			owner[key] = this;
			if (selected)
				this.setSelected(true);
		},

		set: function(x, y) {
			this._x = x;
			this._y = y;
			this._owner._changed(this);
			return this;
		},

		getX: function() {
			return this._x;
		},

		setX: function(x) {
			this._x = x;
			this._owner._changed(this);
		},

		getY: function() {
			return this._y;
		},

		setY: function(y) {
			this._y = y;
			this._owner._changed(this);
		},

		isZero: function() {
			return Numerical.isZero(this._x) && Numerical.isZero(this._y);
		},

		isSelected: function() {
			return !!(this._owner._selection & this._getSelection());
		},

		setSelected: function(selected) {
			this._owner.changeSelection(this._getSelection(), selected);
		},

		_getSelection: function() {
			var owner = this._owner;
			return this === owner._point ? 1
				: this === owner._handleIn ? 2
				: this === owner._handleOut ? 4
				: 0;
		}
	});

	var Curve = Base.extend({
		_class: 'Curve',

		initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
			var count = arguments.length,
				seg1, seg2,
				point1, point2,
				handle1, handle2;
			if (count === 3) {
				this._path = arg0;
				seg1 = arg1;
				seg2 = arg2;
			} else if (count === 0) {
				seg1 = new Segment();
				seg2 = new Segment();
			} else if (count === 1) {
				if ('segment1' in arg0) {
					seg1 = new Segment(arg0.segment1);
					seg2 = new Segment(arg0.segment2);
				} else if ('point1' in arg0) {
					point1 = arg0.point1;
					handle1 = arg0.handle1;
					handle2 = arg0.handle2;
					point2 = arg0.point2;
				} else if (Array.isArray(arg0)) {
					point1 = [arg0[0], arg0[1]];
					point2 = [arg0[6], arg0[7]];
					handle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];
					handle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];
				}
			} else if (count === 2) {
				seg1 = new Segment(arg0);
				seg2 = new Segment(arg1);
			} else if (count === 4) {
				point1 = arg0;
				handle1 = arg1;
				handle2 = arg2;
				point2 = arg3;
			} else if (count === 8) {
				point1 = [arg0, arg1];
				point2 = [arg6, arg7];
				handle1 = [arg2 - arg0, arg3 - arg1];
				handle2 = [arg4 - arg6, arg5 - arg7];
			}
			this._segment1 = seg1 || new Segment(point1, null, handle1);
			this._segment2 = seg2 || new Segment(point2, handle2, null);
		},

		_serialize: function(options, dictionary) {
			return Base.serialize(this.hasHandles()
					? [this.getPoint1(), this.getHandle1(), this.getHandle2(),
						this.getPoint2()]
					: [this.getPoint1(), this.getPoint2()],
					options, true, dictionary);
		},

		_changed: function() {
			this._length = this._bounds = undefined;
		},

		clone: function() {
			return new Curve(this._segment1, this._segment2);
		},

		toString: function() {
			var parts = [ 'point1: ' + this._segment1._point ];
			if (!this._segment1._handleOut.isZero())
				parts.push('handle1: ' + this._segment1._handleOut);
			if (!this._segment2._handleIn.isZero())
				parts.push('handle2: ' + this._segment2._handleIn);
			parts.push('point2: ' + this._segment2._point);
			return '{ ' + parts.join(', ') + ' }';
		},

		remove: function() {
			var removed = false;
			if (this._path) {
				var segment2 = this._segment2,
					handleOut = segment2._handleOut;
				removed = segment2.remove();
				if (removed)
					this._segment1._handleOut.set(handleOut.x, handleOut.y);
			}
			return removed;
		},

		getPoint1: function() {
			return this._segment1._point;
		},

		setPoint1: function() {
			var point = Point.read(arguments);
			this._segment1._point.set(point.x, point.y);
		},

		getPoint2: function() {
			return this._segment2._point;
		},

		setPoint2: function() {
			var point = Point.read(arguments);
			this._segment2._point.set(point.x, point.y);
		},

		getHandle1: function() {
			return this._segment1._handleOut;
		},

		setHandle1: function() {
			var point = Point.read(arguments);
			this._segment1._handleOut.set(point.x, point.y);
		},

		getHandle2: function() {
			return this._segment2._handleIn;
		},

		setHandle2: function() {
			var point = Point.read(arguments);
			this._segment2._handleIn.set(point.x, point.y);
		},

		getSegment1: function() {
			return this._segment1;
		},

		getSegment2: function() {
			return this._segment2;
		},

		getPath: function() {
			return this._path;
		},

		getIndex: function() {
			return this._segment1._index;
		},

		getNext: function() {
			var curves = this._path && this._path._curves;
			return curves && (curves[this._segment1._index + 1]
					|| this._path._closed && curves[0]) || null;
		},

		getPrevious: function() {
			var curves = this._path && this._path._curves;
			return curves && (curves[this._segment1._index - 1]
					|| this._path._closed && curves[curves.length - 1]) || null;
		},

		isFirst: function() {
			return this._segment1._index === 0;
		},

		isLast: function() {
			var path = this._path;
			return path && this._segment1._index === path._curves.length - 1
					|| false;
		},

		isSelected: function() {
			return this.getPoint1().isSelected()
					&& this.getHandle2().isSelected()
					&& this.getHandle2().isSelected()
					&& this.getPoint2().isSelected();
		},

		setSelected: function(selected) {
			this.getPoint1().setSelected(selected);
			this.getHandle1().setSelected(selected);
			this.getHandle2().setSelected(selected);
			this.getPoint2().setSelected(selected);
		},

		getValues: function(matrix) {
			return Curve.getValues(this._segment1, this._segment2, matrix);
		},

		getPoints: function() {
			var coords = this.getValues(),
				points = [];
			for (var i = 0; i < 8; i += 2)
				points.push(new Point(coords[i], coords[i + 1]));
			return points;
		},

		getLength: function() {
			if (this._length == null)
				this._length = Curve.getLength(this.getValues(), 0, 1);
			return this._length;
		},

		getArea: function() {
			return Curve.getArea(this.getValues());
		},

		getLine: function() {
			return new Line(this._segment1._point, this._segment2._point);
		},

		getPart: function(from, to) {
			return new Curve(Curve.getPart(this.getValues(), from, to));
		},

		getPartLength: function(from, to) {
			return Curve.getLength(this.getValues(), from, to);
		},

		getIntersections: function(curve) {
			return Curve._getIntersections(this.getValues(),
					curve && curve !== this ? curve.getValues() : null,
					this, curve, [], {});
		},

		divideAt: function(location) {
			return this.divideAtTime(location && location.curve === this
					? location.time : location);
		},

		divideAtTime: function(time, _setHandles) {
			var tMin = 4e-7,
				tMax = 1 - tMin,
				res = null;
			if (time >= tMin && time <= tMax) {
				var parts = Curve.subdivide(this.getValues(), time),
					left = parts[0],
					right = parts[1],
					setHandles = _setHandles || this.hasHandles(),
					segment1 = this._segment1,
					segment2 = this._segment2,
					path = this._path;
				if (setHandles) {
					segment1._handleOut.set(left[2] - left[0], left[3] - left[1]);
					segment2._handleIn.set(right[4] - right[6],right[5] - right[7]);
				}
				var x = left[6], y = left[7],
					segment = new Segment(new Point(x, y),
							setHandles && new Point(left[4] - x, left[5] - y),
							setHandles && new Point(right[2] - x, right[3] - y));
				if (path) {
					path.insert(segment1._index + 1, segment);
					res = this.getNext();
				} else {
					this._segment2 = segment;
					this._changed();
					res = new Curve(segment, segment2);
				}
			}
			return res;
		},

		splitAt: function(location) {
			return this._path ? this._path.splitAt(location) : null;
		},

		splitAtTime: function(t) {
			return this.splitAt(this.getLocationAtTime(t));
		},

		divide: function(offset, isTime) {
			return this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset
					: this.getTimeAt(offset));
		},

		split: function(offset, isTime) {
			return this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset
					: this.getTimeAt(offset));
		},

		reversed: function() {
			return new Curve(this._segment2.reversed(), this._segment1.reversed());
		},

		clearHandles: function() {
			this._segment1._handleOut.set(0, 0);
			this._segment2._handleIn.set(0, 0);
		},

	statics: {
		getValues: function(segment1, segment2, matrix) {
			var p1 = segment1._point,
				h1 = segment1._handleOut,
				h2 = segment2._handleIn,
				p2 = segment2._point,
				values = [
					p1._x, p1._y,
					p1._x + h1._x, p1._y + h1._y,
					p2._x + h2._x, p2._y + h2._y,
					p2._x, p2._y
				];
			if (matrix)
				matrix._transformCoordinates(values, values, 4);
			return values;
		},

		subdivide: function(v, t) {
			var p1x = v[0], p1y = v[1],
				c1x = v[2], c1y = v[3],
				c2x = v[4], c2y = v[5],
				p2x = v[6], p2y = v[7];
			if (t === undefined)
				t = 0.5;
			var u = 1 - t,
				p3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,
				p4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,
				p5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,
				p6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,
				p7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,
				p8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;
			return [
				[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],
				[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]
			];
		},

		solveCubic: function (v, coord, val, roots, min, max) {
			var p1 = v[coord],
				c1 = v[coord + 2],
				c2 = v[coord + 4],
				p2 = v[coord + 6],
				res = 0;
			if (  !(p1 < val && p2 < val && c1 < val && c2 < val ||
					p1 > val && p2 > val && c1 > val && c2 > val)) {
				var c = 3 * (c1 - p1),
					b = 3 * (c2 - c1) - c,
					a = p2 - p1 - c - b;
				res = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
			}
			return res;
		},

		getTimeOf: function(v, point) {
			var p1 = new Point(v[0], v[1]),
				p2 = new Point(v[6], v[7]),
				epsilon = 1e-12,
				t = point.isClose(p1, epsilon) ? 0
				  : point.isClose(p2, epsilon) ? 1
				  : null;
			if (t !== null)
				return t;
			var coords = [point.x, point.y],
				roots = [],
				geomEpsilon = 2e-7;
			for (var c = 0; c < 2; c++) {
				var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);
				for (var i = 0; i < count; i++) {
					t = roots[i];
					if (point.isClose(Curve.getPoint(v, t), geomEpsilon))
						return t;
				}
			}
			return point.isClose(p1, geomEpsilon) ? 0
				 : point.isClose(p2, geomEpsilon) ? 1
				 : null;
		},

		getNearestTime: function(v, point) {
			if (Curve.isStraight(v)) {
				var p1x = v[0], p1y = v[1],
					p2x = v[6], p2y = v[7],
					vx = p2x - p1x, vy = p2y - p1y,
					det = vx * vx + vy * vy;
				if (det === 0)
					return 0;
				var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
				return u < 1e-12 ? 0
					 : u > 0.999999999999 ? 1
					 : Curve.getTimeOf(v,
						new Point(p1x + u * vx, p1y + u * vy));
			}

			var count = 100,
				minDist = Infinity,
				minT = 0;

			function refine(t) {
				if (t >= 0 && t <= 1) {
					var dist = point.getDistance(Curve.getPoint(v, t), true);
					if (dist < minDist) {
						minDist = dist;
						minT = t;
						return true;
					}
				}
			}

			for (var i = 0; i <= count; i++)
				refine(i / count);

			var step = 1 / (count * 2);
			while (step > 4e-7) {
				if (!refine(minT - step) && !refine(minT + step))
					step /= 2;
			}
			return minT;
		},

		getPart: function(v, from, to) {
			var flip = from > to;
			if (flip) {
				var tmp = from;
				from = to;
				to = tmp;
			}
			if (from > 0)
				v = Curve.subdivide(v, from)[1];
			if (to < 1)
				v = Curve.subdivide(v, (to - from) / (1 - from))[0];
			return flip
					? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]
					: v;
		},

		isFlatEnough: function(v, flatness) {
			var p1x = v[0], p1y = v[1],
				c1x = v[2], c1y = v[3],
				c2x = v[4], c2y = v[5],
				p2x = v[6], p2y = v[7],
				ux = 3 * c1x - 2 * p1x - p2x,
				uy = 3 * c1y - 2 * p1y - p2y,
				vx = 3 * c2x - 2 * p2x - p1x,
				vy = 3 * c2y - 2 * p2y - p1y;
			return Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)
					<= 16 * flatness * flatness;
		},

		getArea: function(v) {
			var p1x = v[0], p1y = v[1],
				c1x = v[2], c1y = v[3],
				c2x = v[4], c2y = v[5],
				p2x = v[6], p2y = v[7];
			return 3 * ((p2y - p1y) * (c1x + c2x) - (p2x - p1x) * (c1y + c2y)
					+ c1y * (p1x - c2x) - c1x * (p1y - c2y)
					+ p2y * (c2x + p1x / 3) - p2x * (c2y + p1y / 3)) / 20;
		},

		getBounds: function(v) {
			var min = v.slice(0, 2),
				max = min.slice(),
				roots = [0, 0];
			for (var i = 0; i < 2; i++)
				Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
						i, 0, min, max, roots);
			return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
		},

		_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
			function add(value, padding) {
				var left = value - padding,
					right = value + padding;
				if (left < min[coord])
					min[coord] = left;
				if (right > max[coord])
					max[coord] = right;
			}

			padding /= 2;
			var minPad = min[coord] - padding,
				maxPad = max[coord] + padding;
			if (    v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||
					v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {
				if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {
					add(v0, padding);
					add(v3, padding);
				} else {
					var a = 3 * (v1 - v2) - v0 + v3,
						b = 2 * (v0 + v2) - 4 * v1,
						c = v1 - v0,
						count = Numerical.solveQuadratic(a, b, c, roots),
						tMin = 4e-7,
						tMax = 1 - tMin;
					add(v3, 0);
					for (var i = 0; i < count; i++) {
						var t = roots[i],
							u = 1 - t;
						if (tMin < t && t < tMax)
							add(u * u * u * v0
								+ 3 * u * u * t * v1
								+ 3 * u * t * t * v2
								+ t * t * t * v3,
								padding);
					}
				}
			}
		}
	}}, Base.each(
		['getBounds', 'getStrokeBounds', 'getHandleBounds'],
		function(name) {
			this[name] = function() {
				if (!this._bounds)
					this._bounds = {};
				var bounds = this._bounds[name];
				if (!bounds) {
					bounds = this._bounds[name] = Path[name](
							[this._segment1, this._segment2], false, this._path);
				}
				return bounds.clone();
			};
		},
	{

	}), Base.each({
		isStraight: function(l, h1, h2) {
			if (h1.isZero() && h2.isZero()) {
				return true;
			} else {
				var v = l.getVector(),
					epsilon = 2e-7;
				if (v.isZero()) {
					return false;
				} else if (l.getDistance(h1) < epsilon
						&& l.getDistance(h2) < epsilon) {
					var div = v.dot(v),
						p1 = v.dot(h1) / div,
						p2 = v.dot(h2) / div;
					return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
				}
			}
			return false;
		},

		isLinear: function(l, h1, h2) {
			var third = l.getVector().divide(3);
			return h1.equals(third) && h2.negate().equals(third);
		}
	}, function(test, name) {
		this[name] = function() {
			var seg1 = this._segment1,
				seg2 = this._segment2;
			return test(new Line(seg1._point, seg2._point),
					seg1._handleOut, seg2._handleIn);
		};

		this.statics[name] = function(v) {
			var p1x = v[0], p1y = v[1],
				p2x = v[6], p2y = v[7];
			return test(new Line(p1x, p1y, p2x, p2y),
					new Point(v[2] - p1x, v[3] - p1y),
					new Point(v[4] - p2x, v[5] - p2y));
		};
	}, {
		statics: {},

		hasHandles: function() {
			return !this._segment1._handleOut.isZero()
					|| !this._segment2._handleIn.isZero();
		},

		isCollinear: function(curve) {
			return curve && this.isStraight() && curve.isStraight()
					&& this.getLine().isCollinear(curve.getLine());
		},

		isHorizontal: function() {
			return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)
					< 1e-7;
		},

		isVertical: function() {
			return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)
					< 1e-7;
		}
	}), {
		beans: false,

		getLocationAt: function(offset, _isTime) {
			return this.getLocationAtTime(
					_isTime ? offset : this.getTimeAt(offset));
		},

		getLocationAtTime: function(t) {
			return t != null && t >= 0 && t <= 1
					? new CurveLocation(this, t)
					: null;
		},

		getTimeAt: function(offset, start) {
			return Curve.getTimeAt(this.getValues(), offset, start);
		},

		getParameterAt: '#getTimeAt',

		getOffsetAtTime: function(t) {
			return this.getPartLength(0, t);
		},

		getLocationOf: function() {
			return this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));
		},

		getOffsetOf: function() {
			var loc = this.getLocationOf.apply(this, arguments);
			return loc ? loc.getOffset() : null;
		},

		getTimeOf: function() {
			return Curve.getTimeOf(this.getValues(), Point.read(arguments));
		},

		getParameterOf: '#getTimeOf',

		getNearestLocation: function() {
			var point = Point.read(arguments),
				values = this.getValues(),
				t = Curve.getNearestTime(values, point),
				pt = Curve.getPoint(values, t);
			return new CurveLocation(this, t, pt, null, point.getDistance(pt));
		},

		getNearestPoint: function() {
			var loc = this.getNearestLocation.apply(this, arguments);
			return loc ? loc.getPoint() : loc;
		}

	},
	new function() {
		var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
			'getWeightedNormal', 'getCurvature'];
		return Base.each(methods,
			function(name) {
				this[name + 'At'] = function(location, _isTime) {
					var values = this.getValues();
					return Curve[name](values, _isTime ? location
							: Curve.getTimeAt(values, location));
				};

				this[name + 'AtTime'] = function(time) {
					return Curve[name](this.getValues(), time);
				};
			}, {
				statics: {
					_evaluateMethods: methods
				}
			}
		);
	},
	new function() {

		function getLengthIntegrand(v) {
			var p1x = v[0], p1y = v[1],
				c1x = v[2], c1y = v[3],
				c2x = v[4], c2y = v[5],
				p2x = v[6], p2y = v[7],

				ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
				bx = 6 * (p1x + c2x) - 12 * c1x,
				cx = 3 * (c1x - p1x),

				ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
				by = 6 * (p1y + c2y) - 12 * c1y,
				cy = 3 * (c1y - p1y);

			return function(t) {
				var dx = (ax * t + bx) * t + cx,
					dy = (ay * t + by) * t + cy;
				return Math.sqrt(dx * dx + dy * dy);
			};
		}

		function getIterations(a, b) {
			return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));
		}

		function evaluate(v, t, type, normalized) {
			if (t == null || t < 0 || t > 1)
				return null;
			var p1x = v[0], p1y = v[1],
				c1x = v[2], c1y = v[3],
				c2x = v[4], c2y = v[5],
				p2x = v[6], p2y = v[7],
				isZero = Numerical.isZero;
			if (isZero(c1x - p1x) && isZero(c1y - p1y)) {
				c1x = p1x;
				c1y = p1y;
			}
			if (isZero(c2x - p2x) && isZero(c2y - p2y)) {
				c2x = p2x;
				c2y = p2y;
			}
			var cx = 3 * (c1x - p1x),
				bx = 3 * (c2x - c1x) - cx,
				ax = p2x - p1x - cx - bx,
				cy = 3 * (c1y - p1y),
				by = 3 * (c2y - c1y) - cy,
				ay = p2y - p1y - cy - by,
				x, y;
			if (type === 0) {
				x = t === 0 ? p1x : t === 1 ? p2x
						: ((ax * t + bx) * t + cx) * t + p1x;
				y = t === 0 ? p1y : t === 1 ? p2y
						: ((ay * t + by) * t + cy) * t + p1y;
			} else {
				var tMin = 4e-7,
					tMax = 1 - tMin;
				if (t < tMin) {
					x = cx;
					y = cy;
				} else if (t > tMax) {
					x = 3 * (p2x - c2x);
					y = 3 * (p2y - c2y);
				} else {
					x = (3 * ax * t + 2 * bx) * t + cx;
					y = (3 * ay * t + 2 * by) * t + cy;
				}
				if (normalized) {
					if (x === 0 && y === 0 && (t < tMin || t > tMax)) {
						x = c2x - c1x;
						y = c2y - c1y;
					}
					var len = Math.sqrt(x * x + y * y);
					if (len) {
						x /= len;
						y /= len;
					}
				}
				if (type === 3) {
					var x2 = 6 * ax * t + 2 * bx,
						y2 = 6 * ay * t + 2 * by,
						d = Math.pow(x * x + y * y, 3 / 2);
					x = d !== 0 ? (x * y2 - y * x2) / d : 0;
					y = 0;
				}
			}
			return type === 2 ? new Point(y, -x) : new Point(x, y);
		}

		return { statics: {

			getLength: function(v, a, b, ds) {
				if (a === undefined)
					a = 0;
				if (b === undefined)
					b = 1;
				if (Curve.isStraight(v)) {
					var c = v;
					if (b < 1) {
						c = Curve.subdivide(c, b)[0];
						a /= b;
					}
					if (a > 0) {
						c = Curve.subdivide(c, a)[1];
					}
					var dx = c[6] - c[0],
						dy = c[7] - c[1];
					return Math.sqrt(dx * dx + dy * dy);
				}
				return Numerical.integrate(ds || getLengthIntegrand(v), a, b,
						getIterations(a, b));
			},

			getTimeAt: function(v, offset, start) {
				if (start === undefined)
					start = offset < 0 ? 1 : 0;
				if (offset === 0)
					return start;
				var abs = Math.abs,
					epsilon = 1e-12,
					forward = offset > 0,
					a = forward ? start : 0,
					b = forward ? 1 : start,
					ds = getLengthIntegrand(v),
					rangeLength = Curve.getLength(v, a, b, ds),
					diff = abs(offset) - rangeLength;
				if (abs(diff) < epsilon) {
					return forward ? b : a;
				} else if (diff > epsilon) {
					return null;
				}
				var guess = offset / rangeLength,
					length = 0;
				function f(t) {
					length += Numerical.integrate(ds, start, t,
							getIterations(start, t));
					start = t;
					return length - offset;
				}
				return Numerical.findRoot(f, ds, start + guess, a, b, 32,
						1e-12);
			},

			getPoint: function(v, t) {
				return evaluate(v, t, 0, false);
			},

			getTangent: function(v, t) {
				return evaluate(v, t, 1, true);
			},

			getWeightedTangent: function(v, t) {
				return evaluate(v, t, 1, false);
			},

			getNormal: function(v, t) {
				return evaluate(v, t, 2, true);
			},

			getWeightedNormal: function(v, t) {
				return evaluate(v, t, 2, false);
			},

			getCurvature: function(v, t) {
				return evaluate(v, t, 3, false).x;
			}
		}};
	},
	new function() {

		function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
				overlap) {
			var excludeStart = !overlap && param.excludeStart,
				excludeEnd = !overlap && param.excludeEnd,
				tMin = 4e-7,
				tMax = 1 - tMin;
			if (t1 == null)
				t1 = Curve.getTimeOf(v1, p1);
			if (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&
				t1 <= (excludeEnd ? tMax : 1)) {
				if (t2 == null)
					t2 = Curve.getTimeOf(v2, p2);
				if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
					t2 <= (excludeStart ? tMax : 1)) {
					var renormalize = param.renormalize;
					if (renormalize) {
						var res = renormalize(t1, t2);
						t1 = res[0];
						t2 = res[1];
					}
					var loc1 = new CurveLocation(c1, t1,
							p1 || Curve.getPoint(v1, t1), overlap),
						loc2 = new CurveLocation(c2, t2,
							p2 || Curve.getPoint(v2, t2), overlap),
						flip = loc1.getPath() === loc2.getPath()
							&& loc1.getIndex() > loc2.getIndex(),
						loc = flip ? loc2 : loc1,
						include = param.include;
					loc1._intersection = loc2;
					loc2._intersection = loc1;
					if (!include || include(loc)) {
						CurveLocation.insert(locations, loc, true);
					}
				}
			}
		}

		function addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,
				uMin, uMax, flip, recursion, calls) {
			if (++recursion >= 48 || ++calls > 4096)
				return calls;
			var q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],
				getSignedDistance = Line.getSignedDistance,
				d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),
				d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),
				factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
				dMin = factor * Math.min(0, d1, d2),
				dMax = factor * Math.max(0, d1, d2),
				dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),
				dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),
				dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),
				dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),
				hull = getConvexHull(dp0, dp1, dp2, dp3),
				top = hull[0],
				bottom = hull[1],
				tMinClip,
				tMaxClip;
			if (d1 === 0 && d2 === 0
					&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0
				|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null
				|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),
					dMin, dMax)) == null)
				return calls;
			var tMinNew = tMin + (tMax - tMin) * tMinClip,
				tMaxNew = tMin + (tMax - tMin) * tMaxClip;
			if (Math.max(uMax - uMin, tMaxNew - tMinNew)
					< 1e-9) {
				var t = (tMinNew + tMaxNew) / 2,
					u = (uMin + uMax) / 2;
				v1 = c1.getValues();
				v2 = c2.getValues();
				addLocation(locations, param,
						flip ? v2 : v1, flip ? c2 : c1, flip ? u : t, null,
						flip ? v1 : v2, flip ? c1 : c2, flip ? t : u, null);
			} else {
				v1 = Curve.getPart(v1, tMinClip, tMaxClip);
				if (tMaxClip - tMinClip > 0.8) {
					if (tMaxNew - tMinNew > uMax - uMin) {
						var parts = Curve.subdivide(v1, 0.5),
							t = (tMinNew + tMaxNew) / 2;
						calls = addCurveIntersections(
								v2, parts[0], c2, c1, locations, param,
								uMin, uMax, tMinNew, t, !flip, recursion, calls);
						calls = addCurveIntersections(
								v2, parts[1], c2, c1, locations, param,
								uMin, uMax, t, tMaxNew, !flip, recursion, calls);
					} else {
						var parts = Curve.subdivide(v2, 0.5),
							u = (uMin + uMax) / 2;
						calls = addCurveIntersections(
								parts[0], v1, c2, c1, locations, param,
								uMin, u, tMinNew, tMaxNew, !flip, recursion, calls);
						calls = addCurveIntersections(
								parts[1], v1, c2, c1, locations, param,
								u, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
					}
				} else {
					calls = addCurveIntersections(
							v2, v1, c2, c1, locations, param,
							uMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls);
				}
			}
			return calls;
		}

		function getConvexHull(dq0, dq1, dq2, dq3) {
			var p0 = [ 0, dq0 ],
				p1 = [ 1 / 3, dq1 ],
				p2 = [ 2 / 3, dq2 ],
				p3 = [ 1, dq3 ],
				dist1 = dq1 - (2 * dq0 + dq3) / 3,
				dist2 = dq2 - (dq0 + 2 * dq3) / 3,
				hull;
			if (dist1 * dist2 < 0) {
				hull = [[p0, p1, p3], [p0, p2, p3]];
			} else {
				var distRatio = dist1 / dist2;
				hull = [
					distRatio >= 2 ? [p0, p1, p3]
					: distRatio <= 0.5 ? [p0, p2, p3]
					: [p0, p1, p2, p3],
					[p0, p3]
				];
			}
			return (dist1 || dist2) < 0 ? hull.reverse() : hull;
		}

		function clipConvexHull(hullTop, hullBottom, dMin, dMax) {
			if (hullTop[0][1] < dMin) {
				return clipConvexHullPart(hullTop, true, dMin);
			} else if (hullBottom[0][1] > dMax) {
				return clipConvexHullPart(hullBottom, false, dMax);
			} else {
				return hullTop[0][0];
			}
		}

		function clipConvexHullPart(part, top, threshold) {
			var px = part[0][0],
				py = part[0][1];
			for (var i = 1, l = part.length; i < l; i++) {
				var qx = part[i][0],
					qy = part[i][1];
				if (top ? qy >= threshold : qy <= threshold) {
					return qy === threshold ? qx
							: px + (threshold - py) * (qx - px) / (qy - py);
				}
				px = qx;
				py = qy;
			}
			return null;
		}

		function addCurveLineIntersections(v1, v2, c1, c2, locations, param) {
			var flip = Curve.isStraight(v1),
				vc = flip ? v2 : v1,
				vl = flip ? v1 : v2,
				lx1 = vl[0], ly1 = vl[1],
				lx2 = vl[6], ly2 = vl[7],
				ldx = lx2 - lx1,
				ldy = ly2 - ly1,
				angle = Math.atan2(-ldy, ldx),
				sin = Math.sin(angle),
				cos = Math.cos(angle),
				rvc = [];
			for(var i = 0; i < 8; i += 2) {
				var x = vc[i] - lx1,
					y = vc[i + 1] - ly1;
				rvc.push(
					x * cos - y * sin,
					x * sin + y * cos);
			}
			var roots = [],
				count = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);
			for (var i = 0; i < count; i++) {
				var tc = roots[i],
					pc = Curve.getPoint(vc, tc),
					tl = Curve.getTimeOf(vl, pc);
				if (tl !== null) {
					var pl = Curve.getPoint(vl, tl),
						t1 = flip ? tl : tc,
						t2 = flip ? tc : tl;
					if (!param.excludeEnd || t2 > Numerical.CURVETIME_EPSILON) {
						addLocation(locations, param,
								v1, c1, t1, flip ? pl : pc,
								v2, c2, t2, flip ? pc : pl);
					}
				}
			}
		}

		function addLineIntersection(v1, v2, c1, c2, locations, param) {
			var pt = Line.intersect(
					v1[0], v1[1], v1[6], v1[7],
					v2[0], v2[1], v2[6], v2[7]);
			if (pt) {
				addLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);
			}
		}

		return { statics: {
			_getIntersections: function(v1, v2, c1, c2, locations, param) {
				if (!v2) {
					return Curve._getSelfIntersection(v1, c1, locations, param);
				}
				var epsilon = 2e-7,
					c1p1x = v1[0], c1p1y = v1[1],
					c1p2x = v1[6], c1p2y = v1[7],
					c2p1x = v2[0], c2p1y = v2[1],
					c2p2x = v2[6], c2p2y = v2[7],
					c1s1x = (3 * v1[2] + c1p1x) / 4,
					c1s1y = (3 * v1[3] + c1p1y) / 4,
					c1s2x = (3 * v1[4] + c1p2x) / 4,
					c1s2y = (3 * v1[5] + c1p2y) / 4,
					c2s1x = (3 * v2[2] + c2p1x) / 4,
					c2s1y = (3 * v2[3] + c2p1y) / 4,
					c2s2x = (3 * v2[4] + c2p2x) / 4,
					c2s2y = (3 * v2[5] + c2p2y) / 4,
					min = Math.min,
					max = Math.max;
				if (!(  max(c1p1x, c1s1x, c1s2x, c1p2x) + epsilon >
						min(c2p1x, c2s1x, c2s2x, c2p2x) &&
						min(c1p1x, c1s1x, c1s2x, c1p2x) - epsilon <
						max(c2p1x, c2s1x, c2s2x, c2p2x) &&
						max(c1p1y, c1s1y, c1s2y, c1p2y) + epsilon >
						min(c2p1y, c2s1y, c2s2y, c2p2y) &&
						min(c1p1y, c1s1y, c1s2y, c1p2y) - epsilon <
						max(c2p1y, c2s1y, c2s2y, c2p2y)))
					return locations;
				var overlaps = Curve.getOverlaps(v1, v2);
				if (overlaps) {
					for (var i = 0; i < 2; i++) {
						var overlap = overlaps[i];
						addLocation(locations, param,
							v1, c1, overlap[0], null,
							v2, c2, overlap[1], null, true);
					}
					return locations;
				}

				var straight1 = Curve.isStraight(v1),
					straight2 = Curve.isStraight(v2),
					straight = straight1 && straight2,
					before = locations.length;
				(straight
					? addLineIntersection
					: straight1 || straight2
						? addCurveLineIntersections
						: addCurveIntersections)(
							v1, v2, c1, c2, locations, param,
							0, 1, 0, 1, 0, 0, 0);
				if (straight && locations.length > before)
					return locations;
				var c1p1 = new Point(c1p1x, c1p1y),
					c1p2 = new Point(c1p2x, c1p2y),
					c2p1 = new Point(c2p1x, c2p1y),
					c2p2 = new Point(c2p2x, c2p2y);
				if (c1p1.isClose(c2p1, epsilon))
					addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);
				if (!param.excludeStart && c1p1.isClose(c2p2, epsilon))
					addLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);
				if (!param.excludeEnd && c1p2.isClose(c2p1, epsilon))
					addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);
				if (c1p2.isClose(c2p2, epsilon))
					addLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);
				return locations;
			},

			_getSelfIntersection: function(v1, c1, locations, param) {
				var p1x = v1[0], p1y = v1[1],
					h1x = v1[2], h1y = v1[3],
					h2x = v1[4], h2y = v1[5],
					p2x = v1[6], p2y = v1[7];
				var line = new Line(p1x, p1y, p2x, p2y, false),
					side1 = line.getSide(new Point(h1x, h1y), true),
					side2 = line.getSide(new Point(h2x, h2y), true);
				if (side1 === side2) {
					var edgeSum = (p1x - h2x) * (h1y - p2y)
								+ (h1x - p2x) * (h2y - p1y);
					if (edgeSum * side1 > 0)
						return locations;
				}
				var ax = p2x - 3 * h2x + 3 * h1x - p1x,
					bx = h2x - 2 * h1x + p1x,
					cx = h1x - p1x,
					ay = p2y - 3 * h2y + 3 * h1y - p1y,
					by = h2y - 2 * h1y + p1y,
					cy = h1y - p1y,
					ac = ay * cx - ax * cy,
					ab = ay * bx - ax * by,
					bc = by * cx - bx * cy;
				if (ac * ac - 4 * ab * bc < 0) {
					var roots = [],
						tSplit,
						count = Numerical.solveCubic(
								ax * ax  + ay * ay,
								3 * (ax * bx + ay * by),
								2 * (bx * bx + by * by) + ax * cx + ay * cy,
								bx * cx + by * cy,
								roots, 0, 1);
					if (count > 0) {
						for (var i = 0, maxCurvature = 0; i < count; i++) {
							var curvature = Math.abs(
									c1.getCurvatureAtTime(roots[i]));
							if (curvature > maxCurvature) {
								maxCurvature = curvature;
								tSplit = roots[i];
							}
						}
						var parts = Curve.subdivide(v1, tSplit);
						param.excludeEnd = true;
						param.renormalize = function(t1, t2) {
							return [t1 * tSplit, t2 * (1 - tSplit) + tSplit];
						};
						Curve._getIntersections(parts[0], parts[1], c1, c1,
								locations, param);
					}
				}
				return locations;
			},

			getOverlaps: function(v1, v2) {
				var abs = Math.abs,
					timeEpsilon = 4e-7,
					geomEpsilon = 2e-7,
					straight1 = Curve.isStraight(v1),
					straight2 = Curve.isStraight(v2),
					straightBoth = straight1 && straight2;

				function getSquaredLineLength(v) {
					var x = v[6] - v[0],
						y = v[7] - v[1];
					return x * x + y * y;
				}

				var flip = getSquaredLineLength(v1) < getSquaredLineLength(v2),
					l1 = flip ? v2 : v1,
					l2 = flip ? v1 : v2,
					line = new Line(l1[0], l1[1], l1[6], l1[7]);
				if (line.getDistance(new Point(l2[0], l2[1])) < geomEpsilon &&
					line.getDistance(new Point(l2[6], l2[7])) < geomEpsilon) {
					if (!straightBoth &&
						line.getDistance(new Point(l1[2], l1[3])) < geomEpsilon &&
						line.getDistance(new Point(l1[4], l1[5])) < geomEpsilon &&
						line.getDistance(new Point(l2[2], l2[3])) < geomEpsilon &&
						line.getDistance(new Point(l2[4], l2[5])) < geomEpsilon) {
						straight1 = straight2 = straightBoth = true;
					}
				} else if (straightBoth) {
					return null;
				}
				if (straight1 ^ straight2) {
					return null;
				}

				var v = [v1, v2],
					pairs = [];
				for (var i = 0, t1 = 0;
						i < 2 && pairs.length < 2;
						i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
					var t2 = Curve.getTimeOf(v[i ^ 1], new Point(
							v[i][t1 === 0 ? 0 : 6],
							v[i][t1 === 0 ? 1 : 7]));
					if (t2 != null) {
						var pair = i === 0 ? [t1, t2] : [t2, t1];
						if (pairs.length === 0 ||
							abs(pair[0] - pairs[0][0]) > timeEpsilon &&
							abs(pair[1] - pairs[0][1]) > timeEpsilon)
							pairs.push(pair);
					}
					if (i === 1 && pairs.length === 0)
						break;
				}
				if (pairs.length !== 2) {
					pairs = null;
				} else if (!straightBoth) {
					var o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),
						o2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);
					if (abs(o2[2] - o1[2]) > geomEpsilon ||
						abs(o2[3] - o1[3]) > geomEpsilon ||
						abs(o2[4] - o1[4]) > geomEpsilon ||
						abs(o2[5] - o1[5]) > geomEpsilon)
						pairs = null;
				}
				return pairs;
			}
		}};
	});

	var CurveLocation = Base.extend({
		_class: 'CurveLocation',
		beans: true,

		initialize: function CurveLocation(curve, time, point, _overlap, _distance) {
			if (time > 0.9999996) {
				var next = curve.getNext();
				if (next) {
					time = 0;
					curve = next;
				}
			}
			this._setCurve(curve);
			this._time = time;
			this._point = point || curve.getPointAtTime(time);
			this._overlap = _overlap;
			this._distance = _distance;
			this._intersection = this._next = this._previous = null;
		},

		_setCurve: function(curve) {
			var path = curve._path;
			this._path = path;
			this._version = path ? path._version : 0;
			this._curve = curve;
			this._segment = null;
			this._segment1 = curve._segment1;
			this._segment2 = curve._segment2;
		},

		_setSegment: function(segment) {
			this._setCurve(segment.getCurve());
			this._segment = segment;
			this._time = segment === this._segment1 ? 0 : 1;
			this._point = segment._point.clone();
		},

		getSegment: function() {
			var curve = this.getCurve(),
				segment = this._segment;
			if (!segment) {
				var time = this.getTime();
				if (time === 0) {
					segment = curve._segment1;
				} else if (time === 1) {
					segment = curve._segment2;
				} else if (time != null) {
					segment = curve.getPartLength(0, time)
						< curve.getPartLength(time, 1)
							? curve._segment1
							: curve._segment2;
				}
				this._segment = segment;
			}
			return segment;
		},

		getCurve: function() {
			var path = this._path,
				that = this;
			if (path && path._version !== this._version) {
				this._time = this._curve = this._offset = null;
			}

			function trySegment(segment) {
				var curve = segment && segment.getCurve();
				if (curve && (that._time = curve.getTimeOf(that._point))
						!= null) {
					that._setCurve(curve);
					that._segment = segment;
					return curve;
				}
			}

			return this._curve
				|| trySegment(this._segment)
				|| trySegment(this._segment1)
				|| trySegment(this._segment2.getPrevious());
		},

		getPath: function() {
			var curve = this.getCurve();
			return curve && curve._path;
		},

		getIndex: function() {
			var curve = this.getCurve();
			return curve && curve.getIndex();
		},

		getTime: function() {
			var curve = this.getCurve(),
				time = this._time;
			return curve && time == null
				? this._time = curve.getTimeOf(this._point)
				: time;
		},

		getParameter: '#getTime',

		getPoint: function() {
			return this._point;
		},

		getOffset: function() {
			var offset = this._offset;
			if (offset == null) {
				offset = 0;
				var path = this.getPath(),
					index = this.getIndex();
				if (path && index != null) {
					var curves = path.getCurves();
					for (var i = 0; i < index; i++)
						offset += curves[i].getLength();
				}
				this._offset = offset += this.getCurveOffset();
			}
			return offset;
		},

		getCurveOffset: function() {
			var curve = this.getCurve(),
				time = this.getTime();
			return time != null && curve && curve.getPartLength(0, time);
		},

		getIntersection: function() {
			return this._intersection;
		},

		getDistance: function() {
			return this._distance;
		},

		divide: function() {
			var curve = this.getCurve(),
				res = null;
			if (curve) {
				res = curve.divideAtTime(this.getTime());
				if (res)
					this._setSegment(res._segment1);
			}
			return res;
		},

		split: function() {
			var curve = this.getCurve();
			return curve ? curve.splitAtTime(this.getTime()) : null;
		},

		equals: function(loc, _ignoreOther) {
			var res = this === loc,
				epsilon = 2e-7;
			if (!res && loc instanceof CurveLocation
					&& this.getPath() === loc.getPath()
					&& this.getPoint().isClose(loc.getPoint(), epsilon)) {
				var c1 = this.getCurve(),
					c2 = loc.getCurve(),
					abs = Math.abs,
					diff = abs(
						((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
								+ this.getTime()) -
						((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
								+ loc.getTime()));
				res = (diff < 4e-7
					|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon
						|| abs(this.getPath().getLength() - diff) < epsilon))
					&& (_ignoreOther
						|| (!this._intersection && !loc._intersection
							|| this._intersection && this._intersection.equals(
									loc._intersection, true)));
			}
			return res;
		},

		toString: function() {
			var parts = [],
				point = this.getPoint(),
				f = Formatter.instance;
			if (point)
				parts.push('point: ' + point);
			var index = this.getIndex();
			if (index != null)
				parts.push('index: ' + index);
			var time = this.getTime();
			if (time != null)
				parts.push('time: ' + f.number(time));
			if (this._distance != null)
				parts.push('distance: ' + f.number(this._distance));
			return '{ ' + parts.join(', ') + ' }';
		},

		isTouching: function() {
			var inter = this._intersection;
			if (inter && this.getTangent().isCollinear(inter.getTangent())) {
				var curve1 = this.getCurve(),
					curve2 = inter.getCurve();
				return !(curve1.isStraight() && curve2.isStraight()
						&& curve1.getLine().intersect(curve2.getLine()));
			}
			return false;
		},

		isCrossing: function() {
			var inter = this._intersection;
			if (!inter)
				return false;
			var t1 = this.getTime(),
				t2 = inter.getTime(),
				tMin = 4e-7,
				tMax = 1 - tMin,
				t1Inside = t1 > tMin && t1 < tMax,
				t2Inside = t2 > tMin && t2 < tMax;
			if (t1Inside && t2Inside)
				return !this.isTouching();
			var c2 = this.getCurve(),
				c1 = t1 <= tMin ? c2.getPrevious() : c2,
				c4 = inter.getCurve(),
				c3 = t2 <= tMin ? c4.getPrevious() : c4;
			if (t1 >= tMax)
				c2 = c2.getNext();
			if (t2 >= tMax)
				c4 = c4.getNext();
			if (!c1 || !c2 || !c3 || !c4)
				return false;

			function isInRange(angle, min, max) {
				return min < max
						? angle > min && angle < max
						: angle > min || angle < max;
			}

			var lenghts = [];
			if (!t1Inside)
				lenghts.push(c1.getLength(), c2.getLength());
			if (!t2Inside)
				lenghts.push(c3.getLength(), c4.getLength());
			var pt = this.getPoint(),
				offset = Math.min.apply(Math, lenghts) / 64,
				v2 = t1Inside ? c2.getTangentAtTime(t1)
						: c2.getPointAt(offset).subtract(pt),
				v1 = t1Inside ? v2.negate()
						: c1.getPointAt(-offset).subtract(pt),
				v4 = t2Inside ? c4.getTangentAtTime(t2)
						: c4.getPointAt(offset).subtract(pt),
				v3 = t2Inside ? v4.negate()
						: c3.getPointAt(-offset).subtract(pt),
				a1 = v1.getAngle(),
				a2 = v2.getAngle(),
				a3 = v3.getAngle(),
				a4 = v4.getAngle();
			return !!(t1Inside
					? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&
					  (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))
					: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&
					  (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));
		},

		hasOverlap: function() {
			return !!this._overlap;
		}
	}, Base.each(Curve._evaluateMethods, function(name) {
		var get = name + 'At';
		this[name] = function() {
			var curve = this.getCurve(),
				time = this.getTime();
			return time != null && curve && curve[get](time, true);
		};
	}, {
		preserve: true
	}),
	new function() {

		function insert(locations, loc, merge) {
			var length = locations.length,
				l = 0,
				r = length - 1;

			function search(index, dir) {
				for (var i = index + dir; i >= -1 && i <= length; i += dir) {
					var loc2 = locations[((i % length) + length) % length];
					if (!loc.getPoint().isClose(loc2.getPoint(),
							2e-7))
						break;
					if (loc.equals(loc2))
						return loc2;
				}
				return null;
			}

			while (l <= r) {
				var m = (l + r) >>> 1,
					loc2 = locations[m],
					found;
				if (merge && (found = loc.equals(loc2) ? loc2
						: (search(m, -1) || search(m, 1)))) {
					if (loc._overlap) {
						found._overlap = found._intersection._overlap = true;
					}
					return found;
				}
			var path1 = loc.getPath(),
				path2 = loc2.getPath(),
				diff = path1 === path2
					? (loc.getIndex() + loc.getTime())
					- (loc2.getIndex() + loc2.getTime())
					: path1._id - path2._id;
				if (diff < 0) {
					r = m - 1;
				} else {
					l = m + 1;
				}
			}
			locations.splice(l, 0, loc);
			return loc;
		}

		return { statics: {
			insert: insert,

			expand: function(locations) {
				var expanded = locations.slice();
				for (var i = locations.length - 1; i >= 0; i--) {
					insert(expanded, locations[i]._intersection, false);
				}
				return expanded;
			}
		}};
	});

	var PathItem = Item.extend({
		_class: 'PathItem',
		_selectBounds: false,
		_canScaleStroke: true,

		initialize: function PathItem() {
		},

		statics: {
			create: function(pathData) {
				var ctor = (pathData && pathData.match(/m/gi) || []).length > 1
						|| /z\s*\S+/i.test(pathData) ? CompoundPath : Path;
				return new ctor(pathData);
			}
		},

		_asPathItem: function() {
			return this;
		},

		setPathData: function(data) {

			var parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),
				coords,
				relative = false,
				previous,
				control,
				current = new Point(),
				start = new Point();

			function getCoord(index, coord) {
				var val = +coords[index];
				if (relative)
					val += current[coord];
				return val;
			}

			function getPoint(index) {
				return new Point(
					getCoord(index, 'x'),
					getCoord(index + 1, 'y')
				);
			}

			this.clear();

			for (var i = 0, l = parts && parts.length; i < l; i++) {
				var part = parts[i],
					command = part[0],
					lower = command.toLowerCase();
				coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
				var length = coords && coords.length;
				relative = command === lower;
				if (previous === 'z' && !/[mz]/.test(lower))
					this.moveTo(current = start);
				switch (lower) {
				case 'm':
				case 'l':
					var move = lower === 'm';
					for (var j = 0; j < length; j += 2)
						this[j === 0 && move ? 'moveTo' : 'lineTo'](
								current = getPoint(j));
					control = current;
					if (move)
						start = current;
					break;
				case 'h':
				case 'v':
					var coord = lower === 'h' ? 'x' : 'y';
					for (var j = 0; j < length; j++) {
						current[coord] = getCoord(j, coord);
						this.lineTo(current);
					}
					control = current;
					break;
				case 'c':
					for (var j = 0; j < length; j += 6) {
						this.cubicCurveTo(
								getPoint(j),
								control = getPoint(j + 2),
								current = getPoint(j + 4));
					}
					break;
				case 's':
					for (var j = 0; j < length; j += 4) {
						this.cubicCurveTo(
								/[cs]/.test(previous)
										? current.multiply(2).subtract(control)
										: current,
								control = getPoint(j),
								current = getPoint(j + 2));
						previous = lower;
					}
					break;
				case 'q':
					for (var j = 0; j < length; j += 4) {
						this.quadraticCurveTo(
								control = getPoint(j),
								current = getPoint(j + 2));
					}
					break;
				case 't':
					for (var j = 0; j < length; j += 2) {
						this.quadraticCurveTo(
								control = (/[qt]/.test(previous)
										? current.multiply(2).subtract(control)
										: current),
								current = getPoint(j));
						previous = lower;
					}
					break;
				case 'a':
					for (var j = 0; j < length; j += 7) {
						this.arcTo(current = getPoint(j + 5),
								new Size(+coords[j], +coords[j + 1]),
								+coords[j + 2], +coords[j + 4], +coords[j + 3]);
					}
					break;
				case 'z':
					this.closePath(1e-12);
					break;
				}
				previous = lower;
			}
		},

		_canComposite: function() {
			return !(this.hasFill() && this.hasStroke());
		},

		_contains: function(point) {
			var winding = point.isInside(
					this.getBounds({ internal: true, handle: true }))
						&& this._getWinding(point);
			return !!(this.getFillRule() === 'evenodd' ? winding & 1 : winding);
		},

		getIntersections: function(path, include, _matrix, _returnFirst) {
			var self = this === path || !path,
				matrix1 = this._matrix._orNullIfIdentity(),
				matrix2 = self ? matrix1
					: (_matrix || path._matrix)._orNullIfIdentity();
			if (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))
				return [];
			var curves1 = this.getCurves(),
				curves2 = self ? curves1 : path.getCurves(),
				length1 = curves1.length,
				length2 = self ? length1 : curves2.length,
				values2 = [],
				arrays = [],
				locations,
				path;
			for (var i = 0; i < length2; i++)
				values2[i] = curves2[i].getValues(matrix2);
			for (var i = 0; i < length1; i++) {
				var curve1 = curves1[i],
					values1 = self ? values2[i] : curve1.getValues(matrix1),
					path1 = curve1.getPath();
				if (path1 !== path) {
					path = path1;
					locations = [];
					arrays.push(locations);
				}
				if (self) {
					Curve._getSelfIntersection(values1, curve1, locations, {
						include: include,
						excludeStart: length1 === 1 &&
								curve1.getPoint1().equals(curve1.getPoint2())
					});
				}
				for (var j = self ? i + 1 : 0; j < length2; j++) {
					if (_returnFirst && locations.length)
						return locations;
					var curve2 = curves2[j];
					Curve._getIntersections(
						values1, values2[j], curve1, curve2, locations,
						{
							include: include,
							excludeStart: self && curve1.getPrevious() === curve2,
							excludeEnd: self && curve1.getNext() === curve2
						}
					);
				}
			}
			locations = [];
			for (var i = 0, l = arrays.length; i < l; i++) {
				locations.push.apply(locations, arrays[i]);
			}
			return locations;
		},

		getCrossings: function(path) {
			return this.getIntersections(path, function(inter) {
				return inter._overlap || inter.isCrossing();
			});
		},

		getNearestLocation: function() {
			var point = Point.read(arguments),
				curves = this.getCurves(),
				minDist = Infinity,
				minLoc = null;
			for (var i = 0, l = curves.length; i < l; i++) {
				var loc = curves[i].getNearestLocation(point);
				if (loc._distance < minDist) {
					minDist = loc._distance;
					minLoc = loc;
				}
			}
			return minLoc;
		},

		getNearestPoint: function() {
			var loc = this.getNearestLocation.apply(this, arguments);
			return loc ? loc.getPoint() : loc;
		},

		interpolate: function(from, to, factor) {
			var isPath = !this._children,
				name = isPath ? '_segments' : '_children',
				itemsFrom = from[name],
				itemsTo = to[name],
				items = this[name];
			if (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {
				throw new Error('Invalid operands in interpolate() call: ' +
						from + ', ' + to);
			}
			var current = items.length,
				length = itemsTo.length;
			if (current < length) {
				var ctor = isPath ? Segment : Path;
				for (var i = current; i < length; i++) {
					this.add(new ctor());
				}
			} else if (current > length) {
				this[isPath ? 'removeSegments' : 'removeChildren'](length, current);
			}
			for (var i = 0; i < length; i++) {
				items[i].interpolate(itemsFrom[i], itemsTo[i], factor);
			}
			if (isPath) {
				this.setClosed(from._closed);
				this._changed(9);
			}
		},

	});

	var Path = PathItem.extend({
		_class: 'Path',
		_serializeFields: {
			segments: [],
			closed: false
		},

		initialize: function Path(arg) {
			this._closed = false;
			this._segments = [];
			this._version = 0;
			var segments = Array.isArray(arg)
				? typeof arg[0] === 'object'
					? arg
					: arguments
				: arg && (arg.size === undefined && (arg.x !== undefined
						|| arg.point !== undefined))
					? arguments
					: null;
			if (segments && segments.length > 0) {
				this.setSegments(segments);
			} else {
				this._curves = undefined;
				this._segmentSelection = 0;
				if (!segments && typeof arg === 'string') {
					this.setPathData(arg);
					arg = null;
				}
			}
			this._initialize(!segments && arg);
		},

		_equals: function(item) {
			return this._closed === item._closed
					&& Base.equals(this._segments, item._segments);
		},

		copyContent: function(source) {
			this.setSegments(source._segments);
			this._closed = source._closed;
			var clockwise = source._clockwise;
			if (clockwise !== undefined)
				this._clockwise = clockwise;
		},

		_changed: function _changed(flags) {
			_changed.base.call(this, flags);
			if (flags & 8) {
				this._length = this._area = this._clockwise = this._monoCurves =
						undefined;
				if (flags & 16) {
					this._version++;
				} else if (this._curves) {
				   for (var i = 0, l = this._curves.length; i < l; i++)
						this._curves[i]._changed();
				}
			} else if (flags & 32) {
				this._bounds = undefined;
			}
		},

		getStyle: function() {
			var parent = this._parent;
			return (parent instanceof CompoundPath ? parent : this)._style;
		},

		getSegments: function() {
			return this._segments;
		},

		setSegments: function(segments) {
			var fullySelected = this.isFullySelected();
			this._segments.length = 0;
			this._segmentSelection = 0;
			this._curves = undefined;
			if (segments && segments.length > 0)
				this._add(Segment.readAll(segments));
			if (fullySelected)
				this.setFullySelected(true);
		},

		getFirstSegment: function() {
			return this._segments[0];
		},

		getLastSegment: function() {
			return this._segments[this._segments.length - 1];
		},

		getCurves: function() {
			var curves = this._curves,
				segments = this._segments;
			if (!curves) {
				var length = this._countCurves();
				curves = this._curves = new Array(length);
				for (var i = 0; i < length; i++)
					curves[i] = new Curve(this, segments[i],
						segments[i + 1] || segments[0]);
			}
			return curves;
		},

		getFirstCurve: function() {
			return this.getCurves()[0];
		},

		getLastCurve: function() {
			var curves = this.getCurves();
			return curves[curves.length - 1];
		},

		isClosed: function() {
			return this._closed;
		},

		setClosed: function(closed) {
			if (this._closed != (closed = !!closed)) {
				this._closed = closed;
				if (this._curves) {
					var length = this._curves.length = this._countCurves();
					if (closed)
						this._curves[length - 1] = new Curve(this,
							this._segments[length - 1], this._segments[0]);
				}
				this._changed(25);
			}
		}
	}, {
		beans: true,

		getPathData: function(_matrix, _precision) {
			var segments = this._segments,
				length = segments.length,
				f = new Formatter(_precision),
				coords = new Array(6),
				first = true,
				curX, curY,
				prevX, prevY,
				inX, inY,
				outX, outY,
				parts = [];

			function addSegment(segment, skipLine) {
				segment._transformCoordinates(_matrix, coords);
				curX = coords[0];
				curY = coords[1];
				if (first) {
					parts.push('M' + f.pair(curX, curY));
					first = false;
				} else {
					inX = coords[2];
					inY = coords[3];
					if (inX === curX && inY === curY
							&& outX === prevX && outY === prevY) {
						if (!skipLine)
							parts.push('l' + f.pair(curX - prevX, curY - prevY));
					} else {
						parts.push('c' + f.pair(outX - prevX, outY - prevY)
								+ ' ' + f.pair(inX - prevX, inY - prevY)
								+ ' ' + f.pair(curX - prevX, curY - prevY));
					}
				}
				prevX = curX;
				prevY = curY;
				outX = coords[4];
				outY = coords[5];
			}

			if (length === 0)
				return '';

			for (var i = 0; i < length; i++)
				addSegment(segments[i]);
			if (this._closed && length > 0) {
				addSegment(segments[0], true);
				parts.push('z');
			}
			return parts.join('');
		},

		isEmpty: function() {
			return this._segments.length === 0;
		},

		_transformContent: function(matrix) {
			var segments = this._segments,
				coords = new Array(6);
			for (var i = 0, l = segments.length; i < l; i++)
				segments[i]._transformCoordinates(matrix, coords, true);
			return true;
		},

		_add: function(segs, index) {
			var segments = this._segments,
				curves = this._curves,
				amount = segs.length,
				append = index == null,
				index = append ? segments.length : index;
			for (var i = 0; i < amount; i++) {
				var segment = segs[i];
				if (segment._path)
					segment = segs[i] = segment.clone();
				segment._path = this;
				segment._index = index + i;
				if (segment._selection)
					this._updateSelection(segment, 0, segment._selection);
			}
			if (append) {
				segments.push.apply(segments, segs);
			} else {
				segments.splice.apply(segments, [index, 0].concat(segs));
				for (var i = index + amount, l = segments.length; i < l; i++)
					segments[i]._index = i;
			}
			if (curves) {
				var total = this._countCurves(),
					start = index > 0 && index + amount - 1 === total ? index - 1
						: index,
					insert = start,
					end = Math.min(start + amount, total);
				if (segs._curves) {
					curves.splice.apply(curves, [start, 0].concat(segs._curves));
					insert += segs._curves.length;
				}
				for (var i = insert; i < end; i++)
					curves.splice(i, 0, new Curve(this, null, null));
				this._adjustCurves(start, end);
			}
			this._changed(25);
			return segs;
		},

		_adjustCurves: function(start, end) {
			var segments = this._segments,
				curves = this._curves,
				curve;
			for (var i = start; i < end; i++) {
				curve = curves[i];
				curve._path = this;
				curve._segment1 = segments[i];
				curve._segment2 = segments[i + 1] || segments[0];
				curve._changed();
			}
			if (curve = curves[this._closed && start === 0 ? segments.length - 1
					: start - 1]) {
				curve._segment2 = segments[start] || segments[0];
				curve._changed();
			}
			if (curve = curves[end]) {
				curve._segment1 = segments[end];
				curve._changed();
			}
		},

		_countCurves: function() {
			var length = this._segments.length;
			return !this._closed && length > 0 ? length - 1 : length;
		},

		add: function(segment1 ) {
			return arguments.length > 1 && typeof segment1 !== 'number'
				? this._add(Segment.readAll(arguments))
				: this._add([ Segment.read(arguments) ])[0];
		},

		insert: function(index, segment1 ) {
			return arguments.length > 2 && typeof segment1 !== 'number'
				? this._add(Segment.readAll(arguments, 1), index)
				: this._add([ Segment.read(arguments, 1) ], index)[0];
		},

		addSegment: function() {
			return this._add([ Segment.read(arguments) ])[0];
		},

		insertSegment: function(index ) {
			return this._add([ Segment.read(arguments, 1) ], index)[0];
		},

		addSegments: function(segments) {
			return this._add(Segment.readAll(segments));
		},

		insertSegments: function(index, segments) {
			return this._add(Segment.readAll(segments), index);
		},

		removeSegment: function(index) {
			return this.removeSegments(index, index + 1)[0] || null;
		},

		removeSegments: function(start, end, _includeCurves) {
			start = start || 0;
			end = Base.pick(end, this._segments.length);
			var segments = this._segments,
				curves = this._curves,
				count = segments.length,
				removed = segments.splice(start, end - start),
				amount = removed.length;
			if (!amount)
				return removed;
			for (var i = 0; i < amount; i++) {
				var segment = removed[i];
				if (segment._selection)
					this._updateSelection(segment, segment._selection, 0);
				segment._index = segment._path = null;
			}
			for (var i = start, l = segments.length; i < l; i++)
				segments[i]._index = i;
			if (curves) {
				var index = start > 0 && end === count + (this._closed ? 1 : 0)
						? start - 1
						: start,
					curves = curves.splice(index, amount);
				for (var i = curves.length - 1; i >= 0; i--)
					curves[i]._path = null;
				if (_includeCurves)
					removed._curves = curves.slice(1);
				this._adjustCurves(index, index);
			}
			this._changed(25);
			return removed;
		},

		clear: '#removeSegments',

		hasHandles: function() {
			var segments = this._segments;
			for (var i = 0, l = segments.length; i < l; i++) {
				if (segments[i].hasHandles())
					return true;
			}
			return false;
		},

		clearHandles: function() {
			var segments = this._segments;
			for (var i = 0, l = segments.length; i < l; i++)
				segments[i].clearHandles();
		},

		getLength: function() {
			if (this._length == null) {
				var curves = this.getCurves(),
					length = 0;
				for (var i = 0, l = curves.length; i < l; i++)
					length += curves[i].getLength();
				this._length = length;
			}
			return this._length;
		},

		getArea: function(_closed) {
			var cached = _closed === undefined,
				area = this._area;
			if (!cached || area == null) {
				var segments = this._segments,
					count = segments.length,
					closed = cached ? this._closed : _closed,
					last = count - 1;
				area = 0;
				for (var i = 0, l = closed ? count : last; i < l; i++) {
					area += Curve.getArea(Curve.getValues(
							segments[i], segments[i < last ? i + 1 : 0]));
				}
				if (cached)
					this._area = area;
			}
			return area;
		},

		isClockwise: function() {
			if (this._clockwise !== undefined)
				return this._clockwise;
			return this.getArea() >= 0;
		},

		setClockwise: function(clockwise) {
			if (this.isClockwise() != (clockwise = !!clockwise))
				this.reverse();
			this._clockwise = clockwise;
		},

		isFullySelected: function() {
			var length = this._segments.length;
			return this.isSelected() && length > 0 && this._segmentSelection
					=== length * 7;
		},

		setFullySelected: function(selected) {
			if (selected)
				this._selectSegments(true);
			this.setSelected(selected);
		},

		setSelection: function setSelection(selection) {
			if (!(selection & 1))
				this._selectSegments(false);
			setSelection.base.call(this, selection);
		},

		_selectSegments: function(selected) {
			var segments = this._segments,
				length = segments.length,
				selection = selected ? 7 : 0;
			this._segmentSelection = selection * length;
			for (var i = 0; i < length; i++)
				segments[i]._selection = selection;
		},

		_updateSelection: function(segment, oldSelection, newSelection) {
			segment._selection = newSelection;
			var selection = this._segmentSelection += newSelection - oldSelection;
			if (selection > 0)
				this.setSelected(true);
		},

		splitAt: function(location) {
			var loc = typeof location === 'number'
					? this.getLocationAt(location) : location,
				index = loc && loc.index,
				time = loc && loc.time,
				tMin = 4e-7,
				tMax = 1 - tMin;
			if (time >= tMax) {
				index++;
				time = 0;
			}
			var curves = this.getCurves();
			if (index >= 0 && index < curves.length) {
				if (time >= tMin) {
					curves[index++].divideAtTime(time);
				}
				var segs = this.removeSegments(index, this._segments.length, true),
					path;
				if (this._closed) {
					this.setClosed(false);
					path = this;
				} else {
					path = new Path(Item.NO_INSERT);
					path.insertAbove(this, true);
					path.copyAttributes(this);
				}
				path._add(segs, 0);
				this.addSegment(segs[0]);
				return path;
			}
			return null;
		},

		split: function(index, time) {
			var curve,
				location = time === undefined ? index
					: (curve = this.getCurves()[index])
						&& curve.getLocationAtTime(time);
			return location != null ? this.splitAt(location) : null;
		},

		join: function(path, tolerance) {
			var epsilon = tolerance || 0;
			if (path && path !== this) {
				var segments = path._segments,
					last1 = this.getLastSegment(),
					last2 = path.getLastSegment();
				if (!last2)
					return this;
				if (last1 && last1._point.isClose(last2._point, epsilon))
					path.reverse();
				var first2 = path.getFirstSegment();
				if (last1 && last1._point.isClose(first2._point, epsilon)) {
					last1.setHandleOut(first2._handleOut);
					this._add(segments.slice(1));
				} else {
					var first1 = this.getFirstSegment();
					if (first1 && first1._point.isClose(first2._point, epsilon))
						path.reverse();
					last2 = path.getLastSegment();
					if (first1 && first1._point.isClose(last2._point, epsilon)) {
						first1.setHandleIn(last2._handleIn);
						this._add(segments.slice(0, segments.length - 1), 0);
					} else {
						this._add(segments.slice());
					}
				}
				if (path._closed)
					this._add([segments[0]]);
				path.remove();
			}
			var first = this.getFirstSegment(),
				last = this.getLastSegment();
			if (first !== last && first._point.isClose(last._point, epsilon)) {
				first.setHandleIn(last._handleIn);
				last.remove();
				this.setClosed(true);
			}
			return this;
		},

		reduce: function(options) {
			var curves = this.getCurves(),
				simplify = options && options.simplify,
				tolerance = simplify ? 2e-7 : 0;
			for (var i = curves.length - 1; i >= 0; i--) {
				var curve = curves[i];
				if (!curve.hasHandles() && (curve.getLength() < tolerance
						|| simplify && curve.isCollinear(curve.getNext())))
					curve.remove();
			}
			return this;
		},

		reverse: function() {
			this._segments.reverse();
			for (var i = 0, l = this._segments.length; i < l; i++) {
				var segment = this._segments[i];
				var handleIn = segment._handleIn;
				segment._handleIn = segment._handleOut;
				segment._handleOut = handleIn;
				segment._index = i;
			}
			this._curves = null;
			if (this._clockwise !== undefined)
				this._clockwise = !this._clockwise;
			this._changed(9);
		},

		flatten: function(flatness) {
			var iterator = new PathIterator(this, flatness || 0.25, 256, true),
				parts = iterator.parts,
				length = parts.length,
				segments = [];
			for (var i = 0; i < length; i++) {
				segments.push(new Segment(parts[i].curve.slice(0, 2)));
			}
			if (!this._closed && length > 0) {
				segments.push(new Segment(parts[length - 1].curve.slice(6)));
			}
			this.setSegments(segments);
		},

		simplify: function(tolerance) {
			var segments = new PathFitter(this).fit(tolerance || 2.5);
			if (segments)
				this.setSegments(segments);
			return !!segments;
		},

		smooth: function(options) {
			var that = this,
				opts = options || {},
				type = opts.type || 'asymmetric',
				segments = this._segments,
				length = segments.length,
				closed = this._closed;

			function getIndex(value, _default) {
				var index = value && value.index;
				if (index != null) {
					var path = value.path;
					if (path && path !== that)
						throw new Error(value._class + ' ' + index + ' of ' + path
								+ ' is not part of ' + that);
					if (_default && value instanceof Curve)
						index++;
				} else {
					index = typeof value === 'number' ? value : _default;
				}
				return Math.min(index < 0 && closed
						? index % length
						: index < 0 ? index + length : index, length - 1);
			}

			var loop = closed && opts.from === undefined && opts.to === undefined,
				from = getIndex(opts.from, 0),
				to = getIndex(opts.to, length - 1);

			if (from > to) {
				if (closed) {
					from -= length;
				} else {
					var tmp = from;
					from = to;
					to = tmp;
				}
			}
			if (/^(?:asymmetric|continuous)$/.test(type)) {
				var asymmetric = type === 'asymmetric',
					min = Math.min,
					amount = to - from + 1,
					n = amount - 1,
					padding = loop ? min(amount, 4) : 1,
					paddingLeft = padding,
					paddingRight = padding,
					knots = [];
				if (!closed) {
					paddingLeft = min(1, from);
					paddingRight = min(1, length - to - 1);
				}
				n += paddingLeft + paddingRight;
				if (n <= 1)
					return;
				for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
					knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
				}

				var x = knots[0]._x + 2 * knots[1]._x,
					y = knots[0]._y + 2 * knots[1]._y,
					f = 2,
					n_1 = n - 1,
					rx = [x],
					ry = [y],
					rf = [f],
					px = [],
					py = [];
				for (var i = 1; i < n; i++) {
					var internal = i < n_1,
						a = internal ? 1 : asymmetric ? 1 : 2,
						b = internal ? 4 : asymmetric ? 2 : 7,
						u = internal ? 4 : asymmetric ? 3 : 8,
						v = internal ? 2 : asymmetric ? 0 : 1,
						m = a / f;
					f = rf[i] = b - m;
					x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
					y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
				}

				px[n_1] = rx[n_1] / rf[n_1];
				py[n_1] = ry[n_1] / rf[n_1];
				for (var i = n - 2; i >= 0; i--) {
					px[i] = (rx[i] - px[i + 1]) / rf[i];
					py[i] = (ry[i] - py[i + 1]) / rf[i];
				}
				px[n] = (3 * knots[n]._x - px[n_1]) / 2;
				py[n] = (3 * knots[n]._y - py[n_1]) / 2;

				for (var i = paddingLeft, max = n - paddingRight, j = from;
						i <= max; i++, j++) {
					var segment = segments[j < 0 ? j + length : j],
						pt = segment._point,
						hx = px[i] - pt._x,
						hy = py[i] - pt._y;
					if (loop || i < max)
						segment.setHandleOut(hx, hy);
					if (loop || i > paddingLeft)
						segment.setHandleIn(-hx, -hy);
				}
			} else {
				for (var i = from; i <= to; i++) {
					segments[i < 0 ? i + length : i].smooth(opts,
							!loop && i === from, !loop && i === to);
				}
			}
		},

		toShape: function(insert) {
			if (!this._closed)
				return null;

			var segments = this._segments,
				type,
				size,
				radius,
				topCenter;

			function isCollinear(i, j) {
				var seg1 = segments[i],
					seg2 = seg1.getNext(),
					seg3 = segments[j],
					seg4 = seg3.getNext();
				return seg1._handleOut.isZero() && seg2._handleIn.isZero()
						&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
						&& seg2._point.subtract(seg1._point).isCollinear(
							seg4._point.subtract(seg3._point));
			}

			function isOrthogonal(i) {
				var seg2 = segments[i],
					seg1 = seg2.getPrevious(),
					seg3 = seg2.getNext();
				return seg1._handleOut.isZero() && seg2._handleIn.isZero()
						&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
						&& seg2._point.subtract(seg1._point).isOrthogonal(
							seg3._point.subtract(seg2._point));
			}

			function isArc(i) {
				var seg1 = segments[i],
					seg2 = seg1.getNext(),
					handle1 = seg1._handleOut,
					handle2 = seg2._handleIn,
					kappa = 0.5522847498307936;
				if (handle1.isOrthogonal(handle2)) {
					var pt1 = seg1._point,
						pt2 = seg2._point,
						corner = new Line(pt1, handle1, true).intersect(
								new Line(pt2, handle2, true), true);
					return corner && Numerical.isZero(handle1.getLength() /
							corner.subtract(pt1).getLength() - kappa)
						&& Numerical.isZero(handle2.getLength() /
							corner.subtract(pt2).getLength() - kappa);
				}
				return false;
			}

			function getDistance(i, j) {
				return segments[i]._point.getDistance(segments[j]._point);
			}

			if (!this.hasHandles() && segments.length === 4
					&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {
				type = Shape.Rectangle;
				size = new Size(getDistance(0, 3), getDistance(0, 1));
				topCenter = segments[1]._point.add(segments[2]._point).divide(2);
			} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)
					&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {
				type = Shape.Rectangle;
				size = new Size(getDistance(1, 6), getDistance(0, 3));
				radius = size.subtract(new Size(getDistance(0, 7),
						getDistance(1, 2))).divide(2);
				topCenter = segments[3]._point.add(segments[4]._point).divide(2);
			} else if (segments.length === 4
					&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
				if (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {
					type = Shape.Circle;
					radius = getDistance(0, 2) / 2;
				} else {
					type = Shape.Ellipse;
					radius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);
				}
				topCenter = segments[1]._point;
			}

			if (type) {
				var center = this.getPosition(true),
					shape = new type({
						center: center,
						size: size,
						radius: radius,
						insert: false
					});
				shape.copyAttributes(this, true);
				shape._matrix.prepend(this._matrix);
				shape.rotate(topCenter.subtract(center).getAngle() + 90);
				if (insert === undefined || insert)
					shape.insertAbove(this);
				return shape;
			}
			return null;
		},

		toPath: '#clone',

		_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {
			var that = this,
				style = this.getStyle(),
				segments = this._segments,
				numSegments = segments.length,
				closed = this._closed,
				tolerancePadding = options._tolerancePadding,
				strokePadding = tolerancePadding,
				join, cap, miterLimit,
				area, loc, res,
				hitStroke = options.stroke && style.hasStroke(),
				hitFill = options.fill && style.hasFill(),
				hitCurves = options.curves,
				strokeRadius = hitStroke
						? style.getStrokeWidth() / 2
						: hitFill && options.tolerance > 0 || hitCurves
							? 0 : null;
			if (strokeRadius !== null) {
				if (strokeRadius > 0) {
					join = style.getStrokeJoin();
					cap = style.getStrokeCap();
					miterLimit = strokeRadius * style.getMiterLimit();
					strokePadding = strokePadding.add(
						Path._getStrokePadding(strokeRadius, strokeMatrix));
				} else {
					join = cap = 'round';
				}
			}

			function isCloseEnough(pt, padding) {
				return point.subtract(pt).divide(padding).length <= 1;
			}

			function checkSegmentPoint(seg, pt, name) {
				if (!options.selected || pt.isSelected()) {
					var anchor = seg._point;
					if (pt !== anchor)
						pt = pt.add(anchor);
					if (isCloseEnough(pt, strokePadding)) {
						return new HitResult(name, that, {
							segment: seg,
							point: pt
						});
					}
				}
			}

			function checkSegmentPoints(seg, ends) {
				return (ends || options.segments)
					&& checkSegmentPoint(seg, seg._point, 'segment')
					|| (!ends && options.handles) && (
						checkSegmentPoint(seg, seg._handleIn, 'handle-in') ||
						checkSegmentPoint(seg, seg._handleOut, 'handle-out'));
			}

			function addToArea(point) {
				area.add(point);
			}

			function checkSegmentStroke(segment) {
				if (join !== 'round' || cap !== 'round') {
					area = new Path({ internal: true, closed: true });
					if (closed || segment._index > 0
							&& segment._index < numSegments - 1) {
						if (join !== 'round' && (segment._handleIn.isZero()
								|| segment._handleOut.isZero()))
							Path._addBevelJoin(segment, join, strokeRadius,
								   miterLimit, null, strokeMatrix, addToArea, true);
					} else if (cap !== 'round') {
						Path._addSquareCap(segment, cap, strokeRadius, null,
								strokeMatrix, addToArea, true);
					}
					if (!area.isEmpty()) {
						var loc;
						return area.contains(point)
							|| (loc = area.getNearestLocation(point))
								&& isCloseEnough(loc.getPoint(), tolerancePadding);
					}
				}
				return isCloseEnough(segment._point, strokePadding);
			}

			if (options.ends && !options.segments && !closed) {
				if (res = checkSegmentPoints(segments[0], true)
						|| checkSegmentPoints(segments[numSegments - 1], true))
					return res;
			} else if (options.segments || options.handles) {
				for (var i = 0; i < numSegments; i++)
					if (res = checkSegmentPoints(segments[i]))
						return res;
			}
			if (strokeRadius !== null) {
				loc = this.getNearestLocation(point);
				if (loc) {
					var time = loc.getTime();
					if (time === 0 || time === 1 && numSegments > 1) {
						if (!checkSegmentStroke(loc.getSegment()))
							loc = null;
					} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
						loc = null;
					}
				}
				if (!loc && join === 'miter' && numSegments > 1) {
					for (var i = 0; i < numSegments; i++) {
						var segment = segments[i];
						if (point.getDistance(segment._point) <= miterLimit
								&& checkSegmentStroke(segment)) {
							loc = segment.getLocation();
							break;
						}
					}
				}
			}
			return !loc && hitFill && this._contains(point)
					|| loc && !hitStroke && !hitCurves
						? new HitResult('fill', this)
						: loc
							? new HitResult(hitStroke ? 'stroke' : 'curve', this, {
								location: loc,
								point: loc.getPoint()
							})
							: null;
		}

	}, Base.each(Curve._evaluateMethods,
		function(name) {
			this[name + 'At'] = function(offset) {
				var loc = this.getLocationAt(offset);
				return loc && loc[name]();
			};
		},
	{
		beans: false,

		getLocationOf: function() {
			var point = Point.read(arguments),
				curves = this.getCurves();
			for (var i = 0, l = curves.length; i < l; i++) {
				var loc = curves[i].getLocationOf(point);
				if (loc)
					return loc;
			}
			return null;
		},

		getOffsetOf: function() {
			var loc = this.getLocationOf.apply(this, arguments);
			return loc ? loc.getOffset() : null;
		},

		getLocationAt: function(offset) {
			var curves = this.getCurves(),
				length = 0;
			for (var i = 0, l = curves.length; i < l; i++) {
				var start = length,
					curve = curves[i];
				length += curve.getLength();
				if (length > offset) {
					return curve.getLocationAt(offset - start);
				}
			}
			if (curves.length > 0 && offset <= this.getLength())
				return new CurveLocation(curves[curves.length - 1], 1);
			return null;
		}

	}),
	new function() {

		function drawHandles(ctx, segments, matrix, size) {
			var half = size / 2,
				coords = new Array(6),
				pX, pY;

			function drawHandle(index) {
				var hX = coords[index],
					hY = coords[index + 1];
				if (pX != hX || pY != hY) {
					ctx.beginPath();
					ctx.moveTo(pX, pY);
					ctx.lineTo(hX, hY);
					ctx.stroke();
					ctx.beginPath();
					ctx.arc(hX, hY, half, 0, Math.PI * 2, true);
					ctx.fill();
				}
			}

			for (var i = 0, l = segments.length; i < l; i++) {
				var segment = segments[i],
					selection = segment._selection;
				segment._transformCoordinates(matrix, coords);
				pX = coords[0];
				pY = coords[1];
				if (selection & 2)
					drawHandle(2);
				if (selection & 4)
					drawHandle(4);
				ctx.fillRect(pX - half, pY - half, size, size);
				if (!(selection & 1)) {
					var fillStyle = ctx.fillStyle;
					ctx.fillStyle = '#ffffff';
					ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);
					ctx.fillStyle = fillStyle;
				}
			}
		}

		function drawSegments(ctx, path, matrix) {
			var segments = path._segments,
				length = segments.length,
				coords = new Array(6),
				first = true,
				curX, curY,
				prevX, prevY,
				inX, inY,
				outX, outY;

			function drawSegment(segment) {
				if (matrix) {
					segment._transformCoordinates(matrix, coords);
					curX = coords[0];
					curY = coords[1];
				} else {
					var point = segment._point;
					curX = point._x;
					curY = point._y;
				}
				if (first) {
					ctx.moveTo(curX, curY);
					first = false;
				} else {
					if (matrix) {
						inX = coords[2];
						inY = coords[3];
					} else {
						var handle = segment._handleIn;
						inX = curX + handle._x;
						inY = curY + handle._y;
					}
					if (inX === curX && inY === curY
							&& outX === prevX && outY === prevY) {
						ctx.lineTo(curX, curY);
					} else {
						ctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);
					}
				}
				prevX = curX;
				prevY = curY;
				if (matrix) {
					outX = coords[4];
					outY = coords[5];
				} else {
					var handle = segment._handleOut;
					outX = prevX + handle._x;
					outY = prevY + handle._y;
				}
			}

			for (var i = 0; i < length; i++)
				drawSegment(segments[i]);
			if (path._closed && length > 0)
				drawSegment(segments[0]);
		}

		return {
			_draw: function(ctx, param, viewMatrix, strokeMatrix) {
				var dontStart = param.dontStart,
					dontPaint = param.dontFinish || param.clip,
					style = this.getStyle(),
					hasFill = style.hasFill(),
					hasStroke = style.hasStroke(),
					dashArray = style.getDashArray(),
					dashLength = !paper.support.nativeDash && hasStroke
							&& dashArray && dashArray.length;

				if (!dontStart)
					ctx.beginPath();

				if (hasFill || hasStroke && !dashLength || dontPaint) {
					drawSegments(ctx, this, strokeMatrix);
					if (this._closed)
						ctx.closePath();
				}

				function getOffset(i) {
					return dashArray[((i % dashLength) + dashLength) % dashLength];
				}

				if (!dontPaint && (hasFill || hasStroke)) {
					this._setStyles(ctx, param, viewMatrix);
					if (hasFill) {
						ctx.fill(style.getFillRule());
						ctx.shadowColor = 'rgba(0,0,0,0)';
					}
					if (hasStroke) {
						if (dashLength) {
							if (!dontStart)
								ctx.beginPath();
							var iterator = new PathIterator(this, 0.25, 32, false,
									strokeMatrix),
								length = iterator.length,
								from = -style.getDashOffset(), to,
								i = 0;
							from = from % length;
							while (from > 0) {
								from -= getOffset(i--) + getOffset(i--);
							}
							while (from < length) {
								to = from + getOffset(i++);
								if (from > 0 || to > 0)
									iterator.drawPart(ctx,
											Math.max(from, 0), Math.max(to, 0));
								from = to + getOffset(i++);
							}
						}
						ctx.stroke();
					}
				}
			},

			_drawSelected: function(ctx, matrix) {
				ctx.beginPath();
				drawSegments(ctx, this, matrix);
				ctx.stroke();
				drawHandles(ctx, this._segments, matrix, paper.settings.handleSize);
			}
		};
	},
	new function() {
		function getCurrentSegment(that) {
			var segments = that._segments;
			if (segments.length === 0)
				throw new Error('Use a moveTo() command first');
			return segments[segments.length - 1];
		}

		return {
			moveTo: function() {
				var segments = this._segments;
				if (segments.length === 1)
					this.removeSegment(0);
				if (!segments.length)
					this._add([ new Segment(Point.read(arguments)) ]);
			},

			moveBy: function() {
				throw new Error('moveBy() is unsupported on Path items.');
			},

			lineTo: function() {
				this._add([ new Segment(Point.read(arguments)) ]);
			},

			cubicCurveTo: function() {
				var handle1 = Point.read(arguments),
					handle2 = Point.read(arguments),
					to = Point.read(arguments),
					current = getCurrentSegment(this);
				current.setHandleOut(handle1.subtract(current._point));
				this._add([ new Segment(to, handle2.subtract(to)) ]);
			},

			quadraticCurveTo: function() {
				var handle = Point.read(arguments),
					to = Point.read(arguments),
					current = getCurrentSegment(this)._point;
				this.cubicCurveTo(
					handle.add(current.subtract(handle).multiply(1 / 3)),
					handle.add(to.subtract(handle).multiply(1 / 3)),
					to
				);
			},

			curveTo: function() {
				var through = Point.read(arguments),
					to = Point.read(arguments),
					t = Base.pick(Base.read(arguments), 0.5),
					t1 = 1 - t,
					current = getCurrentSegment(this)._point,
					handle = through.subtract(current.multiply(t1 * t1))
						.subtract(to.multiply(t * t)).divide(2 * t * t1);
				if (handle.isNaN())
					throw new Error(
						'Cannot put a curve through points with parameter = ' + t);
				this.quadraticCurveTo(handle, to);
			},

			arcTo: function() {
				var current = getCurrentSegment(this),
					from = current._point,
					to = Point.read(arguments),
					through,
					peek = Base.peek(arguments),
					clockwise = Base.pick(peek, true),
					center, extent, vector, matrix;
				if (typeof clockwise === 'boolean') {
					var middle = from.add(to).divide(2),
					through = middle.add(middle.subtract(from).rotate(
							clockwise ? -90 : 90));
				} else if (Base.remain(arguments) <= 2) {
					through = to;
					to = Point.read(arguments);
				} else {
					var radius = Size.read(arguments),
						isZero = Numerical.isZero;
					if (isZero(radius.width) || isZero(radius.height))
						return this.lineTo(to);
					var rotation = Base.read(arguments),
						clockwise = !!Base.read(arguments),
						large = !!Base.read(arguments),
						middle = from.add(to).divide(2),
						pt = from.subtract(middle).rotate(-rotation),
						x = pt.x,
						y = pt.y,
						abs = Math.abs,
						rx = abs(radius.width),
						ry = abs(radius.height),
						rxSq = rx * rx,
						rySq = ry * ry,
						xSq = x * x,
						ySq = y * y;
					var factor = Math.sqrt(xSq / rxSq + ySq / rySq);
					if (factor > 1) {
						rx *= factor;
						ry *= factor;
						rxSq = rx * rx;
						rySq = ry * ry;
					}
					factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /
							(rxSq * ySq + rySq * xSq);
					if (abs(factor) < 1e-12)
						factor = 0;
					if (factor < 0)
						throw new Error(
								'Cannot create an arc with the given arguments');
					center = new Point(rx * y / ry, -ry * x / rx)
							.multiply((large === clockwise ? -1 : 1)
								* Math.sqrt(factor))
							.rotate(rotation).add(middle);
					matrix = new Matrix().translate(center).rotate(rotation)
							.scale(rx, ry);
					vector = matrix._inverseTransform(from);
					extent = vector.getDirectedAngle(matrix._inverseTransform(to));
					if (!clockwise && extent > 0)
						extent -= 360;
					else if (clockwise && extent < 0)
						extent += 360;
				}
				if (through) {
					var l1 = new Line(from.add(through).divide(2),
								through.subtract(from).rotate(90), true),
						l2 = new Line(through.add(to).divide(2),
								to.subtract(through).rotate(90), true),
						line = new Line(from, to),
						throughSide = line.getSide(through);
					center = l1.intersect(l2, true);
					if (!center) {
						if (!throughSide)
							return this.lineTo(to);
						throw new Error(
								'Cannot create an arc with the given arguments');
					}
					vector = from.subtract(center);
					extent = vector.getDirectedAngle(to.subtract(center));
					var centerSide = line.getSide(center);
					if (centerSide === 0) {
						extent = throughSide * Math.abs(extent);
					} else if (throughSide === centerSide) {
						extent += extent < 0 ? 360 : -360;
					}
				}
				var ext = Math.abs(extent),
					count = ext >= 360 ? 4 : Math.ceil(ext / 90),
					inc = extent / count,
					half = inc * Math.PI / 360,
					z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),
					segments = [];
				for (var i = 0; i <= count; i++) {
					var pt = to,
						out = null;
					if (i < count) {
						out = vector.rotate(90).multiply(z);
						if (matrix) {
							pt = matrix._transformPoint(vector);
							out = matrix._transformPoint(vector.add(out))
									.subtract(pt);
						} else {
							pt = center.add(vector);
						}
					}
					if (i === 0) {
						current.setHandleOut(out);
					} else {
						var _in = vector.rotate(-90).multiply(z);
						if (matrix) {
							_in = matrix._transformPoint(vector.add(_in))
									.subtract(pt);
						}
						segments.push(new Segment(pt, _in, out));
					}
					vector = vector.rotate(inc);
				}
				this._add(segments);
			},

			lineBy: function() {
				var to = Point.read(arguments),
					current = getCurrentSegment(this)._point;
				this.lineTo(current.add(to));
			},

			curveBy: function() {
				var through = Point.read(arguments),
					to = Point.read(arguments),
					parameter = Base.read(arguments),
					current = getCurrentSegment(this)._point;
				this.curveTo(current.add(through), current.add(to), parameter);
			},

			cubicCurveBy: function() {
				var handle1 = Point.read(arguments),
					handle2 = Point.read(arguments),
					to = Point.read(arguments),
					current = getCurrentSegment(this)._point;
				this.cubicCurveTo(current.add(handle1), current.add(handle2),
						current.add(to));
			},

			quadraticCurveBy: function() {
				var handle = Point.read(arguments),
					to = Point.read(arguments),
					current = getCurrentSegment(this)._point;
				this.quadraticCurveTo(current.add(handle), current.add(to));
			},

			arcBy: function() {
				var current = getCurrentSegment(this)._point,
					point = current.add(Point.read(arguments)),
					clockwise = Base.pick(Base.peek(arguments), true);
				if (typeof clockwise === 'boolean') {
					this.arcTo(point, clockwise);
				} else {
					this.arcTo(point, current.add(Point.read(arguments)));
				}
			},

			closePath: function(tolerance) {
				this.setClosed(true);
				this.join(this, tolerance);
			}
		};
	}, {

		_getBounds: function(matrix, options) {
			var method = options.handle
					? 'getHandleBounds'
					: options.stroke
					? 'getStrokeBounds'
					: 'getBounds';
			return Path[method](this._segments, this._closed, this, matrix, options);
		},

	statics: {
		getBounds: function(segments, closed, path, matrix, options, strokePadding) {
			var first = segments[0];
			if (!first)
				return new Rectangle();
			var coords = new Array(6),
				prevCoords = first._transformCoordinates(matrix, new Array(6)),
				min = prevCoords.slice(0, 2),
				max = min.slice(),
				roots = new Array(2);

			function processSegment(segment) {
				segment._transformCoordinates(matrix, coords);
				for (var i = 0; i < 2; i++) {
					Curve._addBounds(
						prevCoords[i],
						prevCoords[i + 4],
						coords[i + 2],
						coords[i],
						i, strokePadding ? strokePadding[i] : 0, min, max, roots);
				}
				var tmp = prevCoords;
				prevCoords = coords;
				coords = tmp;
			}

			for (var i = 1, l = segments.length; i < l; i++)
				processSegment(segments[i]);
			if (closed)
				processSegment(first);
			return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
		},

		getStrokeBounds: function(segments, closed, path, matrix, options) {
			var style = path.getStyle(),
				stroke = style.hasStroke(),
				strokeWidth = style.getStrokeWidth(),
				strokeMatrix = stroke && path._getStrokeMatrix(matrix, options),
				strokePadding = stroke && Path._getStrokePadding(strokeWidth,
					strokeMatrix),
				bounds = Path.getBounds(segments, closed, path, matrix, options,
					strokePadding);
			if (!stroke)
				return bounds;
			var strokeRadius = strokeWidth / 2,
				join = style.getStrokeJoin(),
				cap = style.getStrokeCap(),
				miterLimit = strokeRadius * style.getMiterLimit(),
				joinBounds = new Rectangle(new Size(strokePadding));

			function addPoint(point) {
				bounds = bounds.include(point);
			}

			function addRound(segment) {
				bounds = bounds.unite(
						joinBounds.setCenter(segment._point.transform(matrix)));
			}

			function addJoin(segment, join) {
				var handleIn = segment._handleIn,
					handleOut = segment._handleOut;
				if (join === 'round' || !handleIn.isZero() && !handleOut.isZero()
						&& handleIn.isCollinear(handleOut)) {
					addRound(segment);
				} else {
					Path._addBevelJoin(segment, join, strokeRadius, miterLimit,
							matrix, strokeMatrix, addPoint);
				}
			}

			function addCap(segment, cap) {
				if (cap === 'round') {
					addRound(segment);
				} else {
					Path._addSquareCap(segment, cap, strokeRadius, matrix,
							strokeMatrix, addPoint);
				}
			}

			var length = segments.length - (closed ? 0 : 1);
			for (var i = 1; i < length; i++)
				addJoin(segments[i], join);
			if (closed) {
				addJoin(segments[0], join);
			} else if (length > 0) {
				addCap(segments[0], cap);
				addCap(segments[segments.length - 1], cap);
			}
			return bounds;
		},

		_getStrokePadding: function(radius, matrix) {
			if (!matrix)
				return [radius, radius];
			var hor = new Point(radius, 0).transform(matrix),
				ver = new Point(0, radius).transform(matrix),
				phi = hor.getAngleInRadians(),
				a = hor.getLength(),
				b = ver.getLength();
			var sin = Math.sin(phi),
				cos = Math.cos(phi),
				tan = Math.tan(phi),
				tx = Math.atan2(b * tan, a),
				ty = Math.atan2(b, tan * a);
			return [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),
					Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];
		},

		_addBevelJoin: function(segment, join, radius, miterLimit, matrix,
				strokeMatrix, addPoint, isArea) {
			var curve2 = segment.getCurve(),
				curve1 = curve2.getPrevious(),
				point = curve2.getPointAtTime(0),
				normal1 = curve1.getNormalAtTime(1),
				normal2 = curve2.getNormalAtTime(0),
				step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
			normal1.setLength(step);
			normal2.setLength(step);
			if (matrix)
				matrix._transformPoint(point, point);
			if (strokeMatrix) {
				strokeMatrix._transformPoint(normal1, normal1);
				strokeMatrix._transformPoint(normal2, normal2);
			}
			if (isArea) {
				addPoint(point);
				addPoint(point.add(normal1));
			}
			if (join === 'miter') {
				var corner = new Line(point.add(normal1),
						new Point(-normal1.y, normal1.x), true
					).intersect(new Line(point.add(normal2),
						new Point(-normal2.y, normal2.x), true
					), true);
				if (corner && point.getDistance(corner) <= miterLimit) {
					addPoint(corner);
					if (!isArea)
						return;
				}
			}
			if (!isArea)
				addPoint(point.add(normal1));
			addPoint(point.add(normal2));
		},

		_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,
				addPoint, isArea) {
			var point = segment._point,
				loc = segment.getLocation(),
				normal = loc.getNormal().multiply(radius);
			if (matrix)
				matrix._transformPoint(point, point);
			if (strokeMatrix)
				strokeMatrix._transformPoint(normal, normal);
			if (isArea) {
				addPoint(point.subtract(normal));
				addPoint(point.add(normal));
			}
			if (cap === 'square') {
				point = point.add(normal.rotate(
						loc.getTime() === 0 ? -90 : 90));
			}
			addPoint(point.add(normal));
			addPoint(point.subtract(normal));
		},

		getHandleBounds: function(segments, closed, path, matrix, options) {
			var style = path.getStyle(),
				stroke = options.stroke && style.hasStroke(),
				strokePadding,
				joinPadding;
			if (stroke) {
				var strokeMatrix = path._getStrokeMatrix(matrix, options),
					strokeRadius = style.getStrokeWidth() / 2,
					joinRadius = strokeRadius;
				if (style.getStrokeJoin() === 'miter')
					joinRadius = strokeRadius * style.getMiterLimit();
				if (style.getStrokeCap() === 'square')
					joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
				strokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);
				joinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);
			}
			var coords = new Array(6),
				x1 = Infinity,
				x2 = -x1,
				y1 = x1,
				y2 = x2;
			for (var i = 0, l = segments.length; i < l; i++) {
				var segment = segments[i];
				segment._transformCoordinates(matrix, coords);
				for (var j = 0; j < 6; j += 2) {
					var padding = j === 0 ? joinPadding : strokePadding,
						paddingX = padding ? padding[0] : 0,
						paddingY = padding ? padding[1] : 0,
						x = coords[j],
						y = coords[j + 1],
						xn = x - paddingX,
						xx = x + paddingX,
						yn = y - paddingY,
						yx = y + paddingY;
					if (xn < x1) x1 = xn;
					if (xx > x2) x2 = xx;
					if (yn < y1) y1 = yn;
					if (yx > y2) y2 = yx;
				}
			}
			return new Rectangle(x1, y1, x2 - x1, y2 - y1);
		}
	}});

	Path.inject({ statics: new function() {

		var kappa = 0.5522847498307936,
			ellipseSegments = [
				new Segment([-1, 0], [0, kappa ], [0, -kappa]),
				new Segment([0, -1], [-kappa, 0], [kappa, 0 ]),
				new Segment([1, 0], [0, -kappa], [0, kappa ]),
				new Segment([0, 1], [kappa, 0 ], [-kappa, 0])
			];

		function createPath(segments, closed, args) {
			var props = Base.getNamed(args),
				path = new Path(props && props.insert === false && Item.NO_INSERT);
			path._add(segments);
			path._closed = closed;
			return path.set(props);
		}

		function createEllipse(center, radius, args) {
			var segments = new Array(4);
			for (var i = 0; i < 4; i++) {
				var segment = ellipseSegments[i];
				segments[i] = new Segment(
					segment._point.multiply(radius).add(center),
					segment._handleIn.multiply(radius),
					segment._handleOut.multiply(radius)
				);
			}
			return createPath(segments, true, args);
		}

		return {
			Line: function() {
				return createPath([
					new Segment(Point.readNamed(arguments, 'from')),
					new Segment(Point.readNamed(arguments, 'to'))
				], false, arguments);
			},

			Circle: function() {
				var center = Point.readNamed(arguments, 'center'),
					radius = Base.readNamed(arguments, 'radius');
				return createEllipse(center, new Size(radius), arguments);
			},

			Rectangle: function() {
				var rect = Rectangle.readNamed(arguments, 'rectangle'),
					radius = Size.readNamed(arguments, 'radius', 0,
							{ readNull: true }),
					bl = rect.getBottomLeft(true),
					tl = rect.getTopLeft(true),
					tr = rect.getTopRight(true),
					br = rect.getBottomRight(true),
					segments;
				if (!radius || radius.isZero()) {
					segments = [
						new Segment(bl),
						new Segment(tl),
						new Segment(tr),
						new Segment(br)
					];
				} else {
					radius = Size.min(radius, rect.getSize(true).divide(2));
					var rx = radius.width,
						ry = radius.height,
						hx = rx * kappa,
						hy = ry * kappa;
					segments = [
						new Segment(bl.add(rx, 0), null, [-hx, 0]),
						new Segment(bl.subtract(0, ry), [0, hy]),
						new Segment(tl.add(0, ry), null, [0, -hy]),
						new Segment(tl.add(rx, 0), [-hx, 0], null),
						new Segment(tr.subtract(rx, 0), null, [hx, 0]),
						new Segment(tr.add(0, ry), [0, -hy], null),
						new Segment(br.subtract(0, ry), null, [0, hy]),
						new Segment(br.subtract(rx, 0), [hx, 0])
					];
				}
				return createPath(segments, true, arguments);
			},

			RoundRectangle: '#Rectangle',

			Ellipse: function() {
				var ellipse = Shape._readEllipse(arguments);
				return createEllipse(ellipse.center, ellipse.radius, arguments);
			},

			Oval: '#Ellipse',

			Arc: function() {
				var from = Point.readNamed(arguments, 'from'),
					through = Point.readNamed(arguments, 'through'),
					to = Point.readNamed(arguments, 'to'),
					props = Base.getNamed(arguments),
					path = new Path(props && props.insert === false
							&& Item.NO_INSERT);
				path.moveTo(from);
				path.arcTo(through, to);
				return path.set(props);
			},

			RegularPolygon: function() {
				var center = Point.readNamed(arguments, 'center'),
					sides = Base.readNamed(arguments, 'sides'),
					radius = Base.readNamed(arguments, 'radius'),
					step = 360 / sides,
					three = sides % 3 === 0,
					vector = new Point(0, three ? -radius : radius),
					offset = three ? -1 : 0.5,
					segments = new Array(sides);
				for (var i = 0; i < sides; i++)
					segments[i] = new Segment(center.add(
						vector.rotate((i + offset) * step)));
				return createPath(segments, true, arguments);
			},

			Star: function() {
				var center = Point.readNamed(arguments, 'center'),
					points = Base.readNamed(arguments, 'points') * 2,
					radius1 = Base.readNamed(arguments, 'radius1'),
					radius2 = Base.readNamed(arguments, 'radius2'),
					step = 360 / points,
					vector = new Point(0, -1),
					segments = new Array(points);
				for (var i = 0; i < points; i++)
					segments[i] = new Segment(center.add(vector.rotate(step * i)
							.multiply(i % 2 ? radius2 : radius1)));
				return createPath(segments, true, arguments);
			}
		};
	}});

	var CompoundPath = PathItem.extend({
		_class: 'CompoundPath',
		_serializeFields: {
			children: []
		},

		initialize: function CompoundPath(arg) {
			this._children = [];
			this._namedChildren = {};
			if (!this._initialize(arg)) {
				if (typeof arg === 'string') {
					this.setPathData(arg);
				} else {
					this.addChildren(Array.isArray(arg) ? arg : arguments);
				}
			}
		},

		insertChildren: function insertChildren(index, items, _preserve) {
			for (var i = items.length - 1; i >= 0; i--) {
				var item = items[i];
				if (item instanceof CompoundPath) {
					items = items.slice();
					items.splice.apply(items, [i, 1].concat(item.removeChildren()));
					item.remove();
				}
			}
			items = insertChildren.base.call(this, index, items, _preserve, Path);
			for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
				var item = items[i];
				if (item._clockwise === undefined)
					item.setClockwise(item._index === 0);
			}
			return items;
		},

		reduce: function reduce(options) {
			var children = this._children;
			for (var i = children.length - 1; i >= 0; i--) {
				var path = children[i].reduce(options);
				if (path.isEmpty())
					path.remove();
			}
			if (children.length === 0) {
				var path = new Path(Item.NO_INSERT);
				path.copyAttributes(this);
				path.insertAbove(this);
				this.remove();
				return path;
			}
			return reduce.base.call(this);
		},

		isClockwise: function() {
			var child = this.getFirstChild();
			return child && child.isClockwise();
		},

		setClockwise: function(clockwise) {
			if (this.isClockwise() ^ !!clockwise)
				this.reverse();
		},

		getFirstSegment: function() {
			var first = this.getFirstChild();
			return first && first.getFirstSegment();
		},

		getLastSegment: function() {
			var last = this.getLastChild();
			return last && last.getLastSegment();
		},

		getCurves: function() {
			var children = this._children,
				curves = [];
			for (var i = 0, l = children.length; i < l; i++)
				curves.push.apply(curves, children[i].getCurves());
			return curves;
		},

		getFirstCurve: function() {
			var first = this.getFirstChild();
			return first && first.getFirstCurve();
		},

		getLastCurve: function() {
			var last = this.getLastChild();
			return last && last.getFirstCurve();
		},

		getArea: function() {
			var children = this._children,
				area = 0;
			for (var i = 0, l = children.length; i < l; i++)
				area += children[i].getArea();
			return area;
		}
	}, {
		beans: true,

		getPathData: function(_matrix, _precision) {
			var children = this._children,
				paths = [];
			for (var i = 0, l = children.length; i < l; i++) {
				var child = children[i],
					mx = child._matrix;
				paths.push(child.getPathData(_matrix && !mx.isIdentity()
						? _matrix.appended(mx) : _matrix, _precision));
			}
			return paths.join(' ');
		}
	}, {
		_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {
			return _hitTestChildren.base.call(this, point,
					options.class === Path || options.type === 'path' ? options
						: Base.set({}, options, { fill: false }),
					viewMatrix);
		},

		_draw: function(ctx, param, viewMatrix, strokeMatrix) {
			var children = this._children;
			if (children.length === 0)
				return;

			param = param.extend({ dontStart: true, dontFinish: true });
			ctx.beginPath();
			for (var i = 0, l = children.length; i < l; i++)
				children[i].draw(ctx, param, strokeMatrix);

			if (!param.clip) {
				this._setStyles(ctx, param, viewMatrix);
				var style = this._style;
				if (style.hasFill()) {
					ctx.fill(style.getFillRule());
					ctx.shadowColor = 'rgba(0,0,0,0)';
				}
				if (style.hasStroke())
					ctx.stroke();
			}
		},

		_drawSelected: function(ctx, matrix, selectionItems) {
			var children = this._children;
			for (var i = 0, l = children.length; i < l; i++) {
				var child = children[i],
					mx = child._matrix;
				if (!selectionItems[child._id]) {
					child._drawSelected(ctx, mx.isIdentity() ? matrix
							: matrix.appended(mx));
				}
			}
		}
	},
	new function() {
		function getCurrentPath(that, check) {
			var children = that._children;
			if (check && children.length === 0)
				throw new Error('Use a moveTo() command first');
			return children[children.length - 1];
		}

		return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
				'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
				'arcBy'],
			function(key) {
				this[key] = function() {
					var path = getCurrentPath(this, true);
					path[key].apply(path, arguments);
				};
			}, {
				moveTo: function() {
					var current = getCurrentPath(this),
						path = current && current.isEmpty() ? current
								: new Path(Item.NO_INSERT);
					if (path !== current)
						this.addChild(path);
					path.moveTo.apply(path, arguments);
				},

				moveBy: function() {
					var current = getCurrentPath(this, true),
						last = current && current.getLastSegment(),
						point = Point.read(arguments);
					this.moveTo(last ? point.add(last._point) : point);
				},

				closePath: function(tolerance) {
					getCurrentPath(this, true).closePath(tolerance);
				}
			}
		);
	}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
		this[key] = function(param) {
			var children = this._children,
				res;
			for (var i = 0, l = children.length; i < l; i++) {
				res = children[i][key](param) || res;
			}
			return res;
		};
	}, {}));

	PathItem.inject(new function() {
		var operators = {
			unite:     { 1: true },
			intersect: { 2: true },
			subtract:  { 1: true },
			exclude:   { 1: true }
		};

		function preparePath(path, resolve) {
			var res = path.clone(false).reduce({ simplify: true })
					.transform(null, true, true);
			return resolve ? res.resolveCrossings() : res;
		}

		function createResult(ctor, paths, reduce, path1, path2) {
			var result = new ctor(Item.NO_INSERT);
			result.addChildren(paths, true);
			if (reduce)
				result = result.reduce({ simplify: true });
			result.insertAbove(path2 && path1.isSibling(path2)
					&& path1.getIndex() < path2.getIndex() ? path2 : path1);
			result.copyAttributes(path1, true);
			return result;
		}

		function computeBoolean(path1, path2, operation) {
			var operator = operators[operation];
			operator[operation] = true;
			if (!path1._children && !path1._closed)
				return computeOpenBoolean(path1, path2, operator);
			var _path1 = preparePath(path1, true),
				_path2 = path2 && path1 !== path2 && preparePath(path2, true);
			if (_path2 && (operator.subtract || operator.exclude)
					^ (_path2.isClockwise() ^ _path1.isClockwise()))
				_path2.reverse();
			var crossings = divideLocations(
					CurveLocation.expand(_path1.getCrossings(_path2))),
				segments = [],
				monoCurves = [];

			function collect(paths) {
				for (var i = 0, l = paths.length; i < l; i++) {
					var path = paths[i];
					segments.push.apply(segments, path._segments);
					monoCurves.push.apply(monoCurves, path._getMonoCurves());
					path._overlapsOnly = path._validOverlapsOnly = true;
				}
			}

			collect(_path1._children || [_path1]);
			if (_path2)
				collect(_path2._children || [_path2]);
			for (var i = 0, l = crossings.length; i < l; i++) {
				propagateWinding(crossings[i]._segment, _path1, _path2, monoCurves,
						operator);
			}
			for (var i = 0, l = segments.length; i < l; i++) {
				var segment = segments[i],
					inter = segment._intersection;
				if (segment._winding == null) {
					propagateWinding(segment, _path1, _path2, monoCurves, operator);
				}
				if (!(inter && inter._overlap)) {
					var path = segment._path;
					path._overlapsOnly = false;
					if (operator[segment._winding])
						path._validOverlapsOnly = false;
				}
			}
			return createResult(CompoundPath, tracePaths(segments, operator), true,
						path1, path2);
		}

		function computeOpenBoolean(path1, path2, operator) {
			if (!path2 || !path2._children && !path2._closed
					|| !operator.subtract && !operator.intersect)
				return null;
			var _path1 = preparePath(path1, false),
				_path2 = preparePath(path2, false),
				crossings = _path1.getCrossings(_path2),
				sub = operator.subtract,
				paths = [];

			function addPath(path) {
				if (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {
					paths.unshift(path);
					return true;
				}
			}

			for (var i = crossings.length - 1; i >= 0; i--) {
				var path = crossings[i].split();
				if (path) {
					if (addPath(path))
						path.getFirstSegment().setHandleIn(0, 0);
					_path1.getLastSegment().setHandleOut(0, 0);
				}
			}
			addPath(_path1);
			return createResult(Group, paths, false, path1, path2);
		}

		function linkIntersections(from, to) {
			var prev = from;
			while (prev) {
				if (prev === to)
					return;
				prev = prev._previous;
			}
			while (from._next && from._next !== to)
				from = from._next;
			if (!from._next) {
				while (to._previous)
					to = to._previous;
				from._next = to;
				to._previous = from;
			}
		}

		function divideLocations(locations, include) {
			var results = include && [],
				tMin = 4e-7,
				tMax = 1 - tMin,
				noHandles = false,
				clearCurves = [],
				prevCurve,
				prevTime;

			for (var i = locations.length - 1; i >= 0; i--) {
				var loc = locations[i];
				if (include) {
					if (!include(loc))
						continue;
					results.unshift(loc);
				}
				var curve = loc._curve,
					time = loc._time,
					origTime = time,
					segment;
				if (curve !== prevCurve) {
					noHandles = !curve.hasHandles();
				} else if (prevTime >= tMin && prevTime <= tMax ) {
					time /= prevTime;
				}
				if (time < tMin) {
					segment = curve._segment1;
				} else if (time > tMax) {
					segment = curve._segment2;
				} else {
					var newCurve = curve.divideAtTime(time, true);
					if (noHandles)
						clearCurves.push(curve, newCurve);
					segment = newCurve._segment1;
				}
				loc._setSegment(segment);
				var inter = segment._intersection,
					dest = loc._intersection;
				if (inter) {
					linkIntersections(inter, dest);
					var other = inter;
					while (other) {
						linkIntersections(other._intersection, inter);
						other = other._next;
					}
				} else {
					segment._intersection = dest;
				}
				prevCurve = curve;
				prevTime = origTime;
			}
			for (var i = 0, l = clearCurves.length; i < l; i++) {
				clearCurves[i].clearHandles();
			}
			return results || locations;
		}

		function getWinding(point, curves, horizontal) {
			var epsilon = 2e-7,
				px = point.x,
				py = point.y,
				windLeft = 0,
				windRight = 0,
				length = curves.length,
				roots = [],
				abs = Math.abs;
			if (horizontal) {
				var yTop = -Infinity,
					yBottom = Infinity,
					yBefore = py - epsilon,
					yAfter = py + epsilon;
				for (var i = 0; i < length; i++) {
					var values = curves[i].values,
						count = Curve.solveCubic(values, 0, px, roots, 0, 1);
					for (var j = count - 1; j >= 0; j--) {
						var y = Curve.getPoint(values, roots[j]).y;
						if (y < yBefore && y > yTop) {
							yTop = y;
						} else if (y > yAfter && y < yBottom) {
							yBottom = y;
						}
					}
				}
				yTop = (yTop + py) / 2;
				yBottom = (yBottom + py) / 2;
				if (yTop > -Infinity)
					windLeft = getWinding(new Point(px, yTop), curves).winding;
				if (yBottom < Infinity)
					windRight = getWinding(new Point(px, yBottom), curves).winding;
			} else {
				var xBefore = px - epsilon,
					xAfter = px + epsilon,
					prevWinding,
					prevXEnd,
					windLeftOnCurve = 0,
					windRightOnCurve = 0,
					isOnCurve = false;
				for (var i = 0; i < length; i++) {
					var curve = curves[i],
						winding = curve.winding,
						values = curve.values,
						yStart = values[1],
						yEnd = values[7];
					if (curve.last) {
						prevWinding = curve.last.winding;
						prevXEnd = curve.last.values[6];
						isOnCurve = false;
					}
					if (py >= yStart && py <= yEnd || py >= yEnd && py <= yStart) {
						if (winding) {
							var x = py === yStart ? values[0]
								: py === yEnd ? values[6]
								: Curve.solveCubic(values, 1, py, roots, 0, 1) === 1
								? Curve.getPoint(values, roots[0]).x
								: null;
							if (x != null) {
								if (x >= xBefore && x <= xAfter) {
									isOnCurve = true;
								} else if (
									(py !== yStart || winding !== prevWinding)
									&& !(py === yStart
										&& (px - x) * (px - prevXEnd) < 0)) {
									if (x < xBefore) {
										windLeft += winding;
									} else if (x > xAfter) {
										windRight += winding;
									}
								}
							}
							prevWinding = winding;
							prevXEnd = values[6];
						} else if ((px - values[0]) * (px - values[6]) <= 0) {
							isOnCurve = true;
						}
					}
					if (isOnCurve && (i >= length - 1 || curves[i + 1].last)) {
						windLeftOnCurve += 1;
						windRightOnCurve -= 1;
					}
				}
				if (windLeft === 0 && windRight === 0) {
					windLeft = windLeftOnCurve;
					windRight = windRightOnCurve;
				}
			}
			return {
				winding: Math.max(abs(windLeft), abs(windRight)),
				contour: !windLeft ^ !windRight
			};
		}

		function propagateWinding(segment, path1, path2, monoCurves, operator) {
			var chain = [],
				start = segment,
				totalLength = 0,
				winding;
			do {
				var curve = segment.getCurve(),
					length = curve.getLength();
				chain.push({ segment: segment, curve: curve, length: length });
				totalLength += length;
				segment = segment.getNext();
			} while (segment && !segment._intersection && segment !== start);
			var length = totalLength / 2;
			for (var j = 0, l = chain.length; j < l; j++) {
				var entry = chain[j],
					curveLength = entry.length;
				if (length <= curveLength) {
					var curve = entry.curve,
						path = curve._path,
						parent = path._parent,
						t = curve.getTimeAt(length),
						pt = curve.getPointAtTime(t),
						hor = Math.abs(curve.getTangentAtTime(t).y)
								< 1e-7;
					if (parent instanceof CompoundPath)
						path = parent;
					winding = !(operator.subtract && path2 && (
							path === path1 &&  path2._getWinding(pt, hor) ||
							path === path2 && !path1._getWinding(pt, hor)))
								? getWinding(pt, monoCurves, hor)
								: { winding: 0 };
					 break;
				}
				length -= curveLength;
			}
			for (var j = chain.length - 1; j >= 0; j--) {
				var seg = chain[j].segment;
				seg._winding = winding.winding;
				seg._contour = winding.contour;
			}
		}

		function tracePaths(segments, operator) {
			var paths = [],
				start,
				otherStart;

			function isValid(seg, excludeContour) {
				return !!(seg && !seg._visited && (!operator
						|| operator[seg._winding]
						|| !excludeContour && operator.unite && seg._contour));
			}

			function isStart(seg) {
				return seg === start || seg === otherStart;
			}

			function findBestIntersection(inter, exclude) {
				if (!inter._next)
					return inter;
				while (inter) {
					var seg = inter._segment,
						nextSeg = seg.getNext(),
						nextInter = nextSeg && nextSeg._intersection;
					if (seg !== exclude && (isStart(seg) || isStart(nextSeg)
						|| !seg._visited && !nextSeg._visited
						&& (!operator || isValid(seg) && (isValid(nextSeg)
							|| nextInter && isValid(nextInter._segment)))
						))
						return inter;
					inter = inter._next;
				}
				return null;
			}

			for (var i = 0, l = segments.length; i < l; i++) {
				var path = null,
					finished = false,
					seg = segments[i],
					inter = seg._intersection,
					handleIn;
				if (!seg._visited && seg._path._overlapsOnly) {
					var path1 = seg._path,
						path2 = inter._segment._path,
						segments1 = path1._segments,
						segments2 = path2._segments;
					if (Base.equals(segments1, segments2)) {
						if ((operator.unite || operator.intersect)
								&& path1.getArea()) {
							paths.push(path1.clone(false));
						}
						for (var j = 0, k = segments1.length; j < k; j++) {
							segments1[j]._visited = segments2[j]._visited = true;
						}
					}
				}
				if (!isValid(seg, true)
						|| !seg._path._validOverlapsOnly && inter && inter._overlap)
					continue;
				start = otherStart = null;
				while (true) {
					inter = inter && findBestIntersection(inter, seg) || inter;
					var other = inter && inter._segment;
					if (isStart(seg)) {
						finished = true;
					} else if (other) {
						if (isStart(other)) {
							finished = true;
							seg = other;
						} else if (isValid(other, isValid(seg, true))) {
							if (operator
									&& (operator.intersect || operator.subtract)) {
								seg._visited = true;
							}
							seg = other;
						}
					}
					if (finished || seg._visited) {
						seg._visited = true;
						break;
					}
					if (seg._path._validOverlapsOnly && !isValid(seg))
						break;
					if (!path) {
						path = new Path(Item.NO_INSERT);
						start = seg;
						otherStart = other;
					}
					var next = seg.getNext();
					path.add(new Segment(seg._point, handleIn,
							next && seg._handleOut));
					seg._visited = true;
					seg = next || seg._path.getFirstSegment();
					handleIn = next && next._handleIn;
					inter = seg._intersection;
				}
				if (finished) {
					path.firstSegment.setHandleIn(handleIn);
					path.setClosed(true);
				} else if (path) {
					var area = path.getArea(true);
					if (Math.abs(area) >= 2e-7) {
						console.error('Boolean operation resulted in open path',
								'segments =', path._segments.length,
								'length =', path.getLength(),
								'area=', area);
					}
					path = null;
				}
				if (path && (path._segments.length > 8
						|| !Numerical.isZero(path.getArea()))) {
					paths.push(path);
					path = null;
				}
			}
			return paths;
		}

		return {
			_getWinding: function(point, horizontal) {
				return getWinding(point, this._getMonoCurves(), horizontal).winding;
			},

			unite: function(path) {
				return computeBoolean(this, path, 'unite');
			},

			intersect: function(path) {
				return computeBoolean(this, path, 'intersect');
			},

			subtract: function(path) {
				return computeBoolean(this, path, 'subtract');
			},

			exclude: function(path) {
				return computeBoolean(this, path, 'exclude');
			},

			divide: function(path) {
				return createResult(Group, [this.subtract(path),
						this.intersect(path)], true, this, path);
			},

			resolveCrossings: function() {
				var children = this._children,
					paths = children || [this];

				function hasOverlap(seg) {
					var inter = seg && seg._intersection;
					return inter && inter._overlap;
				}

				var hasOverlaps = false,
					hasCrossings = false,
					intersections = this.getIntersections(null, function(inter) {
						return inter._overlap && (hasOverlaps = true)
								|| inter.isCrossing() && (hasCrossings = true);
					});
				intersections = CurveLocation.expand(intersections);
				if (hasOverlaps) {
					var overlaps = divideLocations(intersections, function(inter) {
						return inter._overlap;
					});
					for (var i = overlaps.length - 1; i >= 0; i--) {
						var seg = overlaps[i]._segment,
							prev = seg.getPrevious(),
							next = seg.getNext();
						if (seg._path && hasOverlap(prev) && hasOverlap(next)) {
							seg.remove();
							prev._handleOut.set(0, 0);
							next._handleIn.set(0, 0);
							var curve = prev.getCurve();
							if (curve.isStraight() && curve.getLength() === 0)
								prev.remove();
						}
					}
				}
				if (hasCrossings) {
					divideLocations(intersections, hasOverlaps && function(inter) {
						var curve1 = inter.getCurve(),
							curve2 = inter._intersection._curve,
							seg = inter._segment;
						if (curve1 && curve2 && curve1._path && curve2._path) {
							return true;
						} else if (seg) {
							seg._intersection = null;
						}
					});
					paths = tracePaths(Base.each(paths, function(path) {
						this.push.apply(this, path._segments);
					}, []));
				}
				var length = paths.length,
					item;
				if (length > 1) {
					paths = paths.slice().sort(function (a, b) {
						return b.getBounds().getArea() - a.getBounds().getArea();
					});
					var first = paths[0],
						items = [first],
						excluded = {},
						isNonZero = this.getFillRule() === 'nonzero',
						windings = isNonZero && Base.each(paths, function(path) {
							this.push(path.isClockwise() ? 1 : -1);
						}, []);
					for (var i = 1; i < length; i++) {
						var path = paths[i],
							point = path.getInteriorPoint(),
							isContained = false,
							container = null,
							exclude = false;
						for (var j = i - 1; j >= 0 && !container; j--) {
							if (paths[j].contains(point)) {
								if (isNonZero && !isContained) {
									windings[i] += windings[j];
									if (windings[i] && windings[j]) {
										exclude = excluded[i] = true;
										break;
									}
								}
								isContained = true;
								container = !excluded[j] && paths[j];
							}
						}
						if (!exclude) {
							path.setClockwise(container ? !container.isClockwise()
									: first.isClockwise());
							items.push(path);
						}
					}
					paths = items;
					length = items.length;
				}
				if (length > 1 && children) {
					if (paths !== children) {
						this.setChildren(paths, true);
					}
					item = this;
				} else if (length === 1 && !children) {
					if (paths[0] !== this)
						this.setSegments(paths[0].removeSegments());
					item = this;
				}
				if (!item) {
					item = new CompoundPath(Item.NO_INSERT);
					item.addChildren(paths, true);
					item = item.reduce();
					item.copyAttributes(this);
					this.replaceWith(item);
				}
				return item;
			}
		};
	});

	Path.inject({
		_getMonoCurves: function() {
			var monoCurves = this._monoCurves,
				last;

			function insertCurve(v) {
				var y0 = v[1],
					y1 = v[7],
					winding = Math.abs((y0 - y1) / (v[0] - v[6]))
							< 2e-7
						? 0
						: y0 > y1
							? -1
							: 1,
					curve = { values: v, winding: winding };
				monoCurves.push(curve);
				if (winding)
					last = curve;
			}

			function handleCurve(v) {
				if (Curve.getLength(v) === 0)
					return;
				var y0 = v[1],
					y1 = v[3],
					y2 = v[5],
					y3 = v[7];
				if (Curve.isStraight(v)
						|| y0 >= y1 === y1 >= y2 && y1 >= y2 === y2 >= y3) {
					insertCurve(v);
				} else {
					var a = 3 * (y1 - y2) - y0 + y3,
						b = 2 * (y0 + y2) - 4 * y1,
						c = y1 - y0,
						tMin = 4e-7,
						tMax = 1 - tMin,
						roots = [],
						n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
					if (n < 1) {
						insertCurve(v);
					} else {
						roots.sort();
						var t = roots[0],
							parts = Curve.subdivide(v, t);
						insertCurve(parts[0]);
						if (n > 1) {
							t = (roots[1] - t) / (1 - t);
							parts = Curve.subdivide(parts[1], t);
							insertCurve(parts[0]);
						}
						insertCurve(parts[1]);
					}
				}
			}

			if (!monoCurves) {
				monoCurves = this._monoCurves = [];
				var curves = this.getCurves(),
					segments = this._segments;
				for (var i = 0, l = curves.length; i < l; i++)
					handleCurve(curves[i].getValues());
				if (!this._closed && segments.length > 1) {
					var p1 = segments[segments.length - 1]._point,
						p2 = segments[0]._point,
						p1x = p1._x, p1y = p1._y,
						p2x = p2._x, p2y = p2._y;
					handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
				}
				if (monoCurves.length > 0) {
					monoCurves[0].last = last;
				}
			}
			return monoCurves;
		},

		getInteriorPoint: function() {
			var bounds = this.getBounds(),
				point = bounds.getCenter(true);
			if (!this.contains(point)) {
				var curves = this._getMonoCurves(),
					roots = [],
					y = point.y,
					intercepts = [];
				for (var i = 0, l = curves.length; i < l; i++) {
					var values = curves[i].values;
					if (curves[i].winding === 1
							&& y > values[1] && y <= values[7]
							|| y >= values[7] && y < values[1]) {
						var count = Curve.solveCubic(values, 1, y, roots, 0, 1);
						for (var j = count - 1; j >= 0; j--) {
							intercepts.push(Curve.getPoint(values, roots[j]).x);
						}
					}
				}
				intercepts.sort(function(a, b) { return a - b; });
				point.x = (intercepts[0] + intercepts[1]) / 2;
			}
			return point;
		}
	});

	CompoundPath.inject({
		_getMonoCurves: function() {
			var children = this._children,
				monoCurves = [];
			for (var i = 0, l = children.length; i < l; i++)
				monoCurves.push.apply(monoCurves, children[i]._getMonoCurves());
			return monoCurves;
		}
	});

	var PathIterator = Base.extend({
		_class: 'PathIterator',

		initialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {
			var curves = [],
				parts = [],
				length = 0,
				minSpan = 1 / (maxRecursion || 32),
				segments = path._segments,
				segment1 = segments[0],
				segment2;

			function addCurve(segment1, segment2) {
				var curve = Curve.getValues(segment1, segment2, matrix);
				curves.push(curve);
				computeParts(curve, segment1._index, 0, 1);
			}

			function computeParts(curve, index, t1, t2) {
				if ((t2 - t1) > minSpan
						&& !(ignoreStraight && Curve.isStraight(curve))
						&& !Curve.isFlatEnough(curve, flatness || 0.25)) {
					var halves = Curve.subdivide(curve, 0.5),
						tMid = (t1 + t2) / 2;
					computeParts(halves[0], index, t1, tMid);
					computeParts(halves[1], index, tMid, t2);
				} else {
					var dx = curve[6] - curve[0],
						dy = curve[7] - curve[1],
						dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 0) {
						length += dist;
						parts.push({
							offset: length,
							curve: curve,
							index: index,
							time: t2,
						});
					}
				}
			}

			for (var i = 1, l = segments.length; i < l; i++) {
				segment2 = segments[i];
				addCurve(segment1, segment2);
				segment1 = segment2;
			}
			if (path._closed)
				addCurve(segment2, segments[0]);
			this.curves = curves;
			this.parts = parts;
			this.length = length;
			this.index = 0;
		},

		_get: function(offset) {
			var i, j = this.index;
			for (;;) {
				i = j;
				if (j === 0 || this.parts[--j].offset < offset)
					break;
			}
			for (var l = this.parts.length; i < l; i++) {
				var part = this.parts[i];
				if (part.offset >= offset) {
					this.index = i;
					var prev = this.parts[i - 1];
					var prevTime = prev && prev.index === part.index ? prev.time : 0,
						prevOffset = prev ? prev.offset : 0;
					return {
						index: part.index,
						time: prevTime + (part.time - prevTime)
							* (offset - prevOffset) / (part.offset - prevOffset)
					};
				}
			}
			var part = this.parts[this.parts.length - 1];
			return {
				index: part.index,
				time: 1
			};
		},

		drawPart: function(ctx, from, to) {
			var start = this._get(from),
				end = this._get(to);
			for (var i = start.index, l = end.index; i <= l; i++) {
				var curve = Curve.getPart(this.curves[i],
						i === start.index ? start.time : 0,
						i === end.index ? end.time : 1);
				if (i === start.index)
					ctx.moveTo(curve[0], curve[1]);
				ctx.bezierCurveTo.apply(ctx, curve.slice(2));
			}
		}
	}, Base.each(Curve._evaluateMethods,
		function(name) {
			this[name + 'At'] = function(offset) {
				var param = this._get(offset);
				return Curve[name](this.curves[param.index], param.time);
			};
		}, {})
	);

	var PathFitter = Base.extend({
		initialize: function(path) {
			var points = this.points = [],
				segments = path._segments,
				closed = path._closed;
			for (var i = 0, prev, l = segments.length; i < l; i++) {
				var point = segments[i].point;
				if (!prev || !prev.equals(point)) {
					points.push(prev = point.clone());
				}
			}
			if (closed) {
				points.unshift(points[points.length - 1]);
				points.push(points[1]);
			}
			this.closed = closed;
		},

		fit: function(error) {
			var points = this.points,
				length = points.length,
				segments = null;
			if (length > 0) {
				segments = [new Segment(points[0])];
				if (length > 1) {
					this.fitCubic(segments, error, 0, length - 1,
							points[1].subtract(points[0]),
							points[length - 2].subtract(points[length - 1]));
					if (this.closed) {
						segments.shift();
						segments.pop();
					}
				}
			}
			return segments;
		},

		fitCubic: function(segments, error, first, last, tan1, tan2) {
			var points = this.points;
			if (last - first === 1) {
				var pt1 = points[first],
					pt2 = points[last],
					dist = pt1.getDistance(pt2) / 3;
				this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
						pt2.add(tan2.normalize(dist)), pt2]);
				return;
			}
			var uPrime = this.chordLengthParameterize(first, last),
				maxError = Math.max(error, error * error),
				split,
				parametersInOrder = true;
			for (var i = 0; i <= 4; i++) {
				var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
				var max = this.findMaxError(first, last, curve, uPrime);
				if (max.error < error && parametersInOrder) {
					this.addCurve(segments, curve);
					return;
				}
				split = max.index;
				if (max.error >= maxError)
					break;
				parametersInOrder = this.reparameterize(first, last, uPrime, curve);
				maxError = max.error;
			}
			var tanCenter = points[split - 1].subtract(points[split + 1]);
			this.fitCubic(segments, error, first, split, tan1, tanCenter);
			this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
		},

		addCurve: function(segments, curve) {
			var prev = segments[segments.length - 1];
			prev.setHandleOut(curve[1].subtract(curve[0]));
			segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
		},

		generateBezier: function(first, last, uPrime, tan1, tan2) {
			var epsilon = 1e-12,
				abs = Math.abs,
				points = this.points,
				pt1 = points[first],
				pt2 = points[last],
				C = [[0, 0], [0, 0]],
				X = [0, 0];

			for (var i = 0, l = last - first + 1; i < l; i++) {
				var u = uPrime[i],
					t = 1 - u,
					b = 3 * u * t,
					b0 = t * t * t,
					b1 = b * t,
					b2 = b * u,
					b3 = u * u * u,
					a1 = tan1.normalize(b1),
					a2 = tan2.normalize(b2),
					tmp = points[first + i]
						.subtract(pt1.multiply(b0 + b1))
						.subtract(pt2.multiply(b2 + b3));
				C[0][0] += a1.dot(a1);
				C[0][1] += a1.dot(a2);
				C[1][0] = C[0][1];
				C[1][1] += a2.dot(a2);
				X[0] += a1.dot(tmp);
				X[1] += a2.dot(tmp);
			}

			var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
				alpha1, alpha2;
			if (abs(detC0C1) > epsilon) {
				var detC0X = C[0][0] * X[1]    - C[1][0] * X[0],
					detXC1 = X[0]    * C[1][1] - X[1]    * C[0][1];
				alpha1 = detXC1 / detC0C1;
				alpha2 = detC0X / detC0C1;
			} else {
				var c0 = C[0][0] + C[0][1],
					c1 = C[1][0] + C[1][1];
				if (abs(c0) > epsilon) {
					alpha1 = alpha2 = X[0] / c0;
				} else if (abs(c1) > epsilon) {
					alpha1 = alpha2 = X[1] / c1;
				} else {
					alpha1 = alpha2 = 0;
				}
			}

			var segLength = pt2.getDistance(pt1),
				eps = epsilon * segLength,
				handle1,
				handle2;
			if (alpha1 < eps || alpha2 < eps) {
				alpha1 = alpha2 = segLength / 3;
			} else {
				var line = pt2.subtract(pt1);
				handle1 = tan1.normalize(alpha1);
				handle2 = tan2.normalize(alpha2);
				if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {
					alpha1 = alpha2 = segLength / 3;
					handle1 = handle2 = null;
				}
			}

			return [pt1,
					pt1.add(handle1 || tan1.normalize(alpha1)),
					pt2.add(handle2 || tan2.normalize(alpha2)),
					pt2];
		},

		reparameterize: function(first, last, u, curve) {
			for (var i = first; i <= last; i++) {
				u[i - first] = this.findRoot(curve, this.points[i], u[i - first]);
			}
			for (var i = 1, l = u.length; i < l; i++) {
				if (u[i] <= u[i - 1])
					return false;
			}
			return true;
		},

		findRoot: function(curve, point, u) {
			var curve1 = [],
				curve2 = [];
			for (var i = 0; i <= 2; i++) {
				curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);
			}
			for (var i = 0; i <= 1; i++) {
				curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);
			}
			var pt = this.evaluate(3, curve, u),
				pt1 = this.evaluate(2, curve1, u),
				pt2 = this.evaluate(1, curve2, u),
				diff = pt.subtract(point),
				df = pt1.dot(pt1) + diff.dot(pt2);
			if (Math.abs(df) < 1e-6)
				return u;
			return u - diff.dot(pt1) / df;
		},

		evaluate: function(degree, curve, t) {
			var tmp = curve.slice();
			for (var i = 1; i <= degree; i++) {
				for (var j = 0; j <= degree - i; j++) {
					tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));
				}
			}
			return tmp[0];
		},

		chordLengthParameterize: function(first, last) {
			var u = [0];
			for (var i = first + 1; i <= last; i++) {
				u[i - first] = u[i - first - 1]
						+ this.points[i].getDistance(this.points[i - 1]);
			}
			for (var i = 1, m = last - first; i <= m; i++) {
				u[i] /= u[m];
			}
			return u;
		},

		findMaxError: function(first, last, curve, u) {
			var index = Math.floor((last - first + 1) / 2),
				maxDist = 0;
			for (var i = first + 1; i < last; i++) {
				var P = this.evaluate(3, curve, u[i - first]);
				var v = P.subtract(this.points[i]);
				var dist = v.x * v.x + v.y * v.y;
				if (dist >= maxDist) {
					maxDist = dist;
					index = i;
				}
			}
			return {
				error: maxDist,
				index: index
			};
		}
	});

	var TextItem = Item.extend({
		_class: 'TextItem',
		_applyMatrix: false,
		_canApplyMatrix: false,
		_serializeFields: {
			content: null
		},
		_boundsOptions: { stroke: false, handle: false },

		initialize: function TextItem(arg) {
			this._content = '';
			this._lines = [];
			var hasProps = arg && Base.isPlainObject(arg)
					&& arg.x === undefined && arg.y === undefined;
			this._initialize(hasProps && arg, !hasProps && Point.read(arguments));
		},

		_equals: function(item) {
			return this._content === item._content;
		},

		copyContent: function(source) {
			this.setContent(source._content);
		},

		getContent: function() {
			return this._content;
		},

		setContent: function(content) {
			this._content = '' + content;
			this._lines = this._content.split(/\r\n|\n|\r/mg);
			this._changed(265);
		},

		isEmpty: function() {
			return !this._content;
		},

		getCharacterStyle: '#getStyle',
		setCharacterStyle: '#setStyle',

		getParagraphStyle: '#getStyle',
		setParagraphStyle: '#setStyle'
	});

	var PointText = TextItem.extend({
		_class: 'PointText',

		initialize: function PointText() {
			TextItem.apply(this, arguments);
		},

		getPoint: function() {
			var point = this._matrix.getTranslation();
			return new LinkedPoint(point.x, point.y, this, 'setPoint');
		},

		setPoint: function() {
			var point = Point.read(arguments);
			this.translate(point.subtract(this._matrix.getTranslation()));
		},

		_draw: function(ctx, param, viewMatrix) {
			if (!this._content)
				return;
			this._setStyles(ctx, param, viewMatrix);
			var lines = this._lines,
				style = this._style,
				hasFill = style.hasFill(),
				hasStroke = style.hasStroke(),
				leading = style.getLeading(),
				shadowColor = ctx.shadowColor;
			ctx.font = style.getFontStyle();
			ctx.textAlign = style.getJustification();
			for (var i = 0, l = lines.length; i < l; i++) {
				ctx.shadowColor = shadowColor;
				var line = lines[i];
				if (hasFill) {
					ctx.fillText(line, 0, 0);
					ctx.shadowColor = 'rgba(0,0,0,0)';
				}
				if (hasStroke)
					ctx.strokeText(line, 0, 0);
				ctx.translate(0, leading);
			}
		},

		_getBounds: function(matrix, options) {
			var style = this._style,
				lines = this._lines,
				numLines = lines.length,
				justification = style.getJustification(),
				leading = style.getLeading(),
				width = this.getView().getTextWidth(style.getFontStyle(), lines),
				x = 0;
			if (justification !== 'left')
				x -= width / (justification === 'center' ? 2: 1);
			var bounds = new Rectangle(x,
						numLines ? - 0.75 * leading : 0,
						width, numLines * leading);
			return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
		}
	});

	var Color = Base.extend(new function() {
		var types = {
			gray: ['gray'],
			rgb: ['red', 'green', 'blue'],
			hsb: ['hue', 'saturation', 'brightness'],
			hsl: ['hue', 'saturation', 'lightness'],
			gradient: ['gradient', 'origin', 'destination', 'highlight']
		};

		var componentParsers = {},
			colorCache = {},
			colorCtx;

		function fromCSS(string) {
			var match = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})$/),
				components;
			if (match) {
				components = [0, 0, 0];
				for (var i = 0; i < 3; i++) {
					var value = match[i + 1];
					components[i] = parseInt(value.length == 1
							? value + value : value, 16) / 255;
				}
			} else if (match = string.match(/^rgba?\((.*)\)$/)) {
				components = match[1].split(',');
				for (var i = 0, l = components.length; i < l; i++) {
					var value = +components[i];
					components[i] = i < 3 ? value / 255 : value;
				}
			} else if (window) {
				var cached = colorCache[string];
				if (!cached) {
					if (!colorCtx) {
						colorCtx = CanvasProvider.getContext(1, 1);
						colorCtx.globalCompositeOperation = 'copy';
					}
					colorCtx.fillStyle = 'rgba(0,0,0,0)';
					colorCtx.fillStyle = string;
					colorCtx.fillRect(0, 0, 1, 1);
					var data = colorCtx.getImageData(0, 0, 1, 1).data;
					cached = colorCache[string] = [
						data[0] / 255,
						data[1] / 255,
						data[2] / 255
					];
				}
				components = cached.slice();
			} else {
				components = [0, 0, 0];
			}
			return components;
		}

		var hsbIndices = [
			[0, 3, 1],
			[2, 0, 1],
			[1, 0, 3],
			[1, 2, 0],
			[3, 1, 0],
			[0, 1, 2]
		];

		var converters = {
			'rgb-hsb': function(r, g, b) {
				var max = Math.max(r, g, b),
					min = Math.min(r, g, b),
					delta = max - min,
					h = delta === 0 ? 0
						:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
							: max == g ? (b - r) / delta + 2
							:            (r - g) / delta + 4) * 60;
				return [h, max === 0 ? 0 : delta / max, max];
			},

			'hsb-rgb': function(h, s, b) {
				h = (((h / 60) % 6) + 6) % 6;
				var i = Math.floor(h),
					f = h - i,
					i = hsbIndices[i],
					v = [
						b,
						b * (1 - s),
						b * (1 - s * f),
						b * (1 - s * (1 - f))
					];
				return [v[i[0]], v[i[1]], v[i[2]]];
			},

			'rgb-hsl': function(r, g, b) {
				var max = Math.max(r, g, b),
					min = Math.min(r, g, b),
					delta = max - min,
					achromatic = delta === 0,
					h = achromatic ? 0
						:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
							: max == g ? (b - r) / delta + 2
							:            (r - g) / delta + 4) * 60,
					l = (max + min) / 2,
					s = achromatic ? 0 : l < 0.5
							? delta / (max + min)
							: delta / (2 - max - min);
				return [h, s, l];
			},

			'hsl-rgb': function(h, s, l) {
				h = (((h / 360) % 1) + 1) % 1;
				if (s === 0)
					return [l, l, l];
				var t3s = [ h + 1 / 3, h, h - 1 / 3 ],
					t2 = l < 0.5 ? l * (1 + s) : l + s - l * s,
					t1 = 2 * l - t2,
					c = [];
				for (var i = 0; i < 3; i++) {
					var t3 = t3s[i];
					if (t3 < 0) t3 += 1;
					if (t3 > 1) t3 -= 1;
					c[i] = 6 * t3 < 1
						? t1 + (t2 - t1) * 6 * t3
						: 2 * t3 < 1
							? t2
							: 3 * t3 < 2
								? t1 + (t2 - t1) * ((2 / 3) - t3) * 6
								: t1;
				}
				return c;
			},

			'rgb-gray': function(r, g, b) {
				return [r * 0.2989 + g * 0.587 + b * 0.114];
			},

			'gray-rgb': function(g) {
				return [g, g, g];
			},

			'gray-hsb': function(g) {
				return [0, 0, g];
			},

			'gray-hsl': function(g) {
				return [0, 0, g];
			},

			'gradient-rgb': function() {
				return [];
			},

			'rgb-gradient': function() {
				return [];
			}

		};

		return Base.each(types, function(properties, type) {
			componentParsers[type] = [];
			Base.each(properties, function(name, index) {
				var part = Base.capitalize(name),
					hasOverlap = /^(hue|saturation)$/.test(name),
					parser = componentParsers[type][index] = name === 'gradient'
						? function(value) {
							var current = this._components[0];
							value = Gradient.read(Array.isArray(value) ? value
									: arguments, 0, { readNull: true });
							if (current !== value) {
								if (current)
									current._removeOwner(this);
								if (value)
									value._addOwner(this);
							}
							return value;
						}
						: type === 'gradient'
							? function() {
								return Point.read(arguments, 0, {
										readNull: name === 'highlight',
										clone: true
								});
							}
							: function(value) {
								return value == null || isNaN(value) ? 0 : value;
							};

				this['get' + part] = function() {
					return this._type === type
						|| hasOverlap && /^hs[bl]$/.test(this._type)
							? this._components[index]
							: this._convert(type)[index];
				};

				this['set' + part] = function(value) {
					if (this._type !== type
							&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {
						this._components = this._convert(type);
						this._properties = types[type];
						this._type = type;
					}
					this._components[index] = parser.call(this, value);
					this._changed();
				};
			}, this);
		}, {
			_class: 'Color',
			_readIndex: true,

			initialize: function Color(arg) {
				var slice = Array.prototype.slice,
					args = arguments,
					reading = this.__read,
					read = 0,
					type,
					components,
					alpha,
					values;
				if (Array.isArray(arg)) {
					args = arg;
					arg = args[0];
				}
				var argType = arg != null && typeof arg;
				if (argType === 'string' && arg in types) {
					type = arg;
					arg = args[1];
					if (Array.isArray(arg)) {
						components = arg;
						alpha = args[2];
					} else {
						if (reading)
							read = 1;
						args = slice.call(args, 1);
						argType = typeof arg;
					}
				}
				if (!components) {
					values = argType === 'number'
							? args
							: argType === 'object' && arg.length != null
								? arg
								: null;
					if (values) {
						if (!type)
							type = values.length >= 3
									? 'rgb'
									: 'gray';
						var length = types[type].length;
						alpha = values[length];
						if (reading) {
							read += values === arguments
								? length + (alpha != null ? 1 : 0)
								: 1;
						}
						if (values.length > length)
							values = slice.call(values, 0, length);
					} else if (argType === 'string') {
						type = 'rgb';
						components = fromCSS(arg);
						if (components.length === 4) {
							alpha = components[3];
							components.length--;
						}
					} else if (argType === 'object') {
						if (arg.constructor === Color) {
							type = arg._type;
							components = arg._components.slice();
							alpha = arg._alpha;
							if (type === 'gradient') {
								for (var i = 1, l = components.length; i < l; i++) {
									var point = components[i];
									if (point)
										components[i] = point.clone();
								}
							}
						} else if (arg.constructor === Gradient) {
							type = 'gradient';
							values = args;
						} else {
							type = 'hue' in arg
								? 'lightness' in arg
									? 'hsl'
									: 'hsb'
								: 'gradient' in arg || 'stops' in arg
										|| 'radial' in arg
									? 'gradient'
									: 'gray' in arg
										? 'gray'
										: 'rgb';
							var properties = types[type],
								parsers = componentParsers[type];
							this._components = components = [];
							for (var i = 0, l = properties.length; i < l; i++) {
								var value = arg[properties[i]];
								if (value == null && i === 0 && type === 'gradient'
										&& 'stops' in arg) {
									value = {
										stops: arg.stops,
										radial: arg.radial
									};
								}
								value = parsers[i].call(this, value);
								if (value != null)
									components[i] = value;
							}
							alpha = arg.alpha;
						}
					}
					if (reading && type)
						read = 1;
				}
				this._type = type || 'rgb';
				if (!components) {
					this._components = components = [];
					var parsers = componentParsers[this._type];
					for (var i = 0, l = parsers.length; i < l; i++) {
						var value = parsers[i].call(this, values && values[i]);
						if (value != null)
							components[i] = value;
					}
				}
				this._components = components;
				this._properties = types[this._type];
				this._alpha = alpha;
				if (reading)
					this.__read = read;
			},

			_set: '#initialize',

			_serialize: function(options, dictionary) {
				var components = this.getComponents();
				return Base.serialize(
						/^(gray|rgb)$/.test(this._type)
							? components
							: [this._type].concat(components),
						options, true, dictionary);
			},

			_changed: function() {
				this._canvasStyle = null;
				if (this._owner)
					this._owner._changed(65);
			},

			_convert: function(type) {
				var converter;
				return this._type === type
						? this._components.slice()
						: (converter = converters[this._type + '-' + type])
							? converter.apply(this, this._components)
							: converters['rgb-' + type].apply(this,
								converters[this._type + '-rgb'].apply(this,
									this._components));
			},

			convert: function(type) {
				return new Color(type, this._convert(type), this._alpha);
			},

			getType: function() {
				return this._type;
			},

			setType: function(type) {
				this._components = this._convert(type);
				this._properties = types[type];
				this._type = type;
			},

			getComponents: function() {
				var components = this._components.slice();
				if (this._alpha != null)
					components.push(this._alpha);
				return components;
			},

			getAlpha: function() {
				return this._alpha != null ? this._alpha : 1;
			},

			setAlpha: function(alpha) {
				this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);
				this._changed();
			},

			hasAlpha: function() {
				return this._alpha != null;
			},

			equals: function(color) {
				var col = Base.isPlainValue(color, true)
						? Color.read(arguments)
						: color;
				return col === this || col && this._class === col._class
						&& this._type === col._type
						&& this._alpha === col._alpha
						&& Base.equals(this._components, col._components)
						|| false;
			},

			toString: function() {
				var properties = this._properties,
					parts = [],
					isGradient = this._type === 'gradient',
					f = Formatter.instance;
				for (var i = 0, l = properties.length; i < l; i++) {
					var value = this._components[i];
					if (value != null)
						parts.push(properties[i] + ': '
								+ (isGradient ? value : f.number(value)));
				}
				if (this._alpha != null)
					parts.push('alpha: ' + f.number(this._alpha));
				return '{ ' + parts.join(', ') + ' }';
			},

			toCSS: function(hex) {
				var components = this._convert('rgb'),
					alpha = hex || this._alpha == null ? 1 : this._alpha;
				function convert(val) {
					return Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);
				}
				components = [
					convert(components[0]),
					convert(components[1]),
					convert(components[2])
				];
				if (alpha < 1)
					components.push(alpha < 0 ? 0 : alpha);
				return hex
						? '#' + ((1 << 24) + (components[0] << 16)
							+ (components[1] << 8)
							+ components[2]).toString(16).slice(1)
						: (components.length == 4 ? 'rgba(' : 'rgb(')
							+ components.join(',') + ')';
			},

			toCanvasStyle: function(ctx) {
				if (this._canvasStyle)
					return this._canvasStyle;
				if (this._type !== 'gradient')
					return this._canvasStyle = this.toCSS();
				var components = this._components,
					gradient = components[0],
					stops = gradient._stops,
					origin = components[1],
					destination = components[2],
					canvasGradient;
				if (gradient._radial) {
					var radius = destination.getDistance(origin),
						highlight = components[3];
					if (highlight) {
						var vector = highlight.subtract(origin);
						if (vector.getLength() > radius)
							highlight = origin.add(vector.normalize(radius - 0.1));
					}
					var start = highlight || origin;
					canvasGradient = ctx.createRadialGradient(start.x, start.y,
							0, origin.x, origin.y, radius);
				} else {
					canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
							destination.x, destination.y);
				}
				for (var i = 0, l = stops.length; i < l; i++) {
					var stop = stops[i];
					canvasGradient.addColorStop(stop._offset || i / (l - 1),
							stop._color.toCanvasStyle());
				}
				return this._canvasStyle = canvasGradient;
			},

			transform: function(matrix) {
				if (this._type === 'gradient') {
					var components = this._components;
					for (var i = 1, l = components.length; i < l; i++) {
						var point = components[i];
						matrix._transformPoint(point, point, true);
					}
					this._changed();
				}
			},

			statics: {
				_types: types,

				random: function() {
					var random = Math.random;
					return new Color(random(), random(), random());
				}
			}
		});
	},
	new function() {
		var operators = {
			add: function(a, b) {
				return a + b;
			},

			subtract: function(a, b) {
				return a - b;
			},

			multiply: function(a, b) {
				return a * b;
			},

			divide: function(a, b) {
				return a / b;
			}
		};

		return Base.each(operators, function(operator, name) {
			this[name] = function(color) {
				color = Color.read(arguments);
				var type = this._type,
					components1 = this._components,
					components2 = color._convert(type);
				for (var i = 0, l = components1.length; i < l; i++)
					components2[i] = operator(components1[i], components2[i]);
				return new Color(type, components2,
						this._alpha != null
								? operator(this._alpha, color.getAlpha())
								: null);
			};
		}, {
		});
	});

	var Gradient = Base.extend({
		_class: 'Gradient',

		initialize: function Gradient(stops, radial) {
			this._id = UID.get();
			if (stops && this._set(stops))
				stops = radial = null;
			if (!this._stops)
				this.setStops(stops || ['white', 'black']);
			if (this._radial == null) {
				this.setRadial(typeof radial === 'string' && radial === 'radial'
						|| radial || false);
			}
		},

		_serialize: function(options, dictionary) {
			return dictionary.add(this, function() {
				return Base.serialize([this._stops, this._radial],
						options, true, dictionary);
			});
		},

		_changed: function() {
			for (var i = 0, l = this._owners && this._owners.length; i < l; i++) {
				this._owners[i]._changed();
			}
		},

		_addOwner: function(color) {
			if (!this._owners)
				this._owners = [];
			this._owners.push(color);
		},

		_removeOwner: function(color) {
			var index = this._owners ? this._owners.indexOf(color) : -1;
			if (index != -1) {
				this._owners.splice(index, 1);
				if (this._owners.length === 0)
					this._owners = undefined;
			}
		},

		clone: function() {
			var stops = [];
			for (var i = 0, l = this._stops.length; i < l; i++) {
				stops[i] = this._stops[i].clone();
			}
			return new Gradient(stops, this._radial);
		},

		getStops: function() {
			return this._stops;
		},

		setStops: function(stops) {
			if (stops.length < 2) {
				throw new Error(
						'Gradient stop list needs to contain at least two stops.');
			}
			var _stops = this._stops;
			if (_stops) {
				for (var i = 0, l = _stops.length; i < l; i++)
					_stops[i]._owner = undefined;
			}
			_stops = this._stops = GradientStop.readAll(stops, 0, { clone: true });
			for (var i = 0, l = _stops.length; i < l; i++)
				_stops[i]._owner = this;
			this._changed();
		},

		getRadial: function() {
			return this._radial;
		},

		setRadial: function(radial) {
			this._radial = radial;
			this._changed();
		},

		equals: function(gradient) {
			if (gradient === this)
				return true;
			if (gradient && this._class === gradient._class) {
				var stops1 = this._stops,
					stops2 = gradient._stops,
					length = stops1.length;
				if (length === stops2.length) {
					for (var i = 0; i < length; i++) {
						if (!stops1[i].equals(stops2[i]))
							return false;
					}
					return true;
				}
			}
			return false;
		}
	});

	var GradientStop = Base.extend({
		_class: 'GradientStop',

		initialize: function GradientStop(arg0, arg1) {
			var color = arg0,
				offset = arg1;
			if (typeof arg0 === 'object' && arg1 === undefined) {
				if (Array.isArray(arg0) && typeof arg0[0] !== 'number') {
					color = arg0[0];
					offset = arg0[1];
				} else if ('color' in arg0 || 'offset' in arg0
						|| 'rampPoint' in arg0) {
					color = arg0.color;
					offset = arg0.offset || arg0.rampPoint || 0;
				}
			}
			this.setColor(color);
			this.setOffset(offset);
		},

		clone: function() {
			return new GradientStop(this._color.clone(), this._offset);
		},

		_serialize: function(options, dictionary) {
			var color = this._color,
				offset = this._offset;
			return Base.serialize(offset == null ? [color] : [color, offset],
					options, true, dictionary);
		},

		_changed: function() {
			if (this._owner)
				this._owner._changed(65);
		},

		getOffset: function() {
			return this._offset;
		},

		setOffset: function(offset) {
			this._offset = offset;
			this._changed();
		},

		getRampPoint: '#getOffset',
		setRampPoint: '#setOffset',

		getColor: function() {
			return this._color;
		},

		setColor: function() {
			var color = Color.read(arguments, 0, { clone: true });
			if (color)
				color._owner = this;
			this._color = color;
			this._changed();
		},

		equals: function(stop) {
			return stop === this || stop && this._class === stop._class
					&& this._color.equals(stop._color)
					&& this._offset == stop._offset
					|| false;
		}
	});

	var Style = Base.extend(new function() {
		var itemDefaults = {
			fillColor: null,
			fillRule: 'nonzero',
			strokeColor: null,
			strokeWidth: 1,
			strokeCap: 'butt',
			strokeJoin: 'miter',
			strokeScaling: true,
			miterLimit: 10,
			dashOffset: 0,
			dashArray: [],
			shadowColor: null,
			shadowBlur: 0,
			shadowOffset: new Point(),
			selectedColor: null
		},
		groupDefaults = Base.set({}, itemDefaults, {
			fontFamily: 'sans-serif',
			fontWeight: 'normal',
			fontSize: 12,
			leading: null,
			justification: 'left'
		}),
		textDefaults = Base.set({}, groupDefaults, {
			fillColor: new Color()
		}),
		flags = {
			strokeWidth: 97,
			strokeCap: 97,
			strokeJoin: 97,
			strokeScaling: 105,
			miterLimit: 97,
			fontFamily: 9,
			fontWeight: 9,
			fontSize: 9,
			font: 9,
			leading: 9,
			justification: 9
		},
		item = {
			beans: true
		},
		fields = {
			_class: 'Style',
			beans: true,

			initialize: function Style(style, owner, project) {
				this._values = {};
				this._owner = owner;
				this._project = owner && owner._project || project || paper.project;
				this._defaults = !owner || owner instanceof Group ? groupDefaults
						: owner instanceof TextItem ? textDefaults
						: itemDefaults;
				if (style)
					this.set(style);
			}
		};

		Base.each(groupDefaults, function(value, key) {
			var isColor = /Color$/.test(key),
				isPoint = key === 'shadowOffset',
				part = Base.capitalize(key),
				flag = flags[key],
				set = 'set' + part,
				get = 'get' + part;

			fields[set] = function(value) {
				var owner = this._owner,
					children = owner && owner._children;
				if (children && children.length > 0
						&& !(owner instanceof CompoundPath)) {
					for (var i = 0, l = children.length; i < l; i++)
						children[i]._style[set](value);
				} else if (key in this._defaults) {
					var old = this._values[key];
					if (old !== value) {
						if (isColor) {
							if (old && old._owner !== undefined)
								old._owner = undefined;
							if (value && value.constructor === Color) {
								if (value._owner)
									value = value.clone();
								value._owner = owner;
							}
						}
						this._values[key] = value;
						if (owner)
							owner._changed(flag || 65);
					}
				}
			};

			fields[get] = function(_dontMerge) {
				var owner = this._owner,
					children = owner && owner._children,
					value;
				if (key in this._defaults && (!children || children.length === 0
						|| _dontMerge || owner instanceof CompoundPath)) {
					var value = this._values[key];
					if (value === undefined) {
						value = this._defaults[key];
						if (value && value.clone)
							value = value.clone();
					} else {
						var ctor = isColor ? Color : isPoint ? Point : null;
						if (ctor && !(value && value.constructor === ctor)) {
							this._values[key] = value = ctor.read([value], 0,
									{ readNull: true, clone: true });
							if (value && isColor)
								value._owner = owner;
						}
					}
				} else if (children) {
					for (var i = 0, l = children.length; i < l; i++) {
						var childValue = children[i]._style[get]();
						if (i === 0) {
							value = childValue;
						} else if (!Base.equals(value, childValue)) {
							return undefined;
						}
					}
				}
				return value;
			};

			item[get] = function(_dontMerge) {
				return this._style[get](_dontMerge);
			};

			item[set] = function(value) {
				this._style[set](value);
			};
		});

		Base.each({
			Font: 'FontFamily',
			WindingRule: 'FillRule'
		}, function(value, key) {
			var get = 'get' + key,
				set = 'set' + key;
			fields[get] = item[get] = '#get' + value;
			fields[set] = item[set] = '#set' + value;
		});

		Item.inject(item);
		return fields;
	}, {
		set: function(style) {
			var isStyle = style instanceof Style,
				values = isStyle ? style._values : style;
			if (values) {
				for (var key in values) {
					if (key in this._defaults) {
						var value = values[key];
						this[key] = value && isStyle && value.clone
								? value.clone() : value;
					}
				}
			}
		},

		equals: function(style) {
			return style === this || style && this._class === style._class
					&& Base.equals(this._values, style._values)
					|| false;
		},

		hasFill: function() {
			var color = this.getFillColor();
			return !!color && color.alpha > 0;
		},

		hasStroke: function() {
			var color = this.getStrokeColor();
			return !!color && color.alpha > 0 && this.getStrokeWidth() > 0;
		},

		hasShadow: function() {
			var color = this.getShadowColor();
			return !!color && color.alpha > 0 && (this.getShadowBlur() > 0
					|| !this.getShadowOffset().isZero());
		},

		getView: function() {
			return this._project._view;
		},

		getFontStyle: function() {
			var fontSize = this.getFontSize();
			return this.getFontWeight()
					+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')
					+ this.getFontFamily();
		},

		getFont: '#getFontFamily',
		setFont: '#setFontFamily',

		getLeading: function getLeading() {
			var leading = getLeading.base.call(this),
				fontSize = this.getFontSize();
			if (/pt|em|%|px/.test(fontSize))
				fontSize = this.getView().getPixelSize(fontSize);
			return leading != null ? leading : fontSize * 1.2;
		}

	});

	var DomElement = new function() {
		function handlePrefix(el, name, set, value) {
			var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],
				suffix = name[0].toUpperCase() + name.substring(1);
			for (var i = 0; i < 6; i++) {
				var prefix = prefixes[i],
					key = prefix ? prefix + suffix : name;
				if (key in el) {
					if (set) {
						el[key] = value;
					} else {
						return el[key];
					}
					break;
				}
			}
		}

		return {
			getStyles: function(el) {
				var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
					view = doc && doc.defaultView;
				return view && view.getComputedStyle(el, '');
			},

			getBounds: function(el, viewport) {
				var doc = el.ownerDocument,
					body = doc.body,
					html = doc.documentElement,
					rect;
				try {
					rect = el.getBoundingClientRect();
				} catch (e) {
					rect = { left: 0, top: 0, width: 0, height: 0 };
				}
				var x = rect.left - (html.clientLeft || body.clientLeft || 0),
					y = rect.top - (html.clientTop || body.clientTop || 0);
				if (!viewport) {
					var view = doc.defaultView;
					x += view.pageXOffset || html.scrollLeft || body.scrollLeft;
					y += view.pageYOffset || html.scrollTop || body.scrollTop;
				}
				return new Rectangle(x, y, rect.width, rect.height);
			},

			getViewportBounds: function(el) {
				var doc = el.ownerDocument,
					view = doc.defaultView,
					html = doc.documentElement;
				return new Rectangle(0, 0,
					view.innerWidth || html.clientWidth,
					view.innerHeight || html.clientHeight
				);
			},

			getOffset: function(el, viewport) {
				return DomElement.getBounds(el, viewport).getPoint();
			},

			getSize: function(el) {
				return DomElement.getBounds(el, true).getSize();
			},

			isInvisible: function(el) {
				return DomElement.getSize(el).equals(new Size(0, 0));
			},

			isInView: function(el) {
				return !DomElement.isInvisible(el)
						&& DomElement.getViewportBounds(el).intersects(
							DomElement.getBounds(el, true));
			},

			isInserted: function(el) {
				return document.body.contains(el);
			},

			getPrefixed: function(el, name) {
				return el && handlePrefix(el, name);
			},

			setPrefixed: function(el, name, value) {
				if (typeof name === 'object') {
					for (var key in name)
						handlePrefix(el, key, true, name[key]);
				} else {
					handlePrefix(el, name, true, value);
				}
			}
		};
	};

	var DomEvent = {
		add: function(el, events) {
			if (el) {
				for (var type in events) {
					var func = events[type],
						parts = type.split(/[\s,]+/g);
					for (var i = 0, l = parts.length; i < l; i++)
						el.addEventListener(parts[i], func, false);
				}
			}
		},

		remove: function(el, events) {
			if (el) {
				for (var type in events) {
					var func = events[type],
						parts = type.split(/[\s,]+/g);
					for (var i = 0, l = parts.length; i < l; i++)
						el.removeEventListener(parts[i], func, false);
				}
			}
		},

		getPoint: function(event) {
			var pos = event.targetTouches
					? event.targetTouches.length
						? event.targetTouches[0]
						: event.changedTouches[0]
					: event;
			return new Point(
				pos.pageX || pos.clientX + document.documentElement.scrollLeft,
				pos.pageY || pos.clientY + document.documentElement.scrollTop
			);
		},

		getTarget: function(event) {
			return event.target || event.srcElement;
		},

		getRelatedTarget: function(event) {
			return event.relatedTarget || event.toElement;
		},

		getOffset: function(event, target) {
			return DomEvent.getPoint(event).subtract(DomElement.getOffset(
					target || DomEvent.getTarget(event)));
		}
	};

	DomEvent.requestAnimationFrame = new function() {
		var nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),
			requested = false,
			callbacks = [],
			timer;

		function handleCallbacks() {
			var functions = callbacks;
			callbacks = [];
			for (var i = 0, l = functions.length; i < l; i++)
				functions[i]();
			requested = nativeRequest && callbacks.length;
			if (requested)
				nativeRequest(handleCallbacks);
		}

		return function(callback) {
			callbacks.push(callback);
			if (nativeRequest) {
				if (!requested) {
					nativeRequest(handleCallbacks);
					requested = true;
				}
			} else if (!timer) {
				timer = setInterval(handleCallbacks, 1000 / 60);
			}
		};
	};

	var View = Base.extend(Emitter, {
		_class: 'View',

		initialize: function View(project, element) {

			function getSize(name) {
				return element[name] || parseInt(element.getAttribute(name), 10);
			}

			function getCanvasSize() {
				var size = DomElement.getSize(element);
				return size.isNaN() || size.isZero()
						? new Size(getSize('width'), getSize('height'))
						: size;
			}

			var size;
			if (window && element) {
				this._id = element.getAttribute('id');
				if (this._id == null)
					element.setAttribute('id', this._id = 'view-' + View._id++);
				DomEvent.add(element, this._viewEvents);
				var none = 'none';
				DomElement.setPrefixed(element.style, {
					userDrag: none,
					userSelect: none,
					touchCallout: none,
					contentZooming: none,
					tapHighlightColor: 'rgba(0,0,0,0)'
				});

				if (PaperScope.hasAttribute(element, 'resize')) {
					var that = this;
					DomEvent.add(window, this._windowEvents = {
						resize: function() {
							that.setViewSize(getCanvasSize());
						}
					});
				}

				size = getCanvasSize();

				if (PaperScope.hasAttribute(element, 'stats')
						&& typeof Stats !== 'undefined') {
					this._stats = new Stats();
					var stats = this._stats.domElement,
						style = stats.style,
						offset = DomElement.getOffset(element);
					style.position = 'absolute';
					style.left = offset.x + 'px';
					style.top = offset.y + 'px';
					document.body.appendChild(stats);
				}
			} else {
				size = new Size(element);
				element = null;
			}
			this._project = project;
			this._scope = project._scope;
			this._element = element;
			if (!this._pixelRatio)
				this._pixelRatio = window && window.devicePixelRatio || 1;
			this._setElementSize(size.width, size.height);
			this._viewSize = size;
			View._views.push(this);
			View._viewsById[this._id] = this;
			(this._matrix = new Matrix())._owner = this;
			this._zoom = 1;
			if (!View._focused)
				View._focused = this;
			this._frameItems = {};
			this._frameItemCount = 0;
			this._itemEvents = { native: {}, virtual: {} };
			this._autoUpdate = !paper.agent.node;
			this._needsUpdate = false;
		},

		remove: function() {
			if (!this._project)
				return false;
			if (View._focused === this)
				View._focused = null;
			View._views.splice(View._views.indexOf(this), 1);
			delete View._viewsById[this._id];
			var project = this._project;
			if (project._view === this)
				project._view = null;
			DomEvent.remove(this._element, this._viewEvents);
			DomEvent.remove(window, this._windowEvents);
			this._element = this._project = null;
			this.off('frame');
			this._animate = false;
			this._frameItems = {};
			return true;
		},

		_events: Base.each(
			Item._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),
			function(name) {
				this[name] = {};
			}, {
				onFrame: {
					install: function() {
						this.play();
					},

					uninstall: function() {
						this.pause();
					}
				}
			}
		),

		_animate: false,
		_time: 0,
		_count: 0,

		getAutoUpdate: function() {
			return this._autoUpdate;
		},

		setAutoUpdate: function(autoUpdate) {
			this._autoUpdate = autoUpdate;
			if (autoUpdate)
				this.requestUpdate();
		},

		update: function() {
		},

		draw: function() {
			this.update();
		},

		requestUpdate: function() {
			if (!this._requested) {
				var that = this;
				DomEvent.requestAnimationFrame(function() {
					that._requested = false;
					if (that._animate) {
						that.requestUpdate();
						var element = that._element;
						if ((!DomElement.getPrefixed(document, 'hidden')
								|| PaperScope.getAttribute(element, 'keepalive')
									=== 'true') && DomElement.isInView(element)) {
							that._handleFrame();
						}
					}
					if (that._autoUpdate)
						that.update();
				});
				this._requested = true;
			}
		},

		play: function() {
			this._animate = true;
			this.requestUpdate();
		},

		pause: function() {
			this._animate = false;
		},

		_handleFrame: function() {
			paper = this._scope;
			var now = Date.now() / 1000,
				delta = this._last ? now - this._last : 0;
			this._last = now;
			this.emit('frame', new Base({
				delta: delta,
				time: this._time += delta,
				count: this._count++
			}));
			if (this._stats)
				this._stats.update();
		},

		_animateItem: function(item, animate) {
			var items = this._frameItems;
			if (animate) {
				items[item._id] = {
					item: item,
					time: 0,
					count: 0
				};
				if (++this._frameItemCount === 1)
					this.on('frame', this._handleFrameItems);
			} else {
				delete items[item._id];
				if (--this._frameItemCount === 0) {
					this.off('frame', this._handleFrameItems);
				}
			}
		},

		_handleFrameItems: function(event) {
			for (var i in this._frameItems) {
				var entry = this._frameItems[i];
				entry.item.emit('frame', new Base(event, {
					time: entry.time += event.delta,
					count: entry.count++
				}));
			}
		},

		_changed: function() {
			this._project._changed(2049);
			this._bounds = null;
		},

		getElement: function() {
			return this._element;
		},

		getPixelRatio: function() {
			return this._pixelRatio;
		},

		getResolution: function() {
			return this._pixelRatio * 72;
		},

		getViewSize: function() {
			var size = this._viewSize;
			return new LinkedSize(size.width, size.height, this, 'setViewSize');
		},

		setViewSize: function() {
			var size = Size.read(arguments),
				width = size.width,
				height = size.height,
				delta = size.subtract(this._viewSize);
			if (delta.isZero())
				return;
			this._setElementSize(width, height);
			this._viewSize.set(width, height);
			this.emit('resize', {
				size: size,
				delta: delta
			});
			this._changed();
			if (this._autoUpdate)
				this.requestUpdate();
		},

		_setElementSize: function(width, height) {
			var element = this._element;
			if (element) {
				if (element.width !== width)
					element.width = width;
				if (element.height !== height)
					element.height = height;
			}
		},

		getBounds: function() {
			if (!this._bounds)
				this._bounds = this._matrix.inverted()._transformBounds(
						new Rectangle(new Point(), this._viewSize));
			return this._bounds;
		},

		getSize: function() {
			return this.getBounds().getSize();
		},

		getCenter: function() {
			return this.getBounds().getCenter();
		},

		setCenter: function() {
			var center = Point.read(arguments);
			this.translate(this.getCenter().subtract(center));
		},

		getZoom: function() {
			return this._zoom;
		},

		setZoom: function(zoom) {
			this.transform(new Matrix().scale(zoom / this._zoom,
				this.getCenter()));
			this._zoom = zoom;
		},

		getMatrix: function() {
			return this._matrix;
		},

		setMatrix: function() {
			var matrix = this._matrix;
			matrix.initialize.apply(matrix, arguments);
		},

		isVisible: function() {
			return DomElement.isInView(this._element);
		},

		isInserted: function() {
			return DomElement.isInserted(this._element);
		},

		getPixelSize: function(size) {
			var element = this._element,
				pixels;
			if (element) {
				var parent = element.parentNode,
					temp = document.createElement('div');
				temp.style.fontSize = size;
				parent.appendChild(temp);
				pixels = parseFloat(DomElement.getStyles(temp).fontSize);
				parent.removeChild(temp);
			} else {
				pixels = parseFloat(pixels);
			}
			return pixels;
		},

		getTextWidth: function(font, lines) {
			return 0;
		}
	}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
		var rotate = key === 'rotate';
		this[key] = function() {
			var value = (rotate ? Base : Point).read(arguments),
				center = Point.read(arguments, 0, { readNull: true });
			return this.transform(new Matrix()[key](value,
					center || this.getCenter(true)));
		};
	}, {
		translate: function() {
			var mx = new Matrix();
			return this.transform(mx.translate.apply(mx, arguments));
		},

		transform: function(matrix) {
			this._matrix.append(matrix);
		},

		scrollBy: function() {
			this.translate(Point.read(arguments).negate());
		}
	}), {

		projectToView: function() {
			return this._matrix._transformPoint(Point.read(arguments));
		},

		viewToProject: function() {
			return this._matrix._inverseTransform(Point.read(arguments));
		},

		getEventPoint: function(event) {
			return this.viewToProject(DomEvent.getOffset(event, this._element));
		},

	}, {
		statics: {
			_views: [],
			_viewsById: {},
			_id: 0,

			create: function(project, element) {
				if (document && typeof element === 'string')
					element = document.getElementById(element);
				var ctor = window ? CanvasView : View;
				return new ctor(project, element);
			}
		}
	},
	new function() {
		if (!window)
			return;
		var prevFocus,
			tempFocus,
			dragging = false,
			mouseDown = false;

		function getView(event) {
			var target = DomEvent.getTarget(event);
			return target.getAttribute && View._viewsById[
					target.getAttribute('id')];
		}

		function updateFocus() {
			var view = View._focused;
			if (!view || !view.isVisible()) {
				for (var i = 0, l = View._views.length; i < l; i++) {
					if ((view = View._views[i]).isVisible()) {
						View._focused = tempFocus = view;
						break;
					}
				}
			}
		}

		function handleMouseMove(view, event, point) {
			view._handleMouseEvent('mousemove', event, point);
		}

		var navigator = window.navigator,
			mousedown, mousemove, mouseup;
		if (navigator.pointerEnabled || navigator.msPointerEnabled) {
			mousedown = 'pointerdown MSPointerDown';
			mousemove = 'pointermove MSPointerMove';
			mouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';
		} else {
			mousedown = 'touchstart';
			mousemove = 'touchmove';
			mouseup = 'touchend touchcancel';
			if (!('ontouchstart' in window && navigator.userAgent.match(
					/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {
				mousedown += ' mousedown';
				mousemove += ' mousemove';
				mouseup += ' mouseup';
			}
		}

		var viewEvents = {},
			docEvents = {
				mouseout: function(event) {
					var view = View._focused,
						target = DomEvent.getRelatedTarget(event);
					if (view && (!target || target.nodeName === 'HTML')) {
						var offset = DomEvent.getOffset(event, view._element),
							x = offset.x,
							abs = Math.abs,
							ax = abs(x),
							max = 1 << 25,
							diff = ax - max;
						offset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;
						handleMouseMove(view, event, view.viewToProject(offset));
					}
				},

				scroll: updateFocus
			};

		viewEvents[mousedown] = function(event) {
			var view = View._focused = getView(event);
			if (!dragging) {
				dragging = true;
				view._handleMouseEvent('mousedown', event);
			}
		};

		docEvents[mousemove] = function(event) {
			var view = View._focused;
			if (!mouseDown) {
				var target = getView(event);
				if (target) {
					if (view !== target) {
						if (view)
							handleMouseMove(view, event);
						if (!prevFocus)
							prevFocus = view;
						view = View._focused = tempFocus = target;
					}
				} else if (tempFocus && tempFocus === view) {
					if (prevFocus && !prevFocus.isInserted())
						prevFocus = null;
					view = View._focused = prevFocus;
					prevFocus = null;
					updateFocus();
				}
			}
			if (view)
				handleMouseMove(view, event);
		};

		docEvents[mousedown] = function() {
			mouseDown = true;
		};

		docEvents[mouseup] = function(event) {
			var view = View._focused;
			if (view && dragging)
				view._handleMouseEvent('mouseup', event);
			mouseDown = dragging = false;
		};

		DomEvent.add(document, docEvents);

		DomEvent.add(window, {
			load: updateFocus
		});

		var called = false,
			prevented = false,
			fallbacks = {
				doubleclick: 'click',
				mousedrag: 'mousemove'
			},
			wasInView = false,
			overView,
			downPoint,
			lastPoint,
			downItem,
			overItem,
			dragItem,
			clickItem,
			clickTime,
			dblClick;

		function emitMouseEvent(obj, target, type, event, point, prevPoint,
				stopItem) {
			var stopped = false,
				mouseEvent;

			function emit(obj, type) {
				if (obj.responds(type)) {
					if (!mouseEvent) {
						mouseEvent = new MouseEvent(type, event, point,
								target || obj,
								prevPoint ? point.subtract(prevPoint) : null);
					}
					if (obj.emit(type, mouseEvent)) {
						called = true;
						if (mouseEvent.prevented)
							prevented = true;
						if (mouseEvent.stopped)
							return stopped = true;
					}
				} else {
					var fallback = fallbacks[type];
					if (fallback)
						return emit(obj, fallback);
				}
			}

			while (obj && obj !== stopItem) {
				if (emit(obj, type))
					break;
				obj = obj._parent;
			}
			return stopped;
		}

		function emitMouseEvents(view, hitItem, type, event, point, prevPoint) {
			view._project.removeOn(type);
			prevented = called = false;
			return (dragItem && emitMouseEvent(dragItem, null, type, event,
						point, prevPoint)
				|| hitItem && hitItem !== dragItem
					&& !hitItem.isDescendant(dragItem)
					&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,
						point, prevPoint, dragItem)
				|| emitMouseEvent(view, dragItem || hitItem || view, type, event,
						point, prevPoint));
		}

		var itemEventsMap = {
			mousedown: {
				mousedown: 1,
				mousedrag: 1,
				click: 1,
				doubleclick: 1
			},
			mouseup: {
				mouseup: 1,
				mousedrag: 1,
				click: 1,
				doubleclick: 1
			},
			mousemove: {
				mousedrag: 1,
				mousemove: 1,
				mouseenter: 1,
				mouseleave: 1
			}
		};

		return {
			_viewEvents: viewEvents,

			_handleMouseEvent: function(type, event, point) {
				var itemEvents = this._itemEvents,
					hitItems = itemEvents.native[type],
					nativeMove = type === 'mousemove',
					tool = this._scope.tool,
					view = this;

				function responds(type) {
					return itemEvents.virtual[type] || view.responds(type)
							|| tool && tool.responds(type);
				}

				if (nativeMove && dragging && responds('mousedrag'))
					type = 'mousedrag';
				if (!point)
					point = this.getEventPoint(event);

				var inView = this.getBounds().contains(point),
					hit = hitItems && inView && view._project.hitTest(point, {
						tolerance: 0,
						fill: true,
						stroke: true
					}),
					hitItem = hit && hit.item || null,
					handle = false,
					mouse = {};
				mouse[type.substr(5)] = true;

				if (hitItems && hitItem !== overItem) {
					if (overItem) {
						emitMouseEvent(overItem, null, 'mouseleave', event, point);
					}
					if (hitItem) {
						emitMouseEvent(hitItem, null, 'mouseenter', event, point);
					}
					overItem = hitItem;
				}
				if (wasInView ^ inView) {
					emitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',
							event, point);
					overView = inView ? this : null;
					handle = true;
				}
				if ((inView || mouse.drag) && !point.equals(lastPoint)) {
					emitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',
							event, point, lastPoint);
					handle = true;
				}
				wasInView = inView;
				if (mouse.down && inView || mouse.up && downPoint) {
					emitMouseEvents(this, hitItem, type, event, point, downPoint);
					if (mouse.down) {
						dblClick = hitItem === clickItem
							&& (Date.now() - clickTime < 300);
						downItem = clickItem = hitItem;
						dragItem = !prevented && hitItem;
						downPoint = point;
					} else if (mouse.up) {
						if (!prevented && hitItem === downItem) {
							clickTime = Date.now();
							emitMouseEvents(this, hitItem, dblClick ? 'doubleclick'
									: 'click', event, point, downPoint);
							dblClick = false;
						}
						downItem = dragItem = null;
					}
					wasInView = false;
					handle = true;
				}
				lastPoint = point;
				if (handle && tool) {
					called = tool._handleMouseEvent(type, event, point, mouse)
						|| called;
				}

				if (called && !mouse.move || mouse.down && responds('mouseup'))
					event.preventDefault();
			},

			_handleKeyEvent: function(type, event, key, character) {
				var scope = this._scope,
					tool = scope.tool,
					keyEvent;

				function emit(obj) {
					if (obj.responds(type)) {
						paper = scope;
						obj.emit(type, keyEvent = keyEvent
								|| new KeyEvent(type, event, key, character));
					}
				}

				if (this.isVisible()) {
					emit(this);
					if (tool && tool.responds(type))
						emit(tool);
				}
			},

			_countItemEvent: function(type, sign) {
				var itemEvents = this._itemEvents,
					native = itemEvents.native,
					virtual = itemEvents.virtual;
				for (var key in itemEventsMap) {
					native[key] = (native[key] || 0)
							+ (itemEventsMap[key][type] || 0) * sign;
				}
				virtual[type] = (virtual[type] || 0) + sign;
			},

			statics: {
				updateFocus: updateFocus
			}
		};
	});

	var CanvasView = View.extend({
		_class: 'CanvasView',

		initialize: function CanvasView(project, canvas) {
			if (!(canvas instanceof window.HTMLCanvasElement)) {
				var size = Size.read(arguments, 1);
				if (size.isZero())
					throw new Error(
							'Cannot create CanvasView with the provided argument: '
							+ [].slice.call(arguments, 1));
				canvas = CanvasProvider.getCanvas(size);
			}
			var ctx = this._context = canvas.getContext('2d');
			ctx.save();
			this._pixelRatio = 1;
			if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {
				var deviceRatio = window.devicePixelRatio || 1,
					backingStoreRatio = DomElement.getPrefixed(ctx,
							'backingStorePixelRatio') || 1;
				this._pixelRatio = deviceRatio / backingStoreRatio;
			}
			View.call(this, project, canvas);
			this._needsUpdate = true;
		},

		remove: function remove() {
			this._context.restore();
			return remove.base.call(this);
		},

		_setElementSize: function _setElementSize(width, height) {
			var pixelRatio = this._pixelRatio;
			_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);
			if (pixelRatio !== 1) {
				var element = this._element,
					ctx = this._context;
				if (!PaperScope.hasAttribute(element, 'resize')) {
					var style = element.style;
					style.width = width + 'px';
					style.height = height + 'px';
				}
				ctx.restore();
				ctx.save();
				ctx.scale(pixelRatio, pixelRatio);
			}
		},

		getPixelSize: function getPixelSize(size) {
			var agent = paper.agent,
				pixels;
			if (agent && agent.firefox) {
				pixels = getPixelSize.base.call(this, size);
			} else {
				var ctx = this._context,
					prevFont = ctx.font;
				ctx.font = size + ' serif';
				pixels = parseFloat(ctx.font);
				ctx.font = prevFont;
			}
			return pixels;
		},

		getTextWidth: function(font, lines) {
			var ctx = this._context,
				prevFont = ctx.font,
				width = 0;
			ctx.font = font;
			for (var i = 0, l = lines.length; i < l; i++)
				width = Math.max(width, ctx.measureText(lines[i]).width);
			ctx.font = prevFont;
			return width;
		},

		update: function() {
			if (!this._needsUpdate)
				return false;
			var project = this._project,
				ctx = this._context,
				size = this._viewSize;
			ctx.clearRect(0, 0, size.width + 1, size.height + 1);
			if (project)
				project.draw(ctx, this._matrix, this._pixelRatio);
			this._needsUpdate = false;
			return true;
		}
	});

	var Event = Base.extend({
		_class: 'Event',

		initialize: function Event(event) {
			this.event = event;
			this.type = event && event.type;
		},

		prevented: false,
		stopped: false,

		preventDefault: function() {
			this.prevented = true;
			this.event.preventDefault();
		},

		stopPropagation: function() {
			this.stopped = true;
			this.event.stopPropagation();
		},

		stop: function() {
			this.stopPropagation();
			this.preventDefault();
		},

		getTimeStamp: function() {
			return this.event.timeStamp;
		},

		getModifiers: function() {
			return Key.modifiers;
		}
	});

	var KeyEvent = Event.extend({
		_class: 'KeyEvent',

		initialize: function KeyEvent(type, event, key, character) {
			this.type = type;
			this.event = event;
			this.key = key;
			this.character = character;
		},

		toString: function() {
			return "{ type: '" + this.type
					+ "', key: '" + this.key
					+ "', character: '" + this.character
					+ "', modifiers: " + this.getModifiers()
					+ " }";
		}
	});

	var Key = new function() {
		var keyLookup = {
				'\t': 'tab',
				' ': 'space',
				'\b': 'backspace',
				'\x7f': 'delete',
				'Spacebar': 'space',
				'Del': 'delete',
				'Win': 'meta',
				'Esc': 'escape'
			},

			charLookup = {
				'tab': '\t',
				'space': ' ',
				'enter': '\r'
			},

			keyMap = {},
			charMap = {},
			metaFixMap,
			downKey,

			modifiers = new Base({
				shift: false,
				control: false,
				alt: false,
				meta: false,
				capsLock: false,
				space: false
			}).inject({
				option: {
					get: function() {
						return this.alt;
					}
				},

				command: {
					get: function() {
						var agent = paper && paper.agent;
						return agent && agent.mac ? this.meta : this.control;
					}
				}
			});

		function getKey(event) {
			var key = event.key || event.keyIdentifier;
			key = /^U\+/.test(key)
					? String.fromCharCode(parseInt(key.substr(2), 16))
					: /^Arrow[A-Z]/.test(key) ? key.substr(5)
					: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
					: key;
			return keyLookup[key] ||
					(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());
		}

		function handleKey(down, key, character, event) {
			var type = down ? 'keydown' : 'keyup',
				view = View._focused,
				name;
			keyMap[key] = down;
			if (down) {
				charMap[key] = character;
			} else {
				delete charMap[key];
			}
			if (key.length > 1 && (name = Base.camelize(key)) in modifiers) {
				modifiers[name] = down;
				var agent = paper && paper.agent;
				if (name === 'meta' && agent && agent.mac) {
					if (down) {
						metaFixMap = {};
					} else {
						for (var k in metaFixMap) {
							if (k in charMap)
								handleKey(false, k, metaFixMap[k], event);
						}
						metaFixMap = null;
					}
				}
			} else if (down && metaFixMap) {
				metaFixMap[key] = character;
			}
			if (view) {
				view._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,
						character);
			}
		}

		DomEvent.add(document, {
			keydown: function(event) {
				var key = getKey(event),
					agent = paper && paper.agent;
				if (key.length > 1 || agent && (agent.chrome && (event.altKey
							|| agent.mac && event.metaKey
							|| !agent.mac && event.ctrlKey))) {
					handleKey(true, key,
							charLookup[key] || (key.length > 1 ? '' : key), event);
				} else {
					downKey = key;
				}
			},

			keypress: function(event) {
				if (downKey) {
					var key = getKey(event),
						code = event.charCode,
						character = code >= 32 ? String.fromCharCode(code)
							: key.length > 1 ? '' : key;
					if (key !== downKey) {
						key = character.toLowerCase();
					}
					handleKey(true, key, character, event);
					downKey = null;
				}
			},

			keyup: function(event) {
				var key = getKey(event);
				if (key in charMap)
					handleKey(false, key, charMap[key], event);
			}
		});

		DomEvent.add(window, {
			blur: function(event) {
				for (var key in charMap)
					handleKey(false, key, charMap[key], event);
			}
		});

		return {
			modifiers: modifiers,

			isDown: function(key) {
				return !!keyMap[key];
			}
		};
	};

	var MouseEvent = Event.extend({
		_class: 'MouseEvent',

		initialize: function MouseEvent(type, event, point, target, delta) {
			this.type = type;
			this.event = event;
			this.point = point;
			this.target = target;
			this.delta = delta;
		},

		toString: function() {
			return "{ type: '" + this.type
					+ "', point: " + this.point
					+ ', target: ' + this.target
					+ (this.delta ? ', delta: ' + this.delta : '')
					+ ', modifiers: ' + this.getModifiers()
					+ ' }';
		}
	});

	var ToolEvent = Event.extend({
		_class: 'ToolEvent',
		_item: null,

		initialize: function ToolEvent(tool, type, event) {
			this.tool = tool;
			this.type = type;
			this.event = event;
		},

		_choosePoint: function(point, toolPoint) {
			return point ? point : toolPoint ? toolPoint.clone() : null;
		},

		getPoint: function() {
			return this._choosePoint(this._point, this.tool._point);
		},

		setPoint: function(point) {
			this._point = point;
		},

		getLastPoint: function() {
			return this._choosePoint(this._lastPoint, this.tool._lastPoint);
		},

		setLastPoint: function(lastPoint) {
			this._lastPoint = lastPoint;
		},

		getDownPoint: function() {
			return this._choosePoint(this._downPoint, this.tool._downPoint);
		},

		setDownPoint: function(downPoint) {
			this._downPoint = downPoint;
		},

		getMiddlePoint: function() {
			if (!this._middlePoint && this.tool._lastPoint) {
				return this.tool._point.add(this.tool._lastPoint).divide(2);
			}
			return this._middlePoint;
		},

		setMiddlePoint: function(middlePoint) {
			this._middlePoint = middlePoint;
		},

		getDelta: function() {
			return !this._delta && this.tool._lastPoint
					? this.tool._point.subtract(this.tool._lastPoint)
					: this._delta;
		},

		setDelta: function(delta) {
			this._delta = delta;
		},

		getCount: function() {
			return this.tool[/^mouse(down|up)$/.test(this.type)
					? '_downCount' : '_moveCount'];
		},

		setCount: function(count) {
			this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
				= count;
		},

		getItem: function() {
			if (!this._item) {
				var result = this.tool._scope.project.hitTest(this.getPoint());
				if (result) {
					var item = result.item,
						parent = item._parent;
					while (/^(Group|CompoundPath)$/.test(parent._class)) {
						item = parent;
						parent = parent._parent;
					}
					this._item = item;
				}
			}
			return this._item;
		},

		setItem: function(item) {
			this._item = item;
		},

		toString: function() {
			return '{ type: ' + this.type
					+ ', point: ' + this.getPoint()
					+ ', count: ' + this.getCount()
					+ ', modifiers: ' + this.getModifiers()
					+ ' }';
		}
	});

	var Tool = PaperScopeItem.extend({
		_class: 'Tool',
		_list: 'tools',
		_reference: 'tool',
		_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',
				'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',
				'onKeyUp'],

		initialize: function Tool(props) {
			PaperScopeItem.call(this);
			this._moveCount = -1;
			this._downCount = -1;
			this._set(props);
		},

		getMinDistance: function() {
			return this._minDistance;
		},

		setMinDistance: function(minDistance) {
			this._minDistance = minDistance;
			if (minDistance != null && this._maxDistance != null
					&& minDistance > this._maxDistance) {
				this._maxDistance = minDistance;
			}
		},

		getMaxDistance: function() {
			return this._maxDistance;
		},

		setMaxDistance: function(maxDistance) {
			this._maxDistance = maxDistance;
			if (this._minDistance != null && maxDistance != null
					&& maxDistance < this._minDistance) {
				this._minDistance = maxDistance;
			}
		},

		getFixedDistance: function() {
			return this._minDistance == this._maxDistance
				? this._minDistance : null;
		},

		setFixedDistance: function(distance) {
			this._minDistance = this._maxDistance = distance;
		},

		_handleMouseEvent: function(type, event, point, mouse) {
			paper = this._scope;
			if (mouse.drag && !this.responds(type))
				type = 'mousemove';
			var move = mouse.move || mouse.drag,
				responds = this.responds(type),
				minDistance = this.minDistance,
				maxDistance = this.maxDistance,
				called = false,
				tool = this;
			function update(minDistance, maxDistance) {
				var pt = point,
					toolPoint = move ? tool._point : (tool._downPoint || pt);
				if (move) {
					if (tool._moveCount && pt.equals(toolPoint)) {
						return false;
					}
					if (toolPoint && (minDistance != null || maxDistance != null)) {
						var vector = pt.subtract(toolPoint),
							distance = vector.getLength();
						if (distance < (minDistance || 0))
							return false;
						if (maxDistance) {
							pt = toolPoint.add(vector.normalize(
									Math.min(distance, maxDistance)));
						}
					}
					tool._moveCount++;
				}
				tool._point = pt;
				tool._lastPoint = toolPoint || pt;
				if (mouse.down) {
					tool._moveCount = -1;
					tool._downPoint = pt;
					tool._downCount++;
				}
				return true;
			}

			function emit() {
				if (responds) {
					called = tool.emit(type, new ToolEvent(tool, type, event))
							|| called;
				}
			}

			if (mouse.down) {
				update();
				emit();
			} else if (mouse.up) {
				update(null, maxDistance);
				emit();
			} else if (responds) {
				while (update(minDistance, maxDistance))
					emit();
			}
			return called;
		}

	});

	var Http = {
		request: function(options) {
			var xhr = new window.XMLHttpRequest();
			xhr.open((options.method || 'get').toUpperCase(), options.url,
					Base.pick(options.async, true));
			if (options.mimeType)
				xhr.overrideMimeType(options.mimeType);
			xhr.onload = function() {
				var status = xhr.status;
				if (status === 0 || status === 200) {
					if (options.onLoad) {
						options.onLoad.call(xhr, xhr.responseText);
					}
				} else {
					xhr.onerror();
				}
			};
			xhr.onerror = function() {
				var status = xhr.status,
					message = 'Could not load "' + options.url + '" (Status: '
							+ status + ')';
				if (options.onError) {
					options.onError(message, status);
				} else {
					throw new Error(message);
				}
			};
			return xhr.send(null);
		}
	};

	var CanvasProvider = {
		canvases: [],

		getCanvas: function(width, height) {
			if (!window)
				return null;
			var canvas,
				clear = true;
			if (typeof width === 'object') {
				height = width.height;
				width = width.width;
			}
			if (this.canvases.length) {
				canvas = this.canvases.pop();
			} else {
				canvas = document.createElement('canvas');
				clear = false;
			}
			var ctx = canvas.getContext('2d');
			if (!ctx) {
				throw new Error('Canvas ' + canvas +
						' is unable toprovide a 2D context.');
			}
			if (canvas.width === width && canvas.height === height) {
				if (clear)
					ctx.clearRect(0, 0, width + 1, height + 1);
			} else {
				canvas.width = width;
				canvas.height = height;
			}
			ctx.save();
			return canvas;
		},

		getContext: function(width, height) {
			var canvas = this.getCanvas(width, height);
			return canvas ? canvas.getContext('2d') : null;
		},

		release: function(obj) {
			var canvas = obj && obj.canvas ? obj.canvas : obj;
			if (canvas && canvas.getContext) {
				canvas.getContext('2d').restore();
				this.canvases.push(canvas);
			}
		}
	};

	var BlendMode = new function() {
		var min = Math.min,
			max = Math.max,
			abs = Math.abs,
			sr, sg, sb, sa,
			br, bg, bb, ba,
			dr, dg, db;

		function getLum(r, g, b) {
			return 0.2989 * r + 0.587 * g + 0.114 * b;
		}

		function setLum(r, g, b, l) {
			var d = l - getLum(r, g, b);
			dr = r + d;
			dg = g + d;
			db = b + d;
			var l = getLum(dr, dg, db),
				mn = min(dr, dg, db),
				mx = max(dr, dg, db);
			if (mn < 0) {
				var lmn = l - mn;
				dr = l + (dr - l) * l / lmn;
				dg = l + (dg - l) * l / lmn;
				db = l + (db - l) * l / lmn;
			}
			if (mx > 255) {
				var ln = 255 - l,
					mxl = mx - l;
				dr = l + (dr - l) * ln / mxl;
				dg = l + (dg - l) * ln / mxl;
				db = l + (db - l) * ln / mxl;
			}
		}

		function getSat(r, g, b) {
			return max(r, g, b) - min(r, g, b);
		}

		function setSat(r, g, b, s) {
			var col = [r, g, b],
				mx = max(r, g, b),
				mn = min(r, g, b),
				md;
			mn = mn === r ? 0 : mn === g ? 1 : 2;
			mx = mx === r ? 0 : mx === g ? 1 : 2;
			md = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;
			if (col[mx] > col[mn]) {
				col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);
				col[mx] = s;
			} else {
				col[md] = col[mx] = 0;
			}
			col[mn] = 0;
			dr = col[0];
			dg = col[1];
			db = col[2];
		}

		var modes = {
			multiply: function() {
				dr = br * sr / 255;
				dg = bg * sg / 255;
				db = bb * sb / 255;
			},

			screen: function() {
				dr = br + sr - (br * sr / 255);
				dg = bg + sg - (bg * sg / 255);
				db = bb + sb - (bb * sb / 255);
			},

			overlay: function() {
				dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;
				dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;
				db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;
			},

			'soft-light': function() {
				var t = sr * br / 255;
				dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;
				t = sg * bg / 255;
				dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;
				t = sb * bb / 255;
				db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;
			},

			'hard-light': function() {
				dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;
				dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;
				db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;
			},

			'color-dodge': function() {
				dr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));
				dg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));
				db = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));
			},

			'color-burn': function() {
				dr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);
				dg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);
				db = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);
			},

			darken: function() {
				dr = br < sr ? br : sr;
				dg = bg < sg ? bg : sg;
				db = bb < sb ? bb : sb;
			},

			lighten: function() {
				dr = br > sr ? br : sr;
				dg = bg > sg ? bg : sg;
				db = bb > sb ? bb : sb;
			},

			difference: function() {
				dr = br - sr;
				if (dr < 0)
					dr = -dr;
				dg = bg - sg;
				if (dg < 0)
					dg = -dg;
				db = bb - sb;
				if (db < 0)
					db = -db;
			},

			exclusion: function() {
				dr = br + sr * (255 - br - br) / 255;
				dg = bg + sg * (255 - bg - bg) / 255;
				db = bb + sb * (255 - bb - bb) / 255;
			},

			hue: function() {
				setSat(sr, sg, sb, getSat(br, bg, bb));
				setLum(dr, dg, db, getLum(br, bg, bb));
			},

			saturation: function() {
				setSat(br, bg, bb, getSat(sr, sg, sb));
				setLum(dr, dg, db, getLum(br, bg, bb));
			},

			luminosity: function() {
				setLum(br, bg, bb, getLum(sr, sg, sb));
			},

			color: function() {
				setLum(sr, sg, sb, getLum(br, bg, bb));
			},

			add: function() {
				dr = min(br + sr, 255);
				dg = min(bg + sg, 255);
				db = min(bb + sb, 255);
			},

			subtract: function() {
				dr = max(br - sr, 0);
				dg = max(bg - sg, 0);
				db = max(bb - sb, 0);
			},

			average: function() {
				dr = (br + sr) / 2;
				dg = (bg + sg) / 2;
				db = (bb + sb) / 2;
			},

			negation: function() {
				dr = 255 - abs(255 - sr - br);
				dg = 255 - abs(255 - sg - bg);
				db = 255 - abs(255 - sb - bb);
			}
		};

		var nativeModes = this.nativeModes = Base.each([
			'source-over', 'source-in', 'source-out', 'source-atop',
			'destination-over', 'destination-in', 'destination-out',
			'destination-atop', 'lighter', 'darker', 'copy', 'xor'
		], function(mode) {
			this[mode] = true;
		}, {});

		var ctx = CanvasProvider.getContext(1, 1);
		if (ctx) {
			Base.each(modes, function(func, mode) {
				var darken = mode === 'darken',
					ok = false;
				ctx.save();
				try {
					ctx.fillStyle = darken ? '#300' : '#a00';
					ctx.fillRect(0, 0, 1, 1);
					ctx.globalCompositeOperation = mode;
					if (ctx.globalCompositeOperation === mode) {
						ctx.fillStyle = darken ? '#a00' : '#300';
						ctx.fillRect(0, 0, 1, 1);
						ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken
								? 170 : 51;
					}
				} catch (e) {}
				ctx.restore();
				nativeModes[mode] = ok;
			});
			CanvasProvider.release(ctx);
		}

		this.process = function(mode, srcContext, dstContext, alpha, offset) {
			var srcCanvas = srcContext.canvas,
				normal = mode === 'normal';
			if (normal || nativeModes[mode]) {
				dstContext.save();
				dstContext.setTransform(1, 0, 0, 1, 0, 0);
				dstContext.globalAlpha = alpha;
				if (!normal)
					dstContext.globalCompositeOperation = mode;
				dstContext.drawImage(srcCanvas, offset.x, offset.y);
				dstContext.restore();
			} else {
				var process = modes[mode];
				if (!process)
					return;
				var dstData = dstContext.getImageData(offset.x, offset.y,
						srcCanvas.width, srcCanvas.height),
					dst = dstData.data,
					src = srcContext.getImageData(0, 0,
						srcCanvas.width, srcCanvas.height).data;
				for (var i = 0, l = dst.length; i < l; i += 4) {
					sr = src[i];
					br = dst[i];
					sg = src[i + 1];
					bg = dst[i + 1];
					sb = src[i + 2];
					bb = dst[i + 2];
					sa = src[i + 3];
					ba = dst[i + 3];
					process();
					var a1 = sa * alpha / 255,
						a2 = 1 - a1;
					dst[i] = a1 * dr + a2 * br;
					dst[i + 1] = a1 * dg + a2 * bg;
					dst[i + 2] = a1 * db + a2 * bb;
					dst[i + 3] = sa * alpha + a2 * ba;
				}
				dstContext.putImageData(dstData, offset.x, offset.y);
			}
		};
	};

	var SvgElement = new function() {
		var svg = 'http://www.w3.org/2000/svg',
			xmlns = 'http://www.w3.org/2000/xmlns',
			xlink = 'http://www.w3.org/1999/xlink',
			attributeNamespace = {
				href: xlink,
				xlink: xmlns,
				xmlns: xmlns + '/',
				'xmlns:xlink': xmlns + '/'
			};

		function create(tag, attributes, formatter) {
			return set(document.createElementNS(svg, tag), attributes, formatter);
		}

		function get(node, name) {
			var namespace = attributeNamespace[name],
				value = namespace
					? node.getAttributeNS(namespace, name)
					: node.getAttribute(name);
			return value === 'null' ? null : value;
		}

		function set(node, attributes, formatter) {
			for (var name in attributes) {
				var value = attributes[name],
					namespace = attributeNamespace[name];
				if (typeof value === 'number' && formatter)
					value = formatter.number(value);
				if (namespace) {
					node.setAttributeNS(namespace, name, value);
				} else {
					node.setAttribute(name, value);
				}
			}
			return node;
		}

		return {
			svg: svg,
			xmlns: xmlns,
			xlink: xlink,

			create: create,
			get: get,
			set: set
		};
	};

	var SvgStyles = Base.each({
		fillColor: ['fill', 'color'],
		fillRule: ['fill-rule', 'string'],
		strokeColor: ['stroke', 'color'],
		strokeWidth: ['stroke-width', 'number'],
		strokeCap: ['stroke-linecap', 'string'],
		strokeJoin: ['stroke-linejoin', 'string'],
		strokeScaling: ['vector-effect', 'lookup', {
			true: 'none',
			false: 'non-scaling-stroke'
		}, function(item, value) {
			return !value
					&& (item instanceof PathItem
						|| item instanceof Shape
						|| item instanceof TextItem);
		}],
		miterLimit: ['stroke-miterlimit', 'number'],
		dashArray: ['stroke-dasharray', 'array'],
		dashOffset: ['stroke-dashoffset', 'number'],
		fontFamily: ['font-family', 'string'],
		fontWeight: ['font-weight', 'string'],
		fontSize: ['font-size', 'number'],
		justification: ['text-anchor', 'lookup', {
			left: 'start',
			center: 'middle',
			right: 'end'
		}],
		opacity: ['opacity', 'number'],
		blendMode: ['mix-blend-mode', 'style']
	}, function(entry, key) {
		var part = Base.capitalize(key),
			lookup = entry[2];
		this[key] = {
			type: entry[1],
			property: key,
			attribute: entry[0],
			toSVG: lookup,
			fromSVG: lookup && Base.each(lookup, function(value, name) {
				this[value] = name;
			}, {}),
			exportFilter: entry[3],
			get: 'get' + part,
			set: 'set' + part
		};
	}, {});

	new function() {
		var formatter;

		function getTransform(matrix, coordinates, center) {
			var attrs = new Base(),
				trans = matrix.getTranslation();
			if (coordinates) {
				matrix = matrix._shiftless();
				var point = matrix._inverseTransform(trans);
				attrs[center ? 'cx' : 'x'] = point.x;
				attrs[center ? 'cy' : 'y'] = point.y;
				trans = null;
			}
			if (!matrix.isIdentity()) {
				var decomposed = matrix.decompose();
				if (decomposed) {
					var parts = [],
						angle = decomposed.rotation,
						scale = decomposed.scaling,
						skew = decomposed.skewing;
					if (trans && !trans.isZero())
						parts.push('translate(' + formatter.point(trans) + ')');
					if (angle)
						parts.push('rotate(' + formatter.number(angle) + ')');
					if (!Numerical.isZero(scale.x - 1)
							|| !Numerical.isZero(scale.y - 1))
						parts.push('scale(' + formatter.point(scale) +')');
					if (skew && skew.x)
						parts.push('skewX(' + formatter.number(skew.x) + ')');
					if (skew && skew.y)
						parts.push('skewY(' + formatter.number(skew.y) + ')');
					attrs.transform = parts.join(' ');
				} else {
					attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';
				}
			}
			return attrs;
		}

		function exportGroup(item, options) {
			var attrs = getTransform(item._matrix),
				children = item._children;
			var node = SvgElement.create('g', attrs, formatter);
			for (var i = 0, l = children.length; i < l; i++) {
				var child = children[i];
				var childNode = exportSVG(child, options);
				if (childNode) {
					if (child.isClipMask()) {
						var clip = SvgElement.create('clipPath');
						clip.appendChild(childNode);
						setDefinition(child, clip, 'clip');
						SvgElement.set(node, {
							'clip-path': 'url(#' + clip.id + ')'
						});
					} else {
						node.appendChild(childNode);
					}
				}
			}
			return node;
		}

		function exportRaster(item, options) {
			var attrs = getTransform(item._matrix, true),
				size = item.getSize(),
				image = item.getImage();
			attrs.x -= size.width / 2;
			attrs.y -= size.height / 2;
			attrs.width = size.width;
			attrs.height = size.height;
			attrs.href = options.embedImages === false && image && image.src
					|| item.toDataURL();
			return SvgElement.create('image', attrs, formatter);
		}

		function exportPath(item, options) {
			var matchShapes = options.matchShapes;
			if (matchShapes) {
				var shape = item.toShape(false);
				if (shape)
					return exportShape(shape, options);
			}
			var segments = item._segments,
				length = segments.length,
				type,
				attrs = getTransform(item._matrix);
			if (matchShapes && length >= 2 && !item.hasHandles()) {
				if (length > 2) {
					type = item._closed ? 'polygon' : 'polyline';
					var parts = [];
					for(var i = 0; i < length; i++)
						parts.push(formatter.point(segments[i]._point));
					attrs.points = parts.join(' ');
				} else {
					type = 'line';
					var start = segments[0]._point,
						end = segments[1]._point;
					attrs.set({
						x1: start.x,
						y1: start.y,
						x2: end.x,
						y2: end.y
					});
				}
			} else {
				type = 'path';
				attrs.d = item.getPathData(null, options.precision);
			}
			return SvgElement.create(type, attrs, formatter);
		}

		function exportShape(item) {
			var type = item._type,
				radius = item._radius,
				attrs = getTransform(item._matrix, true, type !== 'rectangle');
			if (type === 'rectangle') {
				type = 'rect';
				var size = item._size,
					width = size.width,
					height = size.height;
				attrs.x -= width / 2;
				attrs.y -= height / 2;
				attrs.width = width;
				attrs.height = height;
				if (radius.isZero())
					radius = null;
			}
			if (radius) {
				if (type === 'circle') {
					attrs.r = radius;
				} else {
					attrs.rx = radius.width;
					attrs.ry = radius.height;
				}
			}
			return SvgElement.create(type, attrs, formatter);
		}

		function exportCompoundPath(item, options) {
			var attrs = getTransform(item._matrix);
			var data = item.getPathData(null, options.precision);
			if (data)
				attrs.d = data;
			return SvgElement.create('path', attrs, formatter);
		}

		function exportSymbolItem(item, options) {
			var attrs = getTransform(item._matrix, true),
				definition = item._definition,
				node = getDefinition(definition, 'symbol'),
				definitionItem = definition._item,
				bounds = definitionItem.getBounds();
			if (!node) {
				node = SvgElement.create('symbol', {
					viewBox: formatter.rectangle(bounds)
				});
				node.appendChild(exportSVG(definitionItem, options));
				setDefinition(definition, node, 'symbol');
			}
			attrs.href = '#' + node.id;
			attrs.x += bounds.x;
			attrs.y += bounds.y;
			attrs.width = bounds.width;
			attrs.height = bounds.height;
			attrs.overflow = 'visible';
			return SvgElement.create('use', attrs, formatter);
		}

		function exportGradient(color) {
			var gradientNode = getDefinition(color, 'color');
			if (!gradientNode) {
				var gradient = color.getGradient(),
					radial = gradient._radial,
					origin = color.getOrigin(),
					destination = color.getDestination(),
					attrs;
				if (radial) {
					attrs = {
						cx: origin.x,
						cy: origin.y,
						r: origin.getDistance(destination)
					};
					var highlight = color.getHighlight();
					if (highlight) {
						attrs.fx = highlight.x;
						attrs.fy = highlight.y;
					}
				} else {
					attrs = {
						x1: origin.x,
						y1: origin.y,
						x2: destination.x,
						y2: destination.y
					};
				}
				attrs.gradientUnits = 'userSpaceOnUse';
				gradientNode = SvgElement.create((radial ? 'radial' : 'linear')
						+ 'Gradient', attrs, formatter);
				var stops = gradient._stops;
				for (var i = 0, l = stops.length; i < l; i++) {
					var stop = stops[i],
						stopColor = stop._color,
						alpha = stopColor.getAlpha();
					attrs = {
						offset: stop._offset || i / (l - 1)
					};
					if (stopColor)
						attrs['stop-color'] = stopColor.toCSS(true);
					if (alpha < 1)
						attrs['stop-opacity'] = alpha;
					gradientNode.appendChild(
							SvgElement.create('stop', attrs, formatter));
				}
				setDefinition(color, gradientNode, 'color');
			}
			return 'url(#' + gradientNode.id + ')';
		}

		function exportText(item) {
			var node = SvgElement.create('text', getTransform(item._matrix, true),
					formatter);
			node.textContent = item._content;
			return node;
		}

		var exporters = {
			Group: exportGroup,
			Layer: exportGroup,
			Raster: exportRaster,
			Path: exportPath,
			Shape: exportShape,
			CompoundPath: exportCompoundPath,
			SymbolItem: exportSymbolItem,
			PointText: exportText
		};

		function applyStyle(item, node, isRoot) {
			var attrs = {},
				parent = !isRoot && item.getParent(),
				style = [];

			if (item._name != null)
				attrs.id = item._name;

			Base.each(SvgStyles, function(entry) {
				var get = entry.get,
					type = entry.type,
					value = item[get]();
				if (entry.exportFilter
						? entry.exportFilter(item, value)
						: !parent || !Base.equals(parent[get](), value)) {
					if (type === 'color' && value != null) {
						var alpha = value.getAlpha();
						if (alpha < 1)
							attrs[entry.attribute + '-opacity'] = alpha;
					}
					if (type === 'style') {
						style.push(entry.attribute + ': ' + value);
					} else {
						attrs[entry.attribute] = value == null ? 'none'
								: type === 'color' ? value.gradient
									? exportGradient(value, item)
									: value.toCSS(true)
								: type === 'array' ? value.join(',')
								: type === 'lookup' ? entry.toSVG[value]
								: value;
					}
				}
			});

			if (style.length)
				attrs.style = style.join(';');

			if (attrs.opacity === 1)
				delete attrs.opacity;

			if (!item._visible)
				attrs.visibility = 'hidden';

			return SvgElement.set(node, attrs, formatter);
		}

		var definitions;
		function getDefinition(item, type) {
			if (!definitions)
				definitions = { ids: {}, svgs: {} };
			var id = item._id || item.__id || (item.__id = UID.get('svg'));
			return item && definitions.svgs[type + '-' + id];
		}

		function setDefinition(item, node, type) {
			if (!definitions)
				getDefinition();
			var typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;
			node.id = type + '-' + typeId;
			definitions.svgs[type + '-' + (item._id || item.__id)] = node;
		}

		function exportDefinitions(node, options) {
			var svg = node,
				defs = null;
			if (definitions) {
				svg = node.nodeName.toLowerCase() === 'svg' && node;
				for (var i in definitions.svgs) {
					if (!defs) {
						if (!svg) {
							svg = SvgElement.create('svg');
							svg.appendChild(node);
						}
						defs = svg.insertBefore(SvgElement.create('defs'),
								svg.firstChild);
					}
					defs.appendChild(definitions.svgs[i]);
				}
				definitions = null;
			}
			return options.asString
					? new window.XMLSerializer().serializeToString(svg)
					: svg;
		}

		function exportSVG(item, options, isRoot) {
			var exporter = exporters[item._class],
				node = exporter && exporter(item, options);
			if (node) {
				var onExport = options.onExport;
				if (onExport)
					node = onExport(item, node, options) || node;
				var data = JSON.stringify(item._data);
				if (data && data !== '{}' && data !== 'null')
					node.setAttribute('data-paper-data', data);
			}
			return node && applyStyle(item, node, isRoot);
		}

		function setOptions(options) {
			if (!options)
				options = {};
			formatter = new Formatter(options.precision);
			return options;
		}

		Item.inject({
			exportSVG: function(options) {
				options = setOptions(options);
				return exportDefinitions(exportSVG(this, options, true), options);
			}
		});

		Project.inject({
			exportSVG: function(options) {
				options = setOptions(options);
				var children = this._children,
					view = this.getView(),
					bounds = Base.pick(options.bounds, 'view'),
					mx = options.matrix || bounds === 'view' && view._matrix,
					matrix = mx && Matrix.read([mx]),
					rect = bounds === 'view'
						? new Rectangle([0, 0], view.getViewSize())
						: bounds === 'content'
							? Item._getBounds(children, matrix, { stroke: true })
							: Rectangle.read([bounds], 0, { readNull: true }),
					attrs = {
						version: '1.1',
						xmlns: SvgElement.svg,
						'xmlns:xlink': SvgElement.xlink,
					};
				if (rect) {
					attrs.width = rect.width;
					attrs.height = rect.height;
					if (rect.x || rect.y)
						attrs.viewBox = formatter.rectangle(rect);
				}
				var node = SvgElement.create('svg', attrs, formatter),
					parent = node;
				if (matrix && !matrix.isIdentity()) {
					parent = node.appendChild(SvgElement.create('g',
							getTransform(matrix), formatter));
				}
				for (var i = 0, l = children.length; i < l; i++) {
					parent.appendChild(exportSVG(children[i], options, true));
				}
				return exportDefinitions(node, options);
			}
		});
	};

	new function() {

		var definitions = {},
			rootSize;

		function getValue(node, name, isString, allowNull, allowPercent) {
			var value = SvgElement.get(node, name),
				res = value == null
					? allowNull
						? null
						: isString ? '' : 0
					: isString
						? value
						: parseFloat(value);
			return /%\s*$/.test(value)
				? (res / 100) * (allowPercent ? 1
					: rootSize[/x|^width/.test(name) ? 'width' : 'height'])
				: res;
		}

		function getPoint(node, x, y, allowNull, allowPercent) {
			x = getValue(node, x || 'x', false, allowNull, allowPercent);
			y = getValue(node, y || 'y', false, allowNull, allowPercent);
			return allowNull && (x == null || y == null) ? null
					: new Point(x, y);
		}

		function getSize(node, w, h, allowNull, allowPercent) {
			w = getValue(node, w || 'width', false, allowNull, allowPercent);
			h = getValue(node, h || 'height', false, allowNull, allowPercent);
			return allowNull && (w == null || h == null) ? null
					: new Size(w, h);
		}

		function convertValue(value, type, lookup) {
			return value === 'none' ? null
					: type === 'number' ? parseFloat(value)
					: type === 'array' ?
						value ? value.split(/[\s,]+/g).map(parseFloat) : []
					: type === 'color' ? getDefinition(value) || value
					: type === 'lookup' ? lookup[value]
					: value;
		}

		function importGroup(node, type, options, isRoot) {
			var nodes = node.childNodes,
				isClip = type === 'clippath',
				isDefs = type === 'defs',
				item = new Group(),
				project = item._project,
				currentStyle = project._currentStyle,
				children = [];
			if (!isClip && !isDefs) {
				item = applyAttributes(item, node, isRoot);
				project._currentStyle = item._style.clone();
			}
			if (isRoot) {
				var defs = node.querySelectorAll('defs');
				for (var i = 0, l = defs.length; i < l; i++) {
					importNode(defs[i], options, false);
				}
			}
			for (var i = 0, l = nodes.length; i < l; i++) {
				var childNode = nodes[i],
					child;
				if (childNode.nodeType === 1
						&& !/^defs$/i.test(childNode.nodeName)
						&& (child = importNode(childNode, options, false))
						&& !(child instanceof SymbolDefinition))
					children.push(child);
			}
			item.addChildren(children);
			if (isClip)
				item = applyAttributes(item.reduce(), node, isRoot);
			project._currentStyle = currentStyle;
			if (isClip || isDefs) {
				item.remove();
				item = null;
			}
			return item;
		}

		function importPoly(node, type) {
			var coords = node.getAttribute('points').match(
						/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g),
				points = [];
			for (var i = 0, l = coords.length; i < l; i += 2)
				points.push(new Point(
						parseFloat(coords[i]),
						parseFloat(coords[i + 1])));
			var path = new Path(points);
			if (type === 'polygon')
				path.closePath();
			return path;
		}

		function importPath(node) {
			return PathItem.create(node.getAttribute('d'));
		}

		function importGradient(node, type) {
			var id = (getValue(node, 'href', true) || '').substring(1),
				radial = type === 'radialgradient',
				gradient;
			if (id) {
				gradient = definitions[id].getGradient();
				if (gradient._radial ^ radial) {
					gradient = gradient.clone();
					gradient._radial = radial;
				}
			} else {
				var nodes = node.childNodes,
					stops = [];
				for (var i = 0, l = nodes.length; i < l; i++) {
					var child = nodes[i];
					if (child.nodeType === 1)
						stops.push(applyAttributes(new GradientStop(), child));
				}
				gradient = new Gradient(stops, radial);
			}
			var origin, destination, highlight,
				scaleToBounds = getValue(node, 'gradientUnits', true) !==
					'userSpaceOnUse';
			if (radial) {
				origin = getPoint(node, 'cx', 'cy', false, scaleToBounds);
				destination = origin.add(
						getValue(node, 'r', false, false, scaleToBounds), 0);
				highlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);
			} else {
				origin = getPoint(node, 'x1', 'y1', false, scaleToBounds);
				destination = getPoint(node, 'x2', 'y2', false, scaleToBounds);
			}
			var color = applyAttributes(
					new Color(gradient, origin, destination, highlight), node);
			color._scaleToBounds = scaleToBounds;
			return null;
		}

		var importers = {
			'#document': function (node, type, options, isRoot) {
				var nodes = node.childNodes;
				for (var i = 0, l = nodes.length; i < l; i++) {
					var child = nodes[i];
					if (child.nodeType === 1)
						return importNode(child, options, isRoot);
				}
			},
			g: importGroup,
			svg: importGroup,
			clippath: importGroup,
			polygon: importPoly,
			polyline: importPoly,
			path: importPath,
			lineargradient: importGradient,
			radialgradient: importGradient,

			image: function (node) {
				var raster = new Raster(getValue(node, 'href', true));
				raster.on('load', function() {
					var size = getSize(node);
					this.setSize(size);
					var center = this._matrix._transformPoint(
							getPoint(node).add(size.divide(2)));
					this.translate(center);
				});
				return raster;
			},

			symbol: function(node, type, options, isRoot) {
				return new SymbolDefinition(
						importGroup(node, type, options, isRoot), true);
			},

			defs: importGroup,

			use: function(node) {
				var id = (getValue(node, 'href', true) || '').substring(1),
					definition = definitions[id],
					point = getPoint(node);
				return definition
						? definition instanceof SymbolDefinition
							? definition.place(point)
							: definition.clone().translate(point)
						: null;
			},

			circle: function(node) {
				return new Shape.Circle(
						getPoint(node, 'cx', 'cy'),
						getValue(node, 'r'));
			},

			ellipse: function(node) {
				return new Shape.Ellipse({
					center: getPoint(node, 'cx', 'cy'),
					radius: getSize(node, 'rx', 'ry')
				});
			},

			rect: function(node) {
				return new Shape.Rectangle(new Rectangle(
							getPoint(node),
							getSize(node)
						), getSize(node, 'rx', 'ry'));
				},

			line: function(node) {
				return new Path.Line(
						getPoint(node, 'x1', 'y1'),
						getPoint(node, 'x2', 'y2'));
			},

			text: function(node) {
				var text = new PointText(getPoint(node).add(
						getPoint(node, 'dx', 'dy')));
				text.setContent(node.textContent.trim() || '');
				return text;
			}
		};

		function applyTransform(item, value, name, node) {
			if (item.transform) {
				var transforms = (node.getAttribute(name) || '').split(/\)\s*/g),
					matrix = new Matrix();
				for (var i = 0, l = transforms.length; i < l; i++) {
					var transform = transforms[i];
					if (!transform)
						break;
					var parts = transform.split(/\(\s*/),
						command = parts[0],
						v = parts[1].split(/[\s,]+/g);
					for (var j = 0, m = v.length; j < m; j++)
						v[j] = parseFloat(v[j]);
					switch (command) {
					case 'matrix':
						matrix.append(
								new Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));
						break;
					case 'rotate':
						matrix.rotate(v[0], v[1], v[2]);
						break;
					case 'translate':
						matrix.translate(v[0], v[1]);
						break;
					case 'scale':
						matrix.scale(v);
						break;
					case 'skewX':
						matrix.skew(v[0], 0);
						break;
					case 'skewY':
						matrix.skew(0, v[0]);
						break;
					}
				}
				item.transform(matrix);
			}
		}

		function applyOpacity(item, value, name) {
			var key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',
				color = item[key] && item[key]();
			if (color)
				color.setAlpha(parseFloat(value));
		}

		var attributes = Base.set(Base.each(SvgStyles, function(entry) {
			this[entry.attribute] = function(item, value) {
				if (item[entry.set]) {
					item[entry.set](convertValue(value, entry.type, entry.fromSVG));
					if (entry.type === 'color') {
						var color = item[entry.get]();
						if (color) {
							if (color._scaleToBounds) {
								var bounds = item.getBounds();
								color.transform(new Matrix()
									.translate(bounds.getPoint())
									.scale(bounds.getSize()));
							}
							if (item instanceof Shape) {
								color.transform(new Matrix().translate(
									item.getPosition(true).negate()));
							}
						}
					}
				}
			};
		}, {}), {
			id: function(item, value) {
				definitions[value] = item;
				if (item.setName)
					item.setName(value);
			},

			'clip-path': function(item, value) {
				var clip = getDefinition(value);
				if (clip) {
					clip = clip.clone();
					clip.setClipMask(true);
					if (item instanceof Group) {
						item.insertChild(0, clip);
					} else {
						return new Group(clip, item);
					}
				}
			},

			gradientTransform: applyTransform,
			transform: applyTransform,

			'fill-opacity': applyOpacity,
			'stroke-opacity': applyOpacity,

			visibility: function(item, value) {
				if (item.setVisible)
					item.setVisible(value === 'visible');
			},

			display: function(item, value) {
				if (item.setVisible)
					item.setVisible(value !== null);
			},

			'stop-color': function(item, value) {
				if (item.setColor)
					item.setColor(value);
			},

			'stop-opacity': function(item, value) {
				if (item._color)
					item._color.setAlpha(parseFloat(value));
			},

			offset: function(item, value) {
				if (item.setOffset) {
					var percent = value.match(/(.*)%$/);
					item.setOffset(percent ? percent[1] / 100 : parseFloat(value));
				}
			},

			viewBox: function(item, value, name, node, styles) {
				var rect = new Rectangle(convertValue(value, 'array')),
					size = getSize(node, null, null, true),
					group,
					matrix;
				if (item instanceof Group) {
					var scale = size ? size.divide(rect.getSize()) : 1,
					matrix = new Matrix().scale(scale)
							.translate(rect.getPoint().negate());
					group = item;
				} else if (item instanceof SymbolDefinition) {
					if (size)
						rect.setSize(size);
					group = item._item;
				}
				if (group)  {
					if (getAttribute(node, 'overflow', styles) !== 'visible') {
						var clip = new Shape.Rectangle(rect);
						clip.setClipMask(true);
						group.addChild(clip);
					}
					if (matrix)
						group.transform(matrix);
				}
			}
		});

		function getAttribute(node, name, styles) {
			var attr = node.attributes[name],
				value = attr && attr.value;
			if (!value) {
				var style = Base.camelize(name);
				value = node.style[style];
				if (!value && styles.node[style] !== styles.parent[style])
					value = styles.node[style];
			}
			return !value ? undefined
					: value === 'none' ? null
					: value;
		}

		function applyAttributes(item, node, isRoot) {
			var parent = node.parentNode,
				styles = {
					node: DomElement.getStyles(node) || {},
					parent: !isRoot && !/^defs$/i.test(parent.tagName)
							&& DomElement.getStyles(parent) || {}
				};
			Base.each(attributes, function(apply, name) {
				var value = getAttribute(node, name, styles);
				item = value !== undefined && apply(item, value, name, node, styles)
						|| item;
			});
			return item;
		}

		function getDefinition(value) {
			var match = value && value.match(/\((?:["'#]*)([^"')]+)/),
				res = match && definitions[match[1]
					.replace(window.location.href.split('#')[0] + '#', '')];
			if (res && res._scaleToBounds) {
				res = res.clone();
				res._scaleToBounds = true;
			}
			return res;
		}

		function importNode(node, options, isRoot) {
			var type = node.nodeName.toLowerCase(),
				isElement = type !== '#document',
				body = document.body,
				container,
				parent,
				next;
			if (isRoot && isElement) {
				rootSize = getSize(node, null, null, true)
						|| paper.getView().getSize();
				container = SvgElement.create('svg', {
					style: 'stroke-width: 1px; stroke-miterlimit: 10'
				});
				parent = node.parentNode;
				next = node.nextSibling;
				container.appendChild(node);
				body.appendChild(container);
			}
			var settings = paper.settings,
				applyMatrix = settings.applyMatrix,
				insertItems = settings.insertItems;
			settings.applyMatrix = false;
			settings.insertItems = false;
			var importer = importers[type],
				item = importer && importer(node, type, options, isRoot) || null;
			settings.insertItems = insertItems;
			settings.applyMatrix = applyMatrix;
			if (item) {
				if (isElement && !(item instanceof Group))
					item = applyAttributes(item, node, isRoot);
				var onImport = options.onImport,
					data = isElement && node.getAttribute('data-paper-data');
				if (onImport)
					item = onImport(node, item, options) || item;
				if (options.expandShapes && item instanceof Shape) {
					item.remove();
					item = item.toPath();
				}
				if (data)
					item._data = JSON.parse(data);
			}
			if (container) {
				body.removeChild(container);
				if (parent) {
					if (next) {
						parent.insertBefore(node, next);
					} else {
						parent.appendChild(node);
					}
				}
			}
			if (isRoot) {
				definitions = {};
				if (item && Base.pick(options.applyMatrix, applyMatrix))
					item.matrix.apply(true, true);
			}
			return item;
		}

		function importSVG(source, options, owner) {
			if (!source)
				return null;
			options = typeof options === 'function' ? { onLoad: options }
					: options || {};
			var scope = paper,
				item = null;

			function onLoad(svg) {
				try {
					var node = typeof svg === 'object' ? svg : new window.DOMParser()
							.parseFromString(svg, 'image/svg+xml');
					if (!node.nodeName) {
						node = null;
						throw new Error('Unsupported SVG source: ' + source);
					}
					paper = scope;
					item = importNode(node, options, true);
					if (!options || options.insert !== false) {
						owner._insertItem(undefined, item);
					}
					var onLoad = options.onLoad;
					if (onLoad)
						onLoad(item, svg);
				} catch (e) {
					onError(e);
				}
			}

			function onError(message, status) {
				var onError = options.onError;
				if (onError) {
					onError(message, status);
				} else {
					throw new Error(message);
				}
			}

			if (typeof source === 'string' && !/^.*</.test(source)) {
				var node = document.getElementById(source);
				if (node) {
					onLoad(node);
				} else {
					Http.request({
						url: source,
						async: true,
						onLoad: onLoad,
						onError: onError
					});
				}
			} else if (typeof File !== 'undefined' && source instanceof File) {
				var reader = new FileReader();
				reader.onload = function() {
					onLoad(reader.result);
				};
				reader.onerror = function() {
					onError(reader.error);
				};
				return reader.readAsText(source);
			} else {
				onLoad(source);
			}

			return item;
		}

		Item.inject({
			importSVG: function(node, options) {
				return importSVG(node, options, this);
			}
		});

		Project.inject({
			importSVG: function(node, options) {
				this.activate();
				return importSVG(node, options, this);
			}
		});
	};

	Base.exports.PaperScript = function() {
		var exports, define,
			scope = this;
	!function(e,r){return"object"==typeof exports&&"object"==typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):void r(e.acorn||(e.acorn={}))}(this,function(e){"use strict";function r(e){fe=e||{};for(var r in he)Object.prototype.hasOwnProperty.call(fe,r)||(fe[r]=he[r]);me=fe.sourceFile||null}function t(e,r){var t=ve(de,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=be,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;r<e.length;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;a<e.length;++a){for(var o=0;o<n.length;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;a<n.length;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return new Function("str",t)}function a(){this.line=Ae,this.column=be-Se}function o(){Ae=1,be=Se=0,Ee=!0,u()}function i(e,r){ge=be,fe.locations&&(ke=new a),we=e,u(),Ce=r,Ee=e.beforeExpr}function s(){var e=fe.onComment&&fe.locations&&new a,r=be,n=de.indexOf("*/",be+=2);if(-1===n&&t(be-2,"Unterminated comment"),be=n+2,fe.locations){Kr.lastIndex=r;for(var o;(o=Kr.exec(de))&&o.index<be;)++Ae,Se=o.index+o[0].length}fe.onComment&&fe.onComment(!0,de.slice(r+2,n),r,be,e,fe.locations&&new a)}function c(){for(var e=be,r=fe.onComment&&fe.locations&&new a,t=de.charCodeAt(be+=2);pe>be&&10!==t&&13!==t&&8232!==t&&8233!==t;)++be,t=de.charCodeAt(be);fe.onComment&&fe.onComment(!1,de.slice(e+2,be),e,be,r,fe.locations&&new a)}function u(){for(;pe>be;){var e=de.charCodeAt(be);if(32===e)++be;else if(13===e){++be;var r=de.charCodeAt(be);10===r&&++be,fe.locations&&(++Ae,Se=be)}else if(10===e||8232===e||8233===e)++be,fe.locations&&(++Ae,Se=be);else if(e>8&&14>e)++be;else if(47===e){var r=de.charCodeAt(be+1);if(42===r)s();else{if(47!==r)break;c()}}else if(160===e)++be;else{if(!(e>=5760&&Jr.test(String.fromCharCode(e))))break;++be}}}function l(){var e=de.charCodeAt(be+1);return e>=48&&57>=e?E(!0):(++be,i(xr))}function f(){var e=de.charCodeAt(be+1);return Ee?(++be,k()):61===e?x(Er,2):x(wr,1)}function d(){var e=de.charCodeAt(be+1);return 61===e?x(Er,2):x(jr,1)}function p(e){var r=de.charCodeAt(be+1);return r===e?x(124===e?Ir:Lr,2):61===r?x(Er,2):x(124===e?Ur:Rr,1)}function m(){var e=de.charCodeAt(be+1);return 61===e?x(Er,2):x(Fr,1)}function h(e){var r=de.charCodeAt(be+1);return r===e?45==r&&62==de.charCodeAt(be+2)&&Gr.test(de.slice(Le,be))?(be+=3,c(),u(),g()):x(Ar,2):61===r?x(Er,2):x(qr,1)}function v(e){var r=de.charCodeAt(be+1),t=1;return r===e?(t=62===e&&62===de.charCodeAt(be+2)?3:2,61===de.charCodeAt(be+t)?x(Er,t+1):x(Tr,t)):33==r&&60==e&&45==de.charCodeAt(be+2)&&45==de.charCodeAt(be+3)?(be+=4,c(),u(),g()):(61===r&&(t=61===de.charCodeAt(be+2)?3:2),x(Vr,t))}function b(e){var r=de.charCodeAt(be+1);return 61===r?x(Or,61===de.charCodeAt(be+2)?3:2):x(61===e?Cr:Sr,1)}function y(e){switch(e){case 46:return l();case 40:return++be,i(hr);case 41:return++be,i(vr);case 59:return++be,i(yr);case 44:return++be,i(br);case 91:return++be,i(fr);case 93:return++be,i(dr);case 123:return++be,i(pr);case 125:return++be,i(mr);case 58:return++be,i(gr);case 63:return++be,i(kr);case 48:var r=de.charCodeAt(be+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return d();case 124:case 38:return p(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(Sr,1)}return!1}function g(e){if(e?be=ye+1:ye=be,fe.locations&&(xe=new a),e)return k();if(be>=pe)return i(Be);var r=de.charCodeAt(be);if(Qr(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$r.test(o))return L();t(be,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=de.slice(be,be+r);be+=r,i(e,t)}function k(){for(var e,r,n="",a=be;;){be>=pe&&t(a,"Unterminated regular expression");var o=de.charAt(be);if(Gr.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++be}var n=de.slice(a,be);++be;var s=I();s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag");try{var c=new RegExp(n,s)}catch(u){u instanceof SyntaxError&&t(a,u.message),t(u)}return i(qe,c)}function w(e,r){for(var t=be,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=de.charCodeAt(be);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++be,n=n*e+i}return be===t||null!=r&&be-t!==r?null:n}function C(){be+=2;var e=w(16);return null==e&&t(ye+2,"Expected hexadecimal number"),Qr(de.charCodeAt(be))&&t(be,"Identifier directly after number"),i(Te,e)}function E(e){var r=be,n=!1,a=48===de.charCodeAt(be);e||null!==w(10)||t(r,"Invalid number"),46===de.charCodeAt(be)&&(++be,w(10),n=!0);var o=de.charCodeAt(be);69!==o&&101!==o||(o=de.charCodeAt(++be),43!==o&&45!==o||++be,null===w(10)&&t(r,"Invalid number"),n=!0),Qr(de.charCodeAt(be))&&t(be,"Identifier directly after number");var s,c=de.slice(r,be);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Oe?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(Te,s)}function A(e){be++;for(var r="";;){be>=pe&&t(ye,"Unterminated string constant");var n=de.charCodeAt(be);if(n===e)return++be,i(je,r);if(92===n){n=de.charCodeAt(++be);var a=/^[0-7]+/.exec(de.slice(be,be+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,-1);if("0"===a&&(a=null),++be,a)Oe&&t(be-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),be+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+="	";break;case 98:r+="\b";break;case 118:r+="\x0B";break;case 102:r+="\f";break;case 48:r+="\x00";break;case 13:10===de.charCodeAt(be)&&++be;case 10:fe.locations&&(Se=be,++Ae);break;default:r+=String.fromCharCode(n)}}else 13!==n&&10!==n&&8232!==n&&8233!==n||t(ye,"Unterminated string constant"),r+=String.fromCharCode(n),++be}}function S(e){var r=w(16,e);return null===r&&t(ye,"Bad character escape sequence"),r}function I(){Br=!1;for(var e,r=!0,n=be;;){var a=de.charCodeAt(be);if(Yr(a))Br&&(e+=de.charAt(be)),++be;else{if(92!==a)break;Br||(e=de.slice(n,be)),Br=!0,117!=de.charCodeAt(++be)&&t(be,"Expecting Unicode escape sequence \\uXXXX"),++be;var o=S(4),i=String.fromCharCode(o);i||t(be-1,"Invalid Unicode escape"),(r?Qr(o):Yr(o))||t(be-4,"Invalid Unicode escape"),e+=i}r=!1}return Br?e:de.slice(n,be)}function L(){var e=I(),r=De;return!Br&&Wr(e)&&(r=lr[e]),i(r,e)}function U(){Ie=ye,Le=ge,Ue=ke,g()}function F(e){if(Oe=e,be=ye,fe.locations)for(;Se>be;)Se=de.lastIndexOf("\n",Se-2)+1,--Ae;u(),g()}function R(){this.type=null,this.start=ye,this.end=null}function O(){this.start=xe,this.end=null,null!==me&&(this.source=me)}function V(){var e=new R;return fe.locations&&(e.loc=new O),fe.directSourceFile&&(e.sourceFile=fe.directSourceFile),fe.ranges&&(e.range=[ye,0]),e}function T(e){var r=new R;return r.start=e.start,fe.locations&&(r.loc=new O,r.loc.start=e.loc.start),fe.ranges&&(r.range=[e.range[0],0]),r}function q(e,r){return e.type=r,e.end=Le,fe.locations&&(e.loc.end=Ue),fe.ranges&&(e.range[1]=Le),e}function j(e){return fe.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return we===e?(U(),!0):void 0}function B(){return!fe.strictSemicolons&&(we===Be||we===mr||Gr.test(de.slice(Le,ye)))}function M(){D(yr)||B()||X()}function z(e){we===e?U():X()}function X(){t(ye,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Oe&&"Identifier"===e.type&&Nr(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ie=Le=be,fe.locations&&(Ue=new a),Fe=Oe=null,Re=[],g();var r=e||V(),t=!0;for(e||(r.body=[]);we!==Be;){var n=J();r.body.push(n),t&&j(n)&&F(!0),t=!1}return q(r,"Program")}function J(){(we===wr||we===Er&&"/="==Ce)&&g(!0);var e=we,r=V();switch(e){case Me:case Ne:U();var n=e===Me;D(yr)||B()?r.label=null:we!==De?X():(r.label=le(),M());for(var a=0;a<Re.length;++a){var o=Re[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Re.length&&t(r.start,"Unsyntactic "+e.keyword),q(r,n?"BreakStatement":"ContinueStatement");case We:return U(),M(),q(r,"DebuggerStatement");case Pe:return U(),Re.push(Zr),r.body=J(),Re.pop(),z(tr),r.test=P(),M(),q(r,"DoWhileStatement");case _e:if(U(),Re.push(Zr),z(hr),we===yr)return $(r,null);if(we===rr){var i=V();return U(),G(i,!0),q(i,"VariableDeclaration"),1===i.declarations.length&&D(ur)?_(r,i):$(r,i)}var i=K(!1,!0);return D(ur)?(N(i),_(r,i)):$(r,i);case Ge:return U(),ce(r,!0);case Ke:return U(),r.test=P(),r.consequent=J(),r.alternate=D(He)?J():null,q(r,"IfStatement");case Qe:return Fe||fe.allowReturnOutsideFunction||t(ye,"'return' outside of function"),U(),D(yr)||B()?r.argument=null:(r.argument=K(),M()),q(r,"ReturnStatement");case Ye:U(),r.discriminant=P(),r.cases=[],z(pr),Re.push(et);for(var s,c;we!=mr;)if(we===ze||we===Je){var u=we===ze;s&&q(s,"SwitchCase"),r.cases.push(s=V()),s.consequent=[],U(),u?s.test=K():(c&&t(Ie,"Multiple default clauses"),c=!0,s.test=null),z(gr)}else s||X(),s.consequent.push(J());return s&&q(s,"SwitchCase"),U(),Re.pop(),q(r,"SwitchStatement");case Ze:return U(),Gr.test(de.slice(Le,ye))&&t(Le,"Illegal newline after throw"),r.argument=K(),M(),q(r,"ThrowStatement");case er:if(U(),r.block=H(),r.handler=null,we===Xe){var l=V();U(),z(hr),l.param=le(),Oe&&Nr(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(vr),l.guard=null,l.body=H(),r.handler=q(l,"CatchClause")}return r.guardedHandlers=Ve,r.finalizer=D($e)?H():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),q(r,"TryStatement");case rr:return U(),G(r),M(),q(r,"VariableDeclaration");case tr:return U(),r.test=P(),Re.push(Zr),r.body=J(),Re.pop(),q(r,"WhileStatement");case nr:return Oe&&t(ye,"'with' in strict mode"),U(),r.object=P(),r.body=J(),q(r,"WithStatement");case pr:return H();case yr:return U(),q(r,"EmptyStatement");default:var f=Ce,d=K();if(e===De&&"Identifier"===d.type&&D(gr)){for(var a=0;a<Re.length;++a)Re[a].name===f&&t(d.start,"Label '"+f+"' is already declared");var p=we.isLoop?"loop":we===Ye?"switch":null;return Re.push({name:f,kind:p}),r.body=J(),Re.pop(),r.label=d,q(r,"LabeledStatement")}return r.expression=d,M(),q(r,"ExpressionStatement")}}function P(){z(hr);var e=K();return z(vr),e}function H(e){var r,t=V(),n=!0,a=!1;for(t.body=[],z(pr);!D(mr);){var o=J();t.body.push(o),n&&e&&j(o)&&(r=a,F(a=!0)),n=!1}return a&&!r&&F(!1),q(t,"BlockStatement")}function $(e,r){return e.init=r,z(yr),e.test=we===yr?null:K(),z(yr),e.update=we===vr?null:K(),z(vr),e.body=J(),Re.pop(),q(e,"ForStatement")}function _(e,r){return e.left=r,e.right=K(),z(vr),e.body=J(),Re.pop(),q(e,"ForInStatement")}function G(e,r){for(e.declarations=[],e.kind="var";;){var n=V();if(n.id=le(),Oe&&Nr(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(Cr)?K(!0,r):null,e.declarations.push(q(n,"VariableDeclarator")),!D(br))break}return e}function K(e,r){var t=Q(r);if(!e&&we===br){var n=T(t);for(n.expressions=[t];D(br);)n.expressions.push(Q(r));return q(n,"SequenceExpression")}return t}function Q(e){var r=Y(e);if(we.isAssign){var t=T(r);return t.operator=Ce,t.left=r,U(),t.right=Q(e),N(r),q(t,"AssignmentExpression")}return r}function Y(e){var r=Z(e);if(D(kr)){var t=T(r);return t.test=r,t.consequent=K(!0),z(gr),t.alternate=K(!0,e),q(t,"ConditionalExpression")}return r}function Z(e){return ee(re(),-1,e)}function ee(e,r,t){var n=we.binop;if(null!=n&&(!t||we!==ur)&&n>r){var a=T(e);a.left=e,a.operator=Ce;var o=we;U(),a.right=ee(re(),n,t);var i=q(a,o===Ir||o===Lr?"LogicalExpression":"BinaryExpression");return ee(i,r,t)}return e}function re(){if(we.prefix){var e=V(),r=we.isUpdate;return e.operator=Ce,e.prefix=!0,Ee=!0,U(),e.argument=re(),r?N(e.argument):Oe&&"delete"===e.operator&&"Identifier"===e.argument.type&&t(e.start,"Deleting local variable in strict mode"),q(e,r?"UpdateExpression":"UnaryExpression")}for(var n=te();we.postfix&&!B();){var e=T(n);e.operator=Ce,e.prefix=!1,e.argument=n,N(n),U(),n=q(e,"UpdateExpression")}return n}function te(){return ne(ae())}function ne(e,r){if(D(xr)){var t=T(e);return t.object=e,t.property=le(!0),t.computed=!1,ne(q(t,"MemberExpression"),r)}if(D(fr)){var t=T(e);return t.object=e,t.property=K(),t.computed=!0,z(dr),ne(q(t,"MemberExpression"),r)}if(!r&&D(hr)){var t=T(e);return t.callee=e,t.arguments=ue(vr,!1),ne(q(t,"CallExpression"),r)}return e}function ae(){switch(we){case or:var e=V();return U(),q(e,"ThisExpression");case De:return le();case Te:case je:case qe:var e=V();return e.value=Ce,e.raw=de.slice(ye,ge),U(),q(e,"Literal");case ir:case sr:case cr:var e=V();return e.value=we.atomValue,e.raw=we.keyword,U(),q(e,"Literal");case hr:var r=xe,t=ye;U();var n=K();return n.start=t,n.end=ge,fe.locations&&(n.loc.start=r,n.loc.end=ke),fe.ranges&&(n.range=[t,ge]),z(vr),n;case fr:var e=V();return U(),e.elements=ue(dr,!0,!0),q(e,"ArrayExpression");case pr:return ie();case Ge:var e=V();return U(),ce(e,!1);case ar:return oe();default:X()}}function oe(){var e=V();return U(),e.callee=ne(ae(),!0),D(hr)?e.arguments=ue(vr,!1):e.arguments=Ve,q(e,"NewExpression")}function ie(){var e=V(),r=!0,n=!1;for(e.properties=[],U();!D(mr);){if(r)r=!1;else if(z(br),fe.allowTrailingCommas&&D(mr))break;var a,o={key:se()},i=!1;if(D(gr)?(o.value=K(!0),a=o.kind="init"):fe.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=se(),we!==hr&&X(),o.value=ce(V(),!1)):X(),"Identifier"===o.key.type&&(Oe||n))for(var s=0;s<e.properties.length;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Oe&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return q(e,"ObjectExpression")}function se(){return we===Te||we===je?ae():le(!0)}function ce(e,r){we===De?e.id=le():r?X():e.id=null,e.params=[];var n=!0;for(z(hr);!D(vr);)n?n=!1:z(br),e.params.push(le());var a=Fe,o=Re;if(Fe=!0,Re=[],e.body=H(!0),Fe=a,Re=o,Oe||e.body.body.length&&j(e.body.body[0]))for(var i=e.id?-1:0;i<e.params.length;++i){var s=0>i?e.id:e.params[i];if((Xr(s.name)||Nr(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return q(e,r?"FunctionDeclaration":"FunctionExpression")}function ue(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(br),r&&fe.allowTrailingCommas&&D(e))break;t&&we===br?n.push(null):n.push(K(!0))}return n}function le(e){var r=V();return e&&"everywhere"==fe.forbidReserved&&(e=!1),we===De?(!e&&(fe.forbidReserved&&(3===fe.ecmaVersion?Mr:zr)(Ce)||Oe&&Xr(Ce))&&-1==de.slice(ye,ge).indexOf("\\")&&t(ye,"The keyword '"+Ce+"' is reserved"),r.name=Ce):e&&we.keyword?r.name=we.keyword:X(),Ee=!1,U(),q(r,"Identifier")}e.version="0.5.0";var fe,de,pe,me;e.parse=function(e,t){return de=String(e),pe=de.length,r(t),o(),W(fe.program)};var he=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,allowReturnOutsideFunction:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null},ve=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kr.lastIndex=n;var a=Kr.exec(e);if(!(a&&a.index<r))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return Le=ge,g(e),a.start=ye,a.end=ge,a.startLoc=xe,a.endLoc=ke,a.type=we,a.value=Ce,a}de=String(e),pe=de.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(be=e,fe.locations){Ae=1,Se=Kr.lastIndex=0;for(var t;(t=Kr.exec(de))&&t.index<e;)++Ae,Se=t.index+t[0].length}Ee=r,u()},n};var be,ye,ge,xe,ke,we,Ce,Ee,Ae,Se,Ie,Le,Ue,Fe,Re,Oe,Ve=[],Te={type:"num"},qe={type:"regexp"},je={type:"string"},De={type:"name"},Be={type:"eof"},Me={keyword:"break"},ze={keyword:"case",beforeExpr:!0},Xe={keyword:"catch"},Ne={keyword:"continue"},We={keyword:"debugger"},Je={keyword:"default"},Pe={keyword:"do",isLoop:!0},He={keyword:"else",beforeExpr:!0},$e={keyword:"finally"},_e={keyword:"for",isLoop:!0},Ge={keyword:"function"},Ke={keyword:"if"},Qe={keyword:"return",beforeExpr:!0},Ye={keyword:"switch"},Ze={keyword:"throw",beforeExpr:!0},er={keyword:"try"},rr={keyword:"var"},tr={keyword:"while",isLoop:!0},nr={keyword:"with"},ar={keyword:"new",beforeExpr:!0},or={keyword:"this"},ir={keyword:"null",atomValue:null},sr={keyword:"true",atomValue:!0},cr={keyword:"false",atomValue:!1},ur={keyword:"in",binop:7,beforeExpr:!0},lr={"break":Me,"case":ze,"catch":Xe,"continue":Ne,"debugger":We,"default":Je,"do":Pe,"else":He,"finally":$e,"for":_e,"function":Ge,"if":Ke,"return":Qe,"switch":Ye,"throw":Ze,"try":er,"var":rr,"while":tr,"with":nr,"null":ir,"true":sr,"false":cr,"new":ar,"in":ur,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":or,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},fr={type:"[",beforeExpr:!0},dr={type:"]"},pr={type:"{",beforeExpr:!0},mr={type:"}"},hr={type:"(",beforeExpr:!0},vr={type:")"},br={type:",",beforeExpr:!0},yr={type:";",beforeExpr:!0},gr={type:":",beforeExpr:!0},xr={type:"."},kr={type:"?",beforeExpr:!0},wr={binop:10,beforeExpr:!0},Cr={isAssign:!0,beforeExpr:!0},Er={isAssign:!0,beforeExpr:!0},Ar={postfix:!0,prefix:!0,isUpdate:!0},Sr={prefix:!0,beforeExpr:!0},Ir={binop:1,beforeExpr:!0},Lr={binop:2,beforeExpr:!0},Ur={binop:3,beforeExpr:!0},Fr={binop:4,beforeExpr:!0},Rr={binop:5,beforeExpr:!0},Or={binop:6,beforeExpr:!0},Vr={binop:7,beforeExpr:!0},Tr={binop:8,beforeExpr:!0},qr={binop:9,prefix:!0,beforeExpr:!0},jr={binop:10,beforeExpr:!0};e.tokTypes={bracketL:fr,bracketR:dr,braceL:pr,braceR:mr,parenL:hr,parenR:vr,comma:br,semi:yr,colon:gr,dot:xr,question:kr,slash:wr,eq:Cr,name:De,eof:Be,num:Te,regexp:qe,string:je};for(var Dr in lr)e.tokTypes["_"+Dr]=lr[Dr];var Br,Mr=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),zr=n("class enum extends super const export import"),Xr=n("implements interface let package private protected public static yield"),Nr=n("eval arguments"),Wr=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Jr=/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/,Pr="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\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\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\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\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-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\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\u0d60\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-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\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\u2160-\u2188\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-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\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",Hr="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$r=new RegExp("["+Pr+"]"),_r=new RegExp("["+Pr+Hr+"]"),Gr=/[\n\r\u2028\u2029]/,Kr=/\r\n|[\n\r\u2028\u2029]/g,Qr=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$r.test(String.fromCharCode(e))},Yr=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&_r.test(String.fromCharCode(e))},Zr={kind:"loop"},et={kind:"switch"}});

		var binaryOperators = {
			'+': '__add',
			'-': '__subtract',
			'*': '__multiply',
			'/': '__divide',
			'%': '__modulo',
			'==': '__equals',
			'!=': '__equals'
		};

		var unaryOperators = {
			'-': '__negate',
			'+': null
		};

		var fields = Base.each(
			['add', 'subtract', 'multiply', 'divide', 'modulo', 'equals', 'negate'],
			function(name) {
				this['__' + name] = '#' + name;
			},
			{}
		);
		Point.inject(fields);
		Size.inject(fields);
		Color.inject(fields);

		function __$__(left, operator, right) {
			var handler = binaryOperators[operator];
			if (left && left[handler]) {
				var res = left[handler](right);
				return operator === '!=' ? !res : res;
			}
			switch (operator) {
			case '+': return left + right;
			case '-': return left - right;
			case '*': return left * right;
			case '/': return left / right;
			case '%': return left % right;
			case '==': return left == right;
			case '!=': return left != right;
			}
		}

		function $__(operator, value) {
			var handler = unaryOperators[operator];
			if (handler && value && value[handler])
				return value[handler]();
			switch (operator) {
			case '+': return +value;
			case '-': return -value;
			}
		}

		function parse(code, options) {
			return scope.acorn.parse(code, options);
		}

		function compile(code, options) {
			if (!code)
				return '';
			options = options || {};

			var insertions = [];

			function getOffset(offset) {
				for (var i = 0, l = insertions.length; i < l; i++) {
					var insertion = insertions[i];
					if (insertion[0] >= offset)
						break;
					offset += insertion[1];
				}
				return offset;
			}

			function getCode(node) {
				return code.substring(getOffset(node.range[0]),
						getOffset(node.range[1]));
			}

			function getBetween(left, right) {
				return code.substring(getOffset(left.range[1]),
						getOffset(right.range[0]));
			}

			function replaceCode(node, str) {
				var start = getOffset(node.range[0]),
					end = getOffset(node.range[1]),
					insert = 0;
				for (var i = insertions.length - 1; i >= 0; i--) {
					if (start > insertions[i][0]) {
						insert = i + 1;
						break;
					}
				}
				insertions.splice(insert, 0, [start, str.length - end + start]);
				code = code.substring(0, start) + str + code.substring(end);
			}

			function walkAST(node, parent) {
				if (!node)
					return;
				for (var key in node) {
					if (key === 'range' || key === 'loc')
						continue;
					var value = node[key];
					if (Array.isArray(value)) {
						for (var i = 0, l = value.length; i < l; i++)
							walkAST(value[i], node);
					} else if (value && typeof value === 'object') {
						walkAST(value, node);
					}
				}
				switch (node.type) {
				case 'UnaryExpression':
					if (node.operator in unaryOperators
							&& node.argument.type !== 'Literal') {
						var arg = getCode(node.argument);
						replaceCode(node, '$__("' + node.operator + '", '
								+ arg + ')');
					}
					break;
				case 'BinaryExpression':
					if (node.operator in binaryOperators
							&& node.left.type !== 'Literal') {
						var left = getCode(node.left),
							right = getCode(node.right),
							between = getBetween(node.left, node.right),
							operator = node.operator;
						replaceCode(node, '__$__(' + left + ','
								+ between.replace(new RegExp('\\' + operator),
									'"' + operator + '"')
								+ ', ' + right + ')');
					}
					break;
				case 'UpdateExpression':
				case 'AssignmentExpression':
					var parentType = parent && parent.type;
					if (!(
							parentType === 'ForStatement'
							|| parentType === 'BinaryExpression'
								&& /^[=!<>]/.test(parent.operator)
							|| parentType === 'MemberExpression' && parent.computed
					)) {
						if (node.type === 'UpdateExpression') {
							var arg = getCode(node.argument),
								exp = '__$__(' + arg + ', "' + node.operator[0]
										+ '", 1)',
								str = arg + ' = ' + exp;
							if (!node.prefix
									&& (parentType === 'AssignmentExpression'
										|| parentType === 'VariableDeclarator')) {
								if (getCode(parent.left || parent.id) === arg)
									str = exp;
								str = arg + '; ' + str;
							}
							replaceCode(node, str);
						} else {
							if (/^.=$/.test(node.operator)
									&& node.left.type !== 'Literal') {
								var left = getCode(node.left),
									right = getCode(node.right);
								replaceCode(node, left + ' = __$__(' + left + ', "'
										+ node.operator[0] + '", ' + right + ')');
							}
						}
					}
					break;
				}
			}

			function encodeVLQ(value) {
				var res = '',
					base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
				value = (Math.abs(value) << 1) + (value < 0 ? 1 : 0);
				while (value || !res) {
					var next = value & (32 - 1);
					value >>= 5;
					if (value)
						next |= 32;
					res += base64[next];
				}
				return res;
			}

			var url = options.url || '',
				agent = paper.agent,
				version = agent.versionNumber,
				offsetCode = false,
				sourceMaps = options.sourceMaps,
				source = options.source || code,
				lineBreaks = /\r\n|\n|\r/mg,
				offset = options.offset || 0,
				map;
			if (sourceMaps && (agent.chrome && version >= 30
					|| agent.webkit && version >= 537.76
					|| agent.firefox && version >= 23
					|| agent.node)) {
				if (agent.node) {
					offset -= 2;
				} else if (window && url && !window.location.href.indexOf(url)) {
					var html = document.getElementsByTagName('html')[0].innerHTML;
					offset = html.substr(0, html.indexOf(code) + 1).match(
							lineBreaks).length + 1;
				}
				offsetCode = offset > 0 && !(
						agent.chrome && version >= 36 ||
						agent.safari && version >= 600 ||
						agent.firefox && version >= 40 ||
						agent.node);
				var mappings = ['AA' + encodeVLQ(offsetCode ? 0 : offset) + 'A'];
				mappings.length = (code.match(lineBreaks) || []).length + 1
						+ (offsetCode ? offset : 0);
				map = {
					version: 3,
					file: url,
					names:[],
					mappings: mappings.join(';AACA'),
					sourceRoot: '',
					sources: [url],
					sourcesContent: [source]
				};
			}
			walkAST(parse(code, { ranges: true }));
			if (map) {
				if (offsetCode) {
					code = new Array(offset + 1).join('\n') + code;
				}
				if (/^(inline|both)$/.test(sourceMaps)) {
					code += "\n//# sourceMappingURL=data:application/json;base64,"
							+ window.btoa(unescape(encodeURIComponent(
								JSON.stringify(map))));
				}
				code += "\n//# sourceURL=" + (url || 'paperscript');
			}
			return {
				url: url,
				source: source,
				code: code,
				map: map
			};
		}

		function execute(code, scope, options) {
			paper = scope;
			var view = scope.getView(),
				tool = /\btool\.\w+|\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\b/
						.test(code) && !/\bnew\s+Tool\b/.test(code)
							? new Tool() : null,
				toolHandlers = tool ? tool._events : [],
				handlers = ['onFrame', 'onResize'].concat(toolHandlers),
				params = [],
				args = [],
				func,
				compiled = typeof code === 'object' ? code : compile(code, options);
			code = compiled.code;
			function expose(scope, hidden) {
				for (var key in scope) {
					if ((hidden || !/^_/.test(key)) && new RegExp('([\\b\\s\\W]|^)'
							+ key.replace(/\$/g, '\\$') + '\\b').test(code)) {
						params.push(key);
						args.push(scope[key]);
					}
				}
			}
			expose({ __$__: __$__, $__: $__, paper: scope, view: view, tool: tool },
					true);
			expose(scope);
			handlers = Base.each(handlers, function(key) {
				if (new RegExp('\\s+' + key + '\\b').test(code)) {
					params.push(key);
					this.push(key + ': ' + key);
				}
			}, []).join(', ');
			if (handlers)
				code += '\nreturn { ' + handlers + ' };';
			var agent = paper.agent;
			if (document && (agent.chrome
					|| agent.firefox && agent.versionNumber < 40)) {
				var script = document.createElement('script'),
					head = document.head || document.getElementsByTagName('head')[0];
				if (agent.firefox)
					code = '\n' + code;
				script.appendChild(document.createTextNode(
					'paper._execute = function(' + params + ') {' + code + '\n}'
				));
				head.appendChild(script);
				func = paper._execute;
				delete paper._execute;
				head.removeChild(script);
			} else {
				func = Function(params, code);
			}
			var res = func.apply(scope, args) || {};
			Base.each(toolHandlers, function(key) {
				var value = res[key];
				if (value)
					tool[key] = value;
			});
			if (view) {
				if (res.onResize)
					view.setOnResize(res.onResize);
				view.emit('resize', {
					size: view.size,
					delta: new Point()
				});
				if (res.onFrame)
					view.setOnFrame(res.onFrame);
				view.requestUpdate();
			}
			return compiled;
		}

		function loadScript(script) {
			if (/^text\/(?:x-|)paperscript$/.test(script.type)
					&& PaperScope.getAttribute(script, 'ignore') !== 'true') {
				var canvasId = PaperScope.getAttribute(script, 'canvas'),
					canvas = document.getElementById(canvasId),
					src = script.src || script.getAttribute('data-src'),
					async = PaperScope.hasAttribute(script, 'async'),
					scopeAttribute = 'data-paper-scope';
				if (!canvas)
					throw new Error('Unable to find canvas with id "'
							+ canvasId + '"');
				var scope = PaperScope.get(canvas.getAttribute(scopeAttribute))
							|| new PaperScope().setup(canvas);
				canvas.setAttribute(scopeAttribute, scope._id);
				if (src) {
					Http.request({
						url: src,
						async: async,
						mimeType: 'text/plain',
						onLoad: function(code) {
							execute(code, scope, src);
						}
					});
				} else {
					execute(script.innerHTML, scope, script.baseURI);
				}
				script.setAttribute('data-paper-ignore', 'true');
				return scope;
			}
		}

		function loadAll() {
			Base.each(document && document.getElementsByTagName('script'),
					loadScript);
		}

		function load(script) {
			return script ? loadScript(script) : loadAll();
		}

		if (window) {
			if (document.readyState === 'complete') {
				setTimeout(loadAll);
			} else {
				DomEvent.add(window, { load: loadAll });
			}
		}

		return {
			compile: compile,
			execute: execute,
			load: load,
			parse: parse
		};

	}.call(this);

	paper = new (PaperScope.inject(Base.exports, {
		enumerable: true,
		Base: Base,
		Numerical: Numerical,
		Key: Key,
		DomEvent: DomEvent,
		DomElement: DomElement,
		document: document,
		window: window,
		Symbol: SymbolDefinition,
		PlacedSymbol: SymbolItem
	}))();

	if (paper.agent.node)
		__webpack_require__(465)(paper);

	if (true) {
		!(__WEBPACK_AMD_DEFINE_FACTORY__ = (paper), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	} else if (typeof module === 'object' && module) {
		module.exports = paper;
	}

	return paper;
	}.call(this, typeof self === 'object' ? self : null);


/***/ },
/* 464 */
/***/ function(module, exports) {

	/* (ignored) */

/***/ },
/* 465 */
/***/ function(module, exports) {

	/* (ignored) */

/***/ },
/* 466 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["Graph"] = __webpack_require__(467);
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 467 */
/***/ function(module, exports) {

	"use strict";

	module.exports = { data: {} };

/***/ },
/* 468 */
/***/ function(module, exports) {

	"use strict";

	Graph.colors = {
	  grid: {
	    fill: "#19191e"
	  },
	  unavailable: {
	    fill: "#46484c",
	    stroke: "#6f7278",
	    strokeSize: 3,
	    text: "#6f7278",
	    link: "#666666"
	  },
	  available: {
	    fill: "#46464c",
	    stroke: "white",
	    strokeSize: 10,
	    text: "white",
	    link: "white"
	  },
	  not_recommended: {
	    fill: "#46464c",
	    stroke: "#E6B291",
	    strokeSize: 10,
	    text: "#E6B291",
	    link: "white"
	  },
	  done: {
	    fill: "#00BABC",
	    stroke: "#00BABC",
	    strokeSize: 10,
	    text: "white",
	    link: "#00BABC"
	  },
	  fail: {
	    fill: "#cc6256",
	    stroke: "#cc6256",
	    strokeSize: 3,
	    text: "white",
	    link: "#cc6256"
	  },
	  in_progress: {
	    fill: "#46464c",
	    stroke: "#00BABC",
	    strokeSize: 3,
	    text: "#00BABC",
	    link: "#00BABC"
	  },
	  selected_layer: {
	    stroke: "#fff000",
	    strokeSize: 10,
	    glow: "#fff"
	  }
	};

/***/ },
/* 469 */
/***/ function(module, exports) {

	'use strict';

	Graph.styles = {
	  unavailable: {
	    strokeColor: Graph.colors['unavailable'].stroke,
	    strokeWidth: 3,
	    fillColor: Graph.colors['unavailable'].fill,
	    text: {
	      fontFamily: 'Noto Sans',
	      fontWeight: 'bold',
	      fontSize: 20,
	      fillColor: Graph.colors['unavailable'].text,
	      justification: 'center'
	    }
	  },
	  available: {
	    strokeColor: Graph.colors['available'].stroke,
	    strokeWidth: 10,
	    fillColor: Graph.colors['available'].fill,
	    text: {
	      fontFamily: 'Noto Sans',
	      fontWeight: 'bold',
	      fontSize: 20,
	      fillColor: Graph.colors['available'].text,
	      justification: 'center'
	    }
	  },
	  not_recommended: {
	    strokeColor: Graph.colors['not_recommended'].stroke,
	    strokeWidth: 10,
	    fillColor: Graph.colors['not_recommended'].fill,
	    text: {
	      fontFamily: 'Noto Sans',
	      fontWeight: 'bold',
	      fontSize: 20,
	      fillColor: Graph.colors['not_recommended'].text,
	      justification: 'center'
	    }
	  },
	  done: {
	    strokeColor: Graph.colors['done'].stroke,
	    strokeWidth: 10,
	    fillColor: Graph.colors['done'].fill,
	    text: {
	      fontFamily: 'Noto Sans',
	      fontWeight: 'bold',
	      fontSize: 20,
	      fillColor: Graph.colors['done'].text,
	      justification: 'center'
	    }
	  },
	  fail: {
	    strokeColor: Graph.colors['fail'].stroke,
	    strokeWidth: 3,
	    fillColor: Graph.colors['fail'].fill,
	    text: {
	      fontFamily: 'Noto Sans',
	      fontWeight: 'bold',
	      fontSize: 20,
	      fillColor: Graph.colors['fail'].text,
	      justification: 'center'
	    }
	  },
	  in_progress: {
	    strokeColor: Graph.colors['in_progress'].stroke,
	    strokeWidth: 3,
	    fillColor: Graph.colors['in_progress'].fill,
	    text: {
	      fontFamily: 'Noto Sans',
	      fontWeight: 'bold',
	      fontSize: 20,
	      fillColor: Graph.colors['in_progress'].text,
	      justification: 'center'
	    }
	  },
	  selected_layer: {
	    strokeColor: Graph.colors['selected_layer'].stroke,
	    strokeWidth: 10
	  }
	};

/***/ },
/* 470 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	Graph.grid = {
	  draw: function draw(layer, width, height) {
	    layer.activate();
	    new _paper2.default.Path.Rectangle({ from: [0, 0], to: [width, height] });
	  }
	};

/***/ },
/* 471 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var $description = (0, _jquery2.default)('#graph_description');
	var _template = _lodash2.default.template((0, _jquery2.default)('script.graph_description_template').html());
	var set_time_out_handler = null;

	Graph.description = {
	  refresh_vars: function refresh_vars() {
	    $description = (0, _jquery2.default)('#graph_description');
	    _template = _lodash2.default.template((0, _jquery2.default)('script.graph_description_template').html());
	  },
	  show: function show(project_id) {
	    var project = _lodash2.default.find(Graph.data.projects, { project_id: project_id });
	    clearTimeout(set_time_out_handler);
	    set_time_out_handler = setTimeout(function () {
	      $description.html(_template(project)).fadeIn('fast');
	    }, 200);
	  },
	  hide: function hide() {
	    $description.fadeOut(0, function () {
	      $description.empty();
	    });
	  },
	  is_visible: function is_visible() {
	    return $description.is(':visible');
	  },
	  click_on_link: function click_on_link() {
	    if ($description.is(':visible')) document.location = $description.find('.header > a')[0].href;
	  }
	};

/***/ },
/* 472 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var lastMousePosition = null;
	var scaling = false;
	var scaling_distance = null;

	var changeZoom = function changeZoom(view, delta, mousePosition) {
	  var viewPosition = view.viewToProject(mousePosition);
	  var newZoom = getNewZoom(view, delta);
	  var beta = view.zoom / newZoom;
	  var pc = viewPosition.subtract(view.center);
	  var offset = viewPosition.subtract(pc.multiply(beta)).subtract(view.center);
	  view.zoom = newZoom;
	  if (delta > 0) changeOffset(view, offset);
	  view.center = view.center.add(offset);
	};

	var getNewZoom = function getNewZoom(view, delta) {
	  var factor = 1.08;
	  var minZoom = getMinZoom(view);
	  var maxZoom = getMaxZoom(view);
	  if (delta < 0) return view.zoom * factor > maxZoom ? maxZoom : view.zoom * factor;
	  if (delta > 0) return view.zoom / factor < minZoom ? minZoom : view.zoom / factor;
	  return view.zoom;
	};

	var getMinZoom = function getMinZoom(view) {
	  return view.viewSize.height / view._project._activeLayer.getBounds().height;
	};

	var getMaxZoom = function getMaxZoom(view) {
	  return 1.8;
	};

	var changeOffset = function changeOffset(view, offset) {
	  var viewBounds = view.getBounds();
	  var layerBounds = view._project._activeLayer.getBounds();
	  if (view.center.y + offset.y < viewBounds.height / 2) // TOP
	    offset.y = viewBounds.height / 2 - view.center.y;
	  if (view.center.y + offset.y + viewBounds.height / 2 > layerBounds.height) // BOTTOM
	    offset.y = layerBounds.height - view.center.y - viewBounds.height / 2;
	  if (view.center.x + offset.x < viewBounds.width / 2) // LEFT
	    offset.x = viewBounds.width / 2 - view.center.x;
	  if (view.center.x + offset.x + viewBounds.width / 2 > layerBounds.width) // RIGHT
	    offset.x = layerBounds.width - view.center.x - viewBounds.width / 2;
	  if (viewBounds.width > layerBounds.width) offset.x = offset.x + (viewBounds.width - layerBounds.width) / 2;
	  if (viewBounds.height > layerBounds.height) offset.y = offset.y + (viewBounds.height - layerBounds.height) / 2;
	};

	var on_frame_callback = [];

	Graph.zoom_handler = {
	  on_frame: function on_frame() {
	    _lodash2.default.each(on_frame_callback, function (cb) {
	      return cb();
	    });
	  },

	  zoom_to: function zoom_to(center_point, zoom_factor) {
	    var max_zoom = getMaxZoom(_paper2.default.view);
	    var zoom_limit = zoom_factor && _paper2.default.view.zoom * zoom_factor < max_zoom ? _paper2.default.view.zoom * zoom_factor : max_zoom;
	    var cb = function cb() {
	      var current_zoom = _paper2.default.view.zoom;
	      if (current_zoom >= zoom_limit) on_frame_callback = on_frame_callback.slice(on_frame_callback.indexOf(cb), 0);else {
	        if (current_zoom < zoom_limit) Graph.zoom_handler.zoom_in();
	        Graph.zoom_handler.changeCenter(_paper2.default.view, center_point.subtract(_paper2.default.view.center), 0.3);
	      }
	    };
	    on_frame_callback.push(cb);
	  },

	  zoom_in: function zoom_in() {
	    var factor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1.08;

	    var wanted_zoom = _paper2.default.view.zoom * factor;
	    var max_zoom = getMaxZoom(_paper2.default.view);
	    _paper2.default.view.zoom = wanted_zoom > max_zoom ? max_zoom : wanted_zoom;
	  },

	  zoom_out: function zoom_out() {
	    var wanted_zoom = _paper2.default.view.zoom + _paper2.default.view.zoom * -0.08;
	    var min_zoom = getMinZoom(_paper2.default.view);
	    _paper2.default.view.zoom = wanted_zoom < min_zoom ? min_zoom : wanted_zoom;
	  },

	  reset_zoom: function reset_zoom(center_point) {
	    _paper2.default.view.center = center_point;
	    _paper2.default.view.zoom = getMinZoom(_paper2.default.view);
	  },

	  changeCenter: function changeCenter(view, offset, factor) {
	    offset = offset.multiply(factor);
	    changeOffset(view, offset);
	    view.center = view.center.add(offset);
	  },

	  bind: function bind($canvas) {
	    $canvas.mousewheel(function (event) {
	      if (event.shiftKey) {
	        Graph.zoom_handler.changeCenter(_paper2.default.view, new _paper2.default.Point(event.deltaX, -event.deltaY), event.deltaFactor);
	        event.preventDefault();
	      } else {
	        lastMousePosition = new _paper2.default.Point(event.offsetX, event.offsetY);
	        changeZoom(_paper2.default.view, -1 * event.deltaY, lastMousePosition);
	        event.preventDefault();
	        _paper2.default.view.draw();
	      }
	    });

	    // re-center after a resize window
	    _paper2.default.view.onresize = function () {
	      changeZoom(_paper2.default.view, 0, lastMousePosition);
	      _paper2.default.view.draw();
	    };

	    $canvas.on('touchstart', function (e) {
	      if (e.originalEvent.touches.length === 2) scaling = true;
	    });

	    $canvas.on('touchmove', function (e) {
	      if (scaling) {
	        var touches = e.originalEvent.touches;
	        var distance = Math.sqrt((touches[0].pageX - touches[1].pageX) * (touches[0].pageX - touches[1].pageX) + (touches[0].pageY - touches[1].pageY) * (touches[0].pageY - touches[1].pageY));
	        if (scaling_distance) {
	          if (scaling_distance < distance) Graph.zoom_handler.zoom_in();
	          if (scaling_distance > distance) Graph.zoom_handler.zoom_out();
	          scaling_distance = distance;
	        }
	      }
	    });

	    $canvas.on('touchend', function (e) {
	      scaling = false;
	      scaling_distance = null;
	    });
	  }
	};

/***/ },
/* 473 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	var _search = __webpack_require__(375);

	var _search2 = _interopRequireDefault(_search);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var limit_double_click = 200;
	var mouse_down_point = null;
	var last_mouse_up_time = new Date();

	Graph.mouse_handler = {

	  on_mouse_move: function on_mouse_move(e) {
	    if (this.projects_layer.contains(e.point)) document.body.style.cursor = "pointer";else document.body.style.cursor = "default";
	  },

	  on_mouse_up: function on_mouse_up(e) {
	    mouse_down_point = null;
	    // Does the user click on projects ?
	    if (this.projects_layer.contains(e.point)) {
	      // Select the clicked projects
	      var projects_clicked = _lodash2.default.filter(Graph.data.projects, function (project) {
	        return '$box' in project && project['$box'].contains(e.point);
	      });
	      if (projects_clicked.length > 0 && e.event.which == 2) window.open('/projects/' + projects_clicked[0].slug, '_blank');
	      Graph.project.select(projects_clicked, new Date() - last_mouse_up_time < limit_double_click);
	    } else {
	      if (new Date() - last_mouse_up_time < limit_double_click) {
	        var point = new _paper2.default.Point(e.event.offsetX, e.event.offsetY);
	        Graph.zoom_handler.zoom_to(_paper2.default.view.viewToProject(point), 3);
	      }
	      // Unselect all the projects
	      Graph.project.unselect();
	    }
	    last_mouse_up_time = new Date();
	    Graph.help.hide();
	    Graph.search.hide();
	  },

	  on_mouse_drag: function on_mouse_drag(e) {
	    var delta = e.point.subtract(mouse_down_point);
	    var factor = -1 * _paper2.default.view.zoom / 2;
	    Graph.zoom_handler.changeCenter(_paper2.default.view, delta, factor);
	  },

	  onMouseDown: function onMouseDown(e) {
	    mouse_down_point = e.point;
	    var typeaheadsearch = new _search2.default();
	    typeaheadsearch.input.blur();
	  },

	  bind: function bind(graph) {
	    graph.tool.onMouseDrag = Graph.mouse_handler.on_mouse_drag;
	    graph.tool.onMouseMove = Graph.mouse_handler.on_mouse_move.bind(graph);
	    graph.tool.onMouseUp = Graph.mouse_handler.on_mouse_up.bind(graph);
	    graph.tool.onMouseDown = Graph.mouse_handler.onMouseDown.bind(graph);
	  }
	};

/***/ },
/* 474 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var $intra_search = (0, _jquery2.default)('.search-input[name="query"]');

	var keys_pressed = {
	  'shift': false,
	  '+': false,
	  '-': false,
	  'up': false,
	  'down': false,
	  'left': false,
	  'right': false
	};

	var target_is_on_graph = function target_is_on_graph(e) {
	  return e.event.target != $intra_search[0];
	};

	var on_escape = function on_escape() {
	  Graph.project.unselect();
	  Graph.search.on_escape();
	  Graph.help.hide();
	};

	var on_key_up = function on_key_up(e) {
	  if (!target_is_on_graph(e)) return;
	  if (!_lodash2.default.isUndefined(keys_pressed[e.key])) keys_pressed[e.key] = false;
	  if (e.key === 'escape') // Quit current action
	    on_escape();else if (e.key === 'h' || e.key == '?') // Help
	    Graph.help.toggle();else if (e.key === 's' || e.key == '/') // Search
	    Graph.search.show();else if (e.key === 'c') // Cursus
	    Graph.cursus.toggle();else if (e.key === 'enter') // Cursus
	    Graph.description.click_on_link();
	};

	var on_key_down = function on_key_down(e) {
	  if (!target_is_on_graph(e)) return;
	  if (!_lodash2.default.isUndefined(keys_pressed[e.key])) keys_pressed[e.key] = true;
	};

	Graph.key_handler = {
	  refresh_vars: function refresh_vars() {
	    $intra_search = (0, _jquery2.default)('.search-input[name="query"]');
	  },
	  is_pressed: function is_pressed(key) {
	    return keys_pressed[key];
	  },
	  bind: function bind(graph) {
	    graph.tool.onKeyUp = on_key_up;
	    graph.tool.onKeyDown = on_key_down;
	  }
	};

/***/ },
/* 475 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var point = null;

	var onFrame = function onFrame(e) {
	  if (Graph.key_handler.is_pressed("shift")) {
	    if (Graph.key_handler.is_pressed("up")) Graph.zoom_handler.changeCenter(_paper2.default.view, point.set(0, -10), 1);
	    if (Graph.key_handler.is_pressed("down")) Graph.zoom_handler.changeCenter(_paper2.default.view, point.set(0, 10), 1);
	    if (Graph.key_handler.is_pressed("left")) Graph.zoom_handler.changeCenter(_paper2.default.view, point.set(-10, 0), 1);
	    if (Graph.key_handler.is_pressed("right")) Graph.zoom_handler.changeCenter(_paper2.default.view, point.set(10, 0), 1);
	  }
	  if (Graph.key_handler.is_pressed("+")) Graph.zoom_handler.zoom_in();
	  if (Graph.key_handler.is_pressed("-")) Graph.zoom_handler.zoom_out();
	  Graph.zoom_handler.on_frame();
	};

	Graph.animation_handler = {
	  bind: function bind() {
	    point = new _paper2.default.Point(0, 0);
	    _paper2.default.view.onFrame = onFrame;
	  }
	};

/***/ },
/* 476 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _slicedToArray = function () { function sliceIterator(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"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var is_an_internship = function is_an_internship(project) {
	  return project.kind.slice(-10) === 'internship';
	};

	var glow = function glow(project, active) {
	  var conf = {
	    shadowBlur: 0,
	    shadowColor: null,
	    shadowOffset: null
	  };

	  if (active) {
	    conf = {
	      shadowBlur: 180 * _paper2.default.view.zoom,
	      shadowColor: Graph.colors[project.state].stroke,
	      shadowOffset: new _paper2.default.Point(0, 0)
	    };
	    if (project.highlighted === true) {
	      conf.shadowBlur = 400 * _paper2.default.view.zoom;
	      conf.shadowColor = Graph.colors['selected_layer'].glow;
	    }
	  }
	  project['$box'].set(conf);
	  if (project['$box_internship']) project['$box_internship'].set(conf);
	  _paper2.default.view.draw();
	};

	var circle = function circle(project, active) {
	  var conf = {
	    shadowBlur: 0,
	    shadowColor: null,
	    shadowOffset: null,
	    strokeColor: Graph.colors[project.state].stroke,
	    strokeWidth: Graph.colors[project.state].strokeSize
	  };

	  if (active) {
	    conf = {
	      shadowBlur: 300 * _paper2.default.view.zoom,
	      shadowColor: Graph.colors['selected_layer'].stroke,
	      shadowOffset: new _paper2.default.Point(0, 0),
	      strokeColor: Graph.colors['selected_layer'].stroke,
	      strokeWidth: Graph.colors['selected_layer'].strokeSize
	    };
	  }
	  project['$box'].set(conf);
	  if (project['$box_internship']) project['$box_internship'].set(conf);
	  _paper2.default.view.draw();
	};

	Graph.project = {
	  draw: function draw(project, layers) {
	    var layer = layers[is_an_internship(project) ? 'internship' : 'project'];
	    layer.activate();
	    project.selected = false;
	    var draw_fct = Graph.project['draw_default'];
	    if ('draw_' + project.kind in Graph.project) draw_fct = Graph.project['draw_' + project.kind];
	    draw_fct(project, layers, function (options) {
	      layers.project.activate();
	      Graph.project.draw_label(project);
	      Graph.project.set_style(project, options);
	    });
	  },

	  set_style: function set_style(project, options) {
	    if (project['$box']) project['$box'].style = Graph.styles[project.state];
	  },

	  // draw the rush box
	  draw_default: function draw_default(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 50 });
	    cb();
	  },

	  // draw inner_solo
	  draw_inner_solo: function draw_inner_solo(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 50 });
	    cb();
	  },

	  // draw inner_exam
	  draw_inner_exam: function draw_inner_exam(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Rectangle({ center: [project.x, project.y], size: new _paper2.default.Size(120, 60), radius: 25 });
	    cb();
	  },

	  // draw inner_planet
	  draw_inner_planet: function draw_inner_planet(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 30 });
	    cb();
	  },

	  // draw inner_satellite
	  draw_inner_satellite: function draw_inner_satellite(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 20 });
	    cb();
	  },

	  // draw inner_linked
	  draw_inner_linked: function draw_inner_linked(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 50 });
	    cb();
	  },

	  // draw inner_big
	  draw_inner_big: function draw_inner_big(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 75 });
	    cb();
	  },

	  // draw the internship box
	  draw_first_internship: function draw_first_internship(project, layers, cb) {
	    var radius = 1000;
	    layers['internship'].activate();
	    project['$box_internship'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: radius, style: _lodash2.default.assign(_lodash2.default.cloneDeep(Graph.styles[project.state]), { fillColor: null }) });
	    layers['project'].activate();
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x + Math.cos(Math.PI / 4) * radius, project.y + Math.cos(Math.PI / 4) * radius], radius: 100, style: Graph.styles[project.state] });
	    cb();
	  },

	  // draw the second internship box
	  draw_second_internship: function draw_second_internship(project, layers, cb) {
	    var radius = 2200;
	    layers['internship'].activate();
	    project['$box_internship'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: radius, style: _lodash2.default.assign(_lodash2.default.cloneDeep(Graph.styles[project.state]), { fillColor: null }) });
	    layers['project'].activate();
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x + Math.cos(Math.PI / 4) * radius, project.y + Math.cos(Math.PI / 4) * radius], radius: 100, style: Graph.styles[project.state] });
	    cb();
	  },

	  // draw the rush box
	  draw_rush: function draw_rush(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Rectangle({ center: [project.x, project.y], size: new _paper2.default.Size(120, 60), radius: 25 });
	    cb();
	  },

	  // draw the exam box
	  draw_exam: function draw_exam(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 80 });
	    cb();
	  },

	  // draw the project box
	  draw_part_time: function draw_part_time(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 150 });
	    cb();
	  },

	  // draw the project box
	  draw_project: function draw_project(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 50 });
	    cb();
	  },

	  // draw the project box
	  draw_big_project: function draw_big_project(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Circle({ center: [project.x, project.y], radius: 70 });
	    cb();
	  },

	  // draw the piscine box
	  draw_piscine: function draw_piscine(project, layers, cb) {
	    project['$box'] = new _paper2.default.Path.Rectangle({ center: [project.x, project.y], size: new _paper2.default.Size(180, 60) });
	    cb();
	  },

	  // draw the label box
	  draw_label: function draw_label(project) {
	    // get point on circle from angle
	    var get_point_on_circle = function get_point_on_circle(x, y, radius, angle) {
	      return new _paper2.default.Point([parseInt(radius * Math.cos(angle * Math.PI / 180), 10) + x, parseInt(radius * Math.sin(angle * Math.PI / 180), 10) + y]);
	    };

	    var fit_label = function fit_label(label, size) {
	      label.scale(label.bounds.width > size.width - 10 ? (size.width - 10) * 100 / label.bounds.width / 100 : 1);
	    };

	    // create the item label
	    var create_label = function create_label(point, size, project) {
	      point.y += 5;
	      var label = new _paper2.default.PointText({ point: point, content: project.name, style: Graph.styles[project.state].text });
	      fit_label(label, size);
	    };

	    var _ref = function () {
	      var bounds = project['$box'].getBounds();
	      return [new _paper2.default.Point(bounds.center), new _paper2.default.Size(bounds)];
	    }(),
	        _ref2 = _slicedToArray(_ref, 2),
	        point = _ref2[0],
	        size = _ref2[1];

	    create_label(point, size, project);
	  },

	  select: function select(projects, to_zoom) {
	    Graph.project.unselect().then(function () {
	      Graph.search.hide();
	      // Show the description if nbProject selected is 1
	      if (projects.length === 1) Graph.description.show(projects[0].project_id);
	      // Graphical display on selected projects
	      _lodash2.default.each(projects, function (project) {
	        project.selected = true;
	        glow(project, true);
	      });
	      // Zoom
	      if (to_zoom) Graph.zoom_handler.zoom_to(_lodash2.default.last(projects)['$box'].position);
	    });
	  },

	  unselect: function unselect() {
	    return new Promise(function (done) {
	      // Hide the description
	      Graph.description.hide();
	      // Remove graphical display on previous selected projects
	      _lodash2.default.each(_lodash2.default.filter(Graph.data.projects, { selected: true }), function (project) {
	        project.selected = false;
	        glow(project, false);
	        if (project.highlighted === true) circle(project, true);
	      });
	      done();
	    });
	  },

	  highlight: function highlight(projects) {
	    Graph.project.unhighlight().then(function () {
	      _lodash2.default.each(projects, function (project) {
	        project.highlighted = true;
	        circle(project, true);
	      });
	    });
	  },

	  unhighlight: function unhighlight() {
	    return new Promise(function (done) {
	      _lodash2.default.each(_lodash2.default.filter(Graph.data.projects, { highlighted: true }), function (project) {
	        project.highlighted = false;
	        circle(project, false);
	        if (project.select === true) glow(project, true);
	      });
	      done();
	    });
	  }
	};

/***/ },
/* 477 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var get_style = function get_style(project, link) {
	  var parent_project = _lodash2.default.find(Graph.data.projects, function (p) {
	    return p.project_id == link.parent_id;
	  });
	  return {
	    strokeWidth: 10,
	    strokeColor: !parent_project || parent_project.state === 'done' ? Graph.colors[project.state].link : Graph.colors['unavailable'].link
	  };
	};

	Graph.link = {
	  draw: function draw(layer, project) {
	    if (project.by === undefined) return;
	    layer.activate();
	    project['$links'] = [];
	    _lodash2.default.each(project.by, function (link) {
	      project['$links'].push(new _paper2.default.Path({ segments: link.points, style: get_style(project, link) }));
	    });
	  }
	};

/***/ },
/* 478 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var $search = (0, _jquery2.default)('#graph_search');
	var $icon = (0, _jquery2.default)('#graph_search_icon');

	var on_select_project = function on_select_project(obj, datum) {
	  return Graph.project.select(_lodash2.default.filter(Graph.data.projects, { project_id: datum.project_id }), true);
	};

	Graph.search = {
	  refresh_vars: function refresh_vars() {
	    $search = (0, _jquery2.default)('#graph_search');
	    $icon = (0, _jquery2.default)('#graph_search_icon');
	  },

	  show: function show() {
	    Graph.description.hide();
	    Graph.help.hide();
	    $search.parent('span').fadeIn('fast');
	    $search.fadeIn('fast').focus();
	    $icon.fadeTo(200, 0);
	  },

	  hide: function hide() {
	    $search.typeahead('val', '');
	    $search.fadeOut('fast');
	    $search.parent('span').fadeOut('fast');
	    $icon.fadeTo(200, 1);
	  },

	  is_visible: function is_visible() {
	    return $search.is(':visible');
	  },

	  toggle: function toggle() {
	    if (Graph.search.is_visible()) Graph.search.hide();else Graph.search.show();
	  },

	  on_escape: function on_escape() {
	    if (Graph.search.is_visible()) {
	      if ($search.typeahead('val').length === 0) Graph.search.hide();else $search.typeahead('val', '');
	    }
	  },

	  _search_project: function _search_project(q, cb) {
	    var matches, substrRegex;

	    // an array that will be populated with substring matches
	    matches = [];

	    // regex used to determine if a string contains the substring `q`
	    substrRegex = new RegExp(q, 'i');

	    // iterate through the pool of strings and for any string that
	    // contains the substring `q`, add it to the `matches` array
	    _jquery2.default.each(Graph.data.projects, function (i, project) {
	      if (substrRegex.test(project.name)) {
	        matches.push({ name: project.name, project_id: project.project_id });
	      }
	    });

	    cb(matches);
	  },

	  bind: function bind() {
	    $search.typeahead({
	      minLength: 1,
	      highlight: true
	    }, {
	      name: 'projects',
	      displayKey: 'name',
	      source: Graph.search._search_project
	    });
	    $search.on('typeahead:selected', on_select_project);
	    $icon.on('click', Graph.search.show);
	    Graph.search.hide();
	  }
	};

/***/ },
/* 479 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var $layer_select = (0, _jquery2.default)('#graph_layer');

	Graph.layer = {
	    refresh_vars: function refresh_vars() {
	        $layer_select = (0, _jquery2.default)('#graph_layer');
	    },
	    show: function show(ids) {
	        Graph.project.unhighlight();
	        if (ids.length === 0) return;
	        _jquery2.default.each(JSON.parse(ids), function (i, id) {
	            Graph.project.highlight(_lodash2.default.filter(Graph.data.projects, { project_id: id }));
	        });
	    },
	    bind: function bind() {
	        $layer_select.change(function () {
	            Graph.layer.show((0, _jquery2.default)(this).val());
	        });
	    }
	};

/***/ },
/* 480 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var $help = (0, _jquery2.default)('#graph_help');
	var $helpIcon = (0, _jquery2.default)('#graph_help_icon');

	Graph.help = {
	  refresh_vars: function refresh_vars() {
	    $help = (0, _jquery2.default)('#graph_help');
	    var $helpIcon = (0, _jquery2.default)('#graph_help_icon');
	  },
	  show: function show(project_id) {
	    if (Graph.search.is_visible()) return;
	    Graph.project.unselect();
	    $help.fadeIn('fast');
	    Graph.search.hide();
	  },
	  hide: function hide() {
	    if (Graph.help.is_visible()) $help.fadeOut('fast');
	  },
	  toggle: function toggle() {
	    if (Graph.help.is_visible()) Graph.help.hide();else Graph.help.show();
	  },
	  is_visible: function is_visible() {
	    return $help.is(':visible');
	  },
	  bind: function bind() {
	    $helpIcon.on('click', Graph.help.toggle);
	  }
	};

/***/ },
/* 481 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var $cursus_selector = (0, _jquery2.default)('#graph_cursus');

	Graph.cursus = {
	  refresh_vars: function refresh_vars() {
	    $cursus_selector = (0, _jquery2.default)('#graph_cursus');
	  },
	  show: function show() {
	    if (Graph.search.is_visible()) return;
	    Graph.description.hide();
	    Graph.help.hide();
	    if (document.createEvent) {
	      var e = document.createEvent("MouseEvents");
	      e.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
	      $cursus_selector[0].dispatchEvent(e);
	    } else if (element.fireEvent) {
	      $cursus_selector.trigger("onmousedown");
	    }
	  },
	  toggle: function toggle() {
	    if (!Graph.cursus.is_visible()) Graph.cursus.show();
	  },
	  is_visible: function is_visible() {
	    return $cursus_selector.is(':selected');
	  }
	};

/***/ },
/* 482 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _lodash = __webpack_require__(7);

	var _lodash2 = _interopRequireDefault(_lodash);

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	__webpack_require__(483);

	var _util = __webpack_require__(484);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	//angle is in degree

	var hack = {};
	hack.list = {
		21: { //42cursus
			"radius": 1000,
			"circles": [{
				"projects": [{
					"kind": "inner_solo",
					"id": 1314 //libft
				}], //circle 0
				"angle": 0
			}, {
				"projects": [{
					"kind": "inner_solo",
					"id": 1327 //gnl

				}, {
					"kind": "inner_solo",
					"id": 1316 //printf
				}, {
					"kind": "inner_solo",
					"id": 1994 // born2beroot
				}], //circle 1
				"angle": 0
			}, {
				"projects": [{
					"kind": "inner_linked",
					"ids": [1476, // fractol
					2008, // fdf
					2009 // so_long
					]
				}, {
					"kind": "inner_linked",
					"ids": [2004, // pipex
					2005 // minitalk
					]
				}, {
					"kind": "inner_solo",
					"id": 1471 // push_swap
				}, {
					"kind": "inner_solo",
					"id": 1328 //ft_server
				}, {
					"kind": "inner_exam",
					"id": 1320
				}], //circle 2
				"angle": 75
			}, {
				"projects": [{
					"kind": "inner_solo",
					"id": 1334 //philosophers
				}, {
					"kind": "inner_solo",
					"id": 1331 //minishell
				}, {
					"kind": "inner_exam",
					"id": 1321
				}], //circle 3
				"angle": -65
			}, {
				"projects": [{
					"kind": "inner_planet",
					"satellites": [1338, //cpp-module-00
					1339, //cpp-module-01
					1340, //cpp-module-02
					1341, //cpp-module-03
					1342 //cpp-module-04
					]
				}, {
					"kind": "inner_linked",
					"ids": [1315, //minirt
					1326 //cub3d
					]
				}, {
					"kind": "inner_solo",
					"id": 2007 //netpractice
				}, {
					"kind": "inner_exam",
					"id": 1322
				}], //circle 4
				"angle": 150
			}, {
				"projects": [{
					"kind": "inner_linked",
					"ids": [1336, //IRC
					1332 //WEBSERV
					]
				}, {
					"kind": "inner_planet",
					"satellites": [1343, //cpp-module-05
					1344, //cpp-module-06
					1345, //cpp-module-07
					1346, //cpp-module-08
					2309 //cpp-module-09
					]
				}, {
					"kind": "inner_linked",
					"ids": [1329, //ft_services
					1983 //inception
					]
				}, {
					"kind": "inner_exam",
					"id": 1323
				}], //circle 5
				"angle": -150
			}, {
				"projects": [{
					"kind": "inner_big",
					"id": 1337
				}, {
					"kind": "inner_exam",
					"id": 1324
				}], //circle 6
				"angle": 50
			}],
			"projects": {}
		}
	};

	function position_on_circle(center, radius, start_angle, number_of_elem_on_circle, elem_number) {
		start_angle = start_angle * Math.PI / 180;
		var angle = Math.PI * 2 * elem_number / number_of_elem_on_circle;
		return new _paper2.default.Point(Math.sin(start_angle + angle) * radius + center.x, Math.cos(start_angle + angle) * radius + center.y);
	}

	function circle_intersection(c1, r1, c2, r2) {
		var x1 = c1.x;
		var x2 = c2.x;
		var y1 = c1.y;
		var y2 = c2.y;
		var dx = x2 - x1;
		var dy = y2 - y1;
		var d = Math.sqrt(dx * dx + dy * dy);
		if (d > r1 + r2) {
			return undefined;
		}
		if (d < Math.abs(r1 - r2)) {
			return undefined;
		}
		if (d == 0 && r1 == r2) {
			return undefined;
		}
		var a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
		var h = Math.sqrt(r1 * r1 - a * a);
		var xm = x1 + a * dx / d;
		var ym = y1 + a * dy / d;
		var xs1 = xm + h * dy / d;
		var xs2 = xm - h * dy / d;
		var ys1 = ym - h * dx / d;
		var ys2 = ym + h * dx / d;
		return [new _paper2.default.Point(xs1, ys1), new _paper2.default.Point(xs2, ys2)];
	}

	function movePoint2OnCircle(x1, y1, x2, y2, cx, cy, radius) {

		var dx = x2 - x1;
		var dy = y2 - y1;

		var A = dx * dx + dy * dy;
		var B = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
		var C = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy) - radius * radius;

		var det = B * B - 4 * A * C;

		if (A <= 0.0000001 || det < 0) return [x2, y2];
		var t = (-B - Math.sqrt(det)) / (2 * A);
		return [x1 + t * dx, y1 + t * dy];
	}

	function calculate_linked_centers(center, nb_proj, radius, circle_center, circle_radius) {
		if (nb_proj <= 0) return [];
		if (nb_proj == 1) return [center];
		var l = Math.sqrt(2 * circle_radius * (circle_radius - Math.sqrt(circle_radius * circle_radius - radius * radius)));
		var ret = new Array(nb_proj);
		var last_left = center;
		var last_right = center;
		var i = 0;
		var mid_proj = Math.floor(nb_proj / 2);
		if (nb_proj % 2) {
			ret[mid_proj] = center;
		} else {
			var inter = circle_intersection(center, l, circle_center, circle_radius);
			last_left = inter[0];
			last_right = inter[1];
			ret[mid_proj - 1] = last_left;
			ret[mid_proj] = last_right;
			i++;
		}
		while (i < mid_proj) {

			last_left = circle_intersection(last_left, 2 * l, circle_center, circle_radius)[0];
			last_right = circle_intersection(last_right, 2 * l, circle_center, circle_radius)[1];
			ret[mid_proj - 1 - i] = last_left;
			ret[mid_proj + i + nb_proj % 2] = last_right;
			i++;
		}
		return ret;
	}

	function init() {
		for (var cursus_id in hack.list) {
			var project_array = []; //it s here to check duplicate
			for (var circle_num = 0; circle_num < hack.list[cursus_id].circles.length; circle_num++) {
				// set the radius of each circle
				if (hack.list[cursus_id].circles.length > 1) hack.list[cursus_id].circles[circle_num].radius = hack.list[cursus_id].radius * circle_num / (hack.list[cursus_id].circles.length - 1);

				for (var project_num = 0; project_num < hack.list[cursus_id].circles[circle_num].projects.length; project_num++) {
					var center = position_on_circle(Graph.center_point, hack.list[cursus_id].circles[circle_num].radius, hack.list[cursus_id].circles[circle_num].angle, hack.list[cursus_id].circles[circle_num].projects.length, project_num);
					switch (hack.list[cursus_id].circles[circle_num].projects[project_num].kind) {
						case "inner_planet":
							for (var i = 0; i < hack.list[cursus_id].circles[circle_num].projects[project_num].satellites.length; i++) {
								project_array.push(hack.list[cursus_id].circles[circle_num].projects[project_num].satellites[i]);
								hack.list[cursus_id].projects[hack.list[cursus_id].circles[circle_num].projects[project_num].satellites[i]] = {
									"center": position_on_circle(center, 50, 36, hack.list[cursus_id].circles[circle_num].projects[project_num].satellites.length, i),
									"kind": "inner_satellite",
									"circle": hack.list[cursus_id].circles[circle_num],
									"circle_project": hack.list[cursus_id].circles[circle_num].projects[project_num]
								};
							}
							hack.list[cursus_id].projects[hack.list[cursus_id].circles[circle_num].projects[project_num].id] = {
								"center": center,
								"kind": hack.list[cursus_id].circles[circle_num].projects[project_num].kind,
								"circle": hack.list[cursus_id].circles[circle_num],
								"circle_project": hack.list[cursus_id].circles[circle_num].projects[project_num]
							};
							project_array.push(hack.list[cursus_id].circles[circle_num].projects[project_num].id);
							break;
						case "inner_linked":
							var centers = calculate_linked_centers(center, hack.list[cursus_id].circles[circle_num].projects[project_num].ids.length, 50, Graph.center_point, hack.list[cursus_id].circles[circle_num].radius);
							for (var i = 0; i < hack.list[cursus_id].circles[circle_num].projects[project_num].ids.length; i++) {
								project_array.push(hack.list[cursus_id].circles[circle_num].projects[project_num].ids[i]);
								hack.list[cursus_id].projects[hack.list[cursus_id].circles[circle_num].projects[project_num].ids[i]] = {
									"center": centers[i],
									"kind": hack.list[cursus_id].circles[circle_num].projects[project_num].kind,
									"circle": hack.list[cursus_id].circles[circle_num],
									"circle_project": hack.list[cursus_id].circles[circle_num].projects[project_num]
								};
							}
							break;
						default:
							hack.list[cursus_id].projects[hack.list[cursus_id].circles[circle_num].projects[project_num].id] = {
								"center": center,
								"kind": hack.list[cursus_id].circles[circle_num].projects[project_num].kind,
								"circle": hack.list[cursus_id].circles[circle_num],
								"circle_project": hack.list[cursus_id].circles[circle_num].projects[project_num]
							};
							project_array.push(hack.list[cursus_id].circles[circle_num].projects[project_num].id);
							break;
					}
				}
			}
			var project_set = new Set(project_array);
			if (project_set.size !== project_array.length) {
				var duplicates_list = "";
				var _iteratorNormalCompletion = true;
				var _didIteratorError = false;
				var _iteratorError = undefined;

				try {
					for (var _iterator = project_array[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
						var id = _step.value;

						if (project_set.has(id)) {
							project_set.delete(id);
						} else {
							duplicates_list += " " + id;
						}
					}
					// throw "ERROR IN HACK LIST duplicates found:" + duplicates_list
				} catch (err) {
					_didIteratorError = true;
					_iteratorError = err;
				} finally {
					try {
						if (!_iteratorNormalCompletion && _iterator.return) {
							_iterator.return();
						}
					} finally {
						if (_didIteratorError) {
							throw _iteratorError;
						}
					}
				}
			}
		}
	}

	init();

	hack.get_circle_type = function (projects_hacked, circle_info) {
		var states = {
			"fail": 0,
			"unavailable": 0,
			"done": 0,
			"in_progress": 0,
			"available": 0
		};
		var _iteratorNormalCompletion2 = true;
		var _didIteratorError2 = false;
		var _iteratorError2 = undefined;

		try {
			for (var _iterator2 = circle_info.projects[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
				var project_info = _step2.value;

				var cur_state = "unavailable";
				switch (project_info.kind) {
					case "inner_linked":
						var _iteratorNormalCompletion3 = true;
						var _didIteratorError3 = false;
						var _iteratorError3 = undefined;

						try {
							for (var _iterator3 = project_info.ids[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
								var id = _step3.value;

								if (!(id in projects_hacked)) continue;
								var project = projects_hacked[id];
								if (project.state == "done") {
									cur_state = "done";
									var _iteratorNormalCompletion4 = true;
									var _didIteratorError4 = false;
									var _iteratorError4 = undefined;

									try {
										for (var _iterator4 = project_info.ids[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
											var id2 = _step4.value;

											if (id2 != id && id2 in projects_hacked) projects_hacked[id2].state = "unavailable";
										}
									} catch (err) {
										_didIteratorError4 = true;
										_iteratorError4 = err;
									} finally {
										try {
											if (!_iteratorNormalCompletion4 && _iterator4.return) {
												_iterator4.return();
											}
										} finally {
											if (_didIteratorError4) {
												throw _iteratorError4;
											}
										}
									}

									break;
								}
								if (project.state == "fail" && (cur_state == "unavailable" || cur_state == "fail")) {
									cur_state = "fail";
								} else if (project.state == "available" && cur_state != "in_progress") {
									cur_state = "available";
								} else if (project.state == "in_progress") {
									cur_state = "in_progress";
								}
							}
						} catch (err) {
							_didIteratorError3 = true;
							_iteratorError3 = err;
						} finally {
							try {
								if (!_iteratorNormalCompletion3 && _iterator3.return) {
									_iterator3.return();
								}
							} finally {
								if (_didIteratorError3) {
									throw _iteratorError3;
								}
							}
						}

						break;
					default:
						if (project_info.id in projects_hacked) cur_state = projects_hacked[project_info.id].state;
						break;
				}
				states[cur_state]++;
			}
		} catch (err) {
			_didIteratorError2 = true;
			_iteratorError2 = err;
		} finally {
			try {
				if (!_iteratorNormalCompletion2 && _iterator2.return) {
					_iterator2.return();
				}
			} finally {
				if (_didIteratorError2) {
					throw _iteratorError2;
				}
			}
		}

		circle_info.state = "unavailable";
		if (states.fail == circle_info.projects.length) circle_info.state = "fail";else if (states.done == circle_info.projects.length) circle_info.state = "done";else if (states.available == circle_info.projects.length) circle_info.state = "available";else if (states.done > 0 || states.in_progress > 0) circle_info.state = "in_progress";
	};

	var move_away = 10000;

	hack.add_hack_info = function (projects, cursus_id) {
		var projects_hacked = {};
		_lodash2.default.each(projects, function (project) {
			if (Math.pow(project.x - Graph.center_point.x, 2) + Math.pow(project.y - Graph.center_point.y, 2) <= hack.list[cursus_id].radius * (hack.list[cursus_id].radius + 1)) {
				project.x += move_away;
				project.y += move_away;
				for (var by = 0; by < project.by.length; by++) {
					project.by[by].points[0][0] += move_away;
					project.by[by].points[0][1] += move_away;
					project.by[by].points[1][0] += move_away;
					project.by[by].points[1][1] += move_away;
				}
			} else {
				for (var by = 0; by < project.by.length; by++) {
					if (project.by[by].points[0][0] == project.by[by].points[1][0] && project.by[by].points[0][1] == project.by[by].points[1][1]) continue;
					var point0IsIn = Math.pow(project.by[by].points[0][0] - Graph.center_point.x, 2) + Math.pow(project.by[by].points[0][1] - Graph.center_point.y, 2) <= hack.list[cursus_id].radius * (hack.list[cursus_id].radius + 1);
					var point1IsIn = Math.pow(project.by[by].points[1][0] - Graph.center_point.x, 2) + Math.pow(project.by[by].points[1][1] - Graph.center_point.y, 2) <= hack.list[cursus_id].radius * (hack.list[cursus_id].radius + 1);
					if (point0IsIn && point1IsIn) {
						project.by[by].points[0][0] += move_away;
						project.by[by].points[0][1] += move_away;
						project.by[by].points[1][0] += move_away;
						project.by[by].points[1][1] += move_away;
					} else if (point1IsIn) {
						project.by[by].points[1] = movePoint2OnCircle(project.by[by].points[0][0], project.by[by].points[0][1], project.by[by].points[1][0], project.by[by].points[1][1], Graph.center_point.x, Graph.center_point.y, hack.list[cursus_id].radius);
					} else if (point0IsIn) {
						project.by[by].points[0] = movePoint2OnCircle(project.by[by].points[1][0], project.by[by].points[1][1], project.by[by].points[0][0], project.by[by].points[0][1], Graph.center_point.x, Graph.center_point.y, hack.list[cursus_id].radius);
					}
				}
			}
			if (!(project.project_id in hack.list[cursus_id].projects)) return;
			project.kind = hack.list[cursus_id].projects[project.project_id].kind;
			project.x = hack.list[cursus_id].projects[project.project_id].center.x;
			project.y = hack.list[cursus_id].projects[project.project_id].center.y;
			project.by = [];
			projects_hacked[project.project_id] = project;
		});
		for (var circle_num = 0; circle_num < hack.list[cursus_id].circles.length; circle_num++) {
			this.get_circle_type(projects_hacked, hack.list[cursus_id].circles[circle_num]);
		}
		return projects_hacked;
	};

	hack.hack_it = function (projects, cursus_id, project_layer, internship_layer) {
		if (!(cursus_id in hack.list)) return;
		var projects_hacked = this.add_hack_info(projects, cursus_id);
		var cursus_info = hack.list[cursus_id];
		var project_styles_keys = Object.keys(Graph.styles);
		for (var i = 0; i < cursus_info.circles.length; i++) {
			internship_layer.activate();
			if (i > 0) {
				var circle = new _paper2.default.Path.Circle({ center: Graph.center_point, radius: cursus_info.radius * i / (cursus_info.circles.length - 1) });
				circle.set(_lodash2.default.assign(_lodash2.default.cloneDeep(Graph.styles[cursus_info.circles[i].state]), { fillColor: null }));
			}
		}
	};

	Graph.hack = hack;

/***/ },
/* 483 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	var _paper = __webpack_require__(463);

	var _paper2 = _interopRequireDefault(_paper);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	Graph.HEIGHT = 6000;
	Graph.WIDTH = 6000;
	Graph.center_point = new _paper2.default.Point(Graph.WIDTH / 2, Graph.HEIGHT / 2);

/***/ },
/* 484 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.

	var formatRegExp = /%[sdj%]/g;
	exports.format = function(f) {
	  if (!isString(f)) {
	    var objects = [];
	    for (var i = 0; i < arguments.length; i++) {
	      objects.push(inspect(arguments[i]));
	    }
	    return objects.join(' ');
	  }

	  var i = 1;
	  var args = arguments;
	  var len = args.length;
	  var str = String(f).replace(formatRegExp, function(x) {
	    if (x === '%%') return '%';
	    if (i >= len) return x;
	    switch (x) {
	      case '%s': return String(args[i++]);
	      case '%d': return Number(args[i++]);
	      case '%j':
	        try {
	          return JSON.stringify(args[i++]);
	        } catch (_) {
	          return '[Circular]';
	        }
	      default:
	        return x;
	    }
	  });
	  for (var x = args[i]; i < len; x = args[++i]) {
	    if (isNull(x) || !isObject(x)) {
	      str += ' ' + x;
	    } else {
	      str += ' ' + inspect(x);
	    }
	  }
	  return str;
	};


	// Mark that a method should not be used.
	// Returns a modified function which warns once by default.
	// If --no-deprecation is set, then it is a no-op.
	exports.deprecate = function(fn, msg) {
	  // Allow for deprecating things in the process of starting up.
	  if (isUndefined(global.process)) {
	    return function() {
	      return exports.deprecate(fn, msg).apply(this, arguments);
	    };
	  }

	  if (process.noDeprecation === true) {
	    return fn;
	  }

	  var warned = false;
	  function deprecated() {
	    if (!warned) {
	      if (process.throwDeprecation) {
	        throw new Error(msg);
	      } else if (process.traceDeprecation) {
	        console.trace(msg);
	      } else {
	        console.error(msg);
	      }
	      warned = true;
	    }
	    return fn.apply(this, arguments);
	  }

	  return deprecated;
	};


	var debugs = {};
	var debugEnviron;
	exports.debuglog = function(set) {
	  if (isUndefined(debugEnviron))
	    debugEnviron = process.env.NODE_DEBUG || '';
	  set = set.toUpperCase();
	  if (!debugs[set]) {
	    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
	      var pid = process.pid;
	      debugs[set] = function() {
	        var msg = exports.format.apply(exports, arguments);
	        console.error('%s %d: %s', set, pid, msg);
	      };
	    } else {
	      debugs[set] = function() {};
	    }
	  }
	  return debugs[set];
	};


	/**
	 * Echos the value of a value. Trys to print the value out
	 * in the best way possible given the different types.
	 *
	 * @param {Object} obj The object to print out.
	 * @param {Object} opts Optional options object that alters the output.
	 */
	/* legacy: obj, showHidden, depth, colors*/
	function inspect(obj, opts) {
	  // default options
	  var ctx = {
	    seen: [],
	    stylize: stylizeNoColor
	  };
	  // legacy...
	  if (arguments.length >= 3) ctx.depth = arguments[2];
	  if (arguments.length >= 4) ctx.colors = arguments[3];
	  if (isBoolean(opts)) {
	    // legacy...
	    ctx.showHidden = opts;
	  } else if (opts) {
	    // got an "options" object
	    exports._extend(ctx, opts);
	  }
	  // set default options
	  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
	  if (isUndefined(ctx.depth)) ctx.depth = 2;
	  if (isUndefined(ctx.colors)) ctx.colors = false;
	  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
	  if (ctx.colors) ctx.stylize = stylizeWithColor;
	  return formatValue(ctx, obj, ctx.depth);
	}
	exports.inspect = inspect;


	// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
	inspect.colors = {
	  'bold' : [1, 22],
	  'italic' : [3, 23],
	  'underline' : [4, 24],
	  'inverse' : [7, 27],
	  'white' : [37, 39],
	  'grey' : [90, 39],
	  'black' : [30, 39],
	  'blue' : [34, 39],
	  'cyan' : [36, 39],
	  'green' : [32, 39],
	  'magenta' : [35, 39],
	  'red' : [31, 39],
	  'yellow' : [33, 39]
	};

	// Don't use 'blue' not visible on cmd.exe
	inspect.styles = {
	  'special': 'cyan',
	  'number': 'yellow',
	  'boolean': 'yellow',
	  'undefined': 'grey',
	  'null': 'bold',
	  'string': 'green',
	  'date': 'magenta',
	  // "name": intentionally not styling
	  'regexp': 'red'
	};


	function stylizeWithColor(str, styleType) {
	  var style = inspect.styles[styleType];

	  if (style) {
	    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
	           '\u001b[' + inspect.colors[style][1] + 'm';
	  } else {
	    return str;
	  }
	}


	function stylizeNoColor(str, styleType) {
	  return str;
	}


	function arrayToHash(array) {
	  var hash = {};

	  array.forEach(function(val, idx) {
	    hash[val] = true;
	  });

	  return hash;
	}


	function formatValue(ctx, value, recurseTimes) {
	  // Provide a hook for user-specified inspect functions.
	  // Check that value is an object with an inspect function on it
	  if (ctx.customInspect &&
	      value &&
	      isFunction(value.inspect) &&
	      // Filter out the util module, it's inspect function is special
	      value.inspect !== exports.inspect &&
	      // Also filter out any prototype objects using the circular check.
	      !(value.constructor && value.constructor.prototype === value)) {
	    var ret = value.inspect(recurseTimes, ctx);
	    if (!isString(ret)) {
	      ret = formatValue(ctx, ret, recurseTimes);
	    }
	    return ret;
	  }

	  // Primitive types cannot have properties
	  var primitive = formatPrimitive(ctx, value);
	  if (primitive) {
	    return primitive;
	  }

	  // Look up the keys of the object.
	  var keys = Object.keys(value);
	  var visibleKeys = arrayToHash(keys);

	  if (ctx.showHidden) {
	    keys = Object.getOwnPropertyNames(value);
	  }

	  // IE doesn't make error fields non-enumerable
	  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
	  if (isError(value)
	      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
	    return formatError(value);
	  }

	  // Some type of object without properties can be shortcutted.
	  if (keys.length === 0) {
	    if (isFunction(value)) {
	      var name = value.name ? ': ' + value.name : '';
	      return ctx.stylize('[Function' + name + ']', 'special');
	    }
	    if (isRegExp(value)) {
	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
	    }
	    if (isDate(value)) {
	      return ctx.stylize(Date.prototype.toString.call(value), 'date');
	    }
	    if (isError(value)) {
	      return formatError(value);
	    }
	  }

	  var base = '', array = false, braces = ['{', '}'];

	  // Make Array say that they are Array
	  if (isArray(value)) {
	    array = true;
	    braces = ['[', ']'];
	  }

	  // Make functions say that they are functions
	  if (isFunction(value)) {
	    var n = value.name ? ': ' + value.name : '';
	    base = ' [Function' + n + ']';
	  }

	  // Make RegExps say that they are RegExps
	  if (isRegExp(value)) {
	    base = ' ' + RegExp.prototype.toString.call(value);
	  }

	  // Make dates with properties first say the date
	  if (isDate(value)) {
	    base = ' ' + Date.prototype.toUTCString.call(value);
	  }

	  // Make error with message first say the error
	  if (isError(value)) {
	    base = ' ' + formatError(value);
	  }

	  if (keys.length === 0 && (!array || value.length == 0)) {
	    return braces[0] + base + braces[1];
	  }

	  if (recurseTimes < 0) {
	    if (isRegExp(value)) {
	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
	    } else {
	      return ctx.stylize('[Object]', 'special');
	    }
	  }

	  ctx.seen.push(value);

	  var output;
	  if (array) {
	    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
	  } else {
	    output = keys.map(function(key) {
	      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
	    });
	  }

	  ctx.seen.pop();

	  return reduceToSingleString(output, base, braces);
	}


	function formatPrimitive(ctx, value) {
	  if (isUndefined(value))
	    return ctx.stylize('undefined', 'undefined');
	  if (isString(value)) {
	    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
	                                             .replace(/'/g, "\\'")
	                                             .replace(/\\"/g, '"') + '\'';
	    return ctx.stylize(simple, 'string');
	  }
	  if (isNumber(value))
	    return ctx.stylize('' + value, 'number');
	  if (isBoolean(value))
	    return ctx.stylize('' + value, 'boolean');
	  // For some reason typeof null is "object", so special case here.
	  if (isNull(value))
	    return ctx.stylize('null', 'null');
	}


	function formatError(value) {
	  return '[' + Error.prototype.toString.call(value) + ']';
	}


	function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
	  var output = [];
	  for (var i = 0, l = value.length; i < l; ++i) {
	    if (hasOwnProperty(value, String(i))) {
	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
	          String(i), true));
	    } else {
	      output.push('');
	    }
	  }
	  keys.forEach(function(key) {
	    if (!key.match(/^\d+$/)) {
	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
	          key, true));
	    }
	  });
	  return output;
	}


	function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
	  var name, str, desc;
	  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
	  if (desc.get) {
	    if (desc.set) {
	      str = ctx.stylize('[Getter/Setter]', 'special');
	    } else {
	      str = ctx.stylize('[Getter]', 'special');
	    }
	  } else {
	    if (desc.set) {
	      str = ctx.stylize('[Setter]', 'special');
	    }
	  }
	  if (!hasOwnProperty(visibleKeys, key)) {
	    name = '[' + key + ']';
	  }
	  if (!str) {
	    if (ctx.seen.indexOf(desc.value) < 0) {
	      if (isNull(recurseTimes)) {
	        str = formatValue(ctx, desc.value, null);
	      } else {
	        str = formatValue(ctx, desc.value, recurseTimes - 1);
	      }
	      if (str.indexOf('\n') > -1) {
	        if (array) {
	          str = str.split('\n').map(function(line) {
	            return '  ' + line;
	          }).join('\n').substr(2);
	        } else {
	          str = '\n' + str.split('\n').map(function(line) {
	            return '   ' + line;
	          }).join('\n');
	        }
	      }
	    } else {
	      str = ctx.stylize('[Circular]', 'special');
	    }
	  }
	  if (isUndefined(name)) {
	    if (array && key.match(/^\d+$/)) {
	      return str;
	    }
	    name = JSON.stringify('' + key);
	    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
	      name = name.substr(1, name.length - 2);
	      name = ctx.stylize(name, 'name');
	    } else {
	      name = name.replace(/'/g, "\\'")
	                 .replace(/\\"/g, '"')
	                 .replace(/(^"|"$)/g, "'");
	      name = ctx.stylize(name, 'string');
	    }
	  }

	  return name + ': ' + str;
	}


	function reduceToSingleString(output, base, braces) {
	  var numLinesEst = 0;
	  var length = output.reduce(function(prev, cur) {
	    numLinesEst++;
	    if (cur.indexOf('\n') >= 0) numLinesEst++;
	    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
	  }, 0);

	  if (length > 60) {
	    return braces[0] +
	           (base === '' ? '' : base + '\n ') +
	           ' ' +
	           output.join(',\n  ') +
	           ' ' +
	           braces[1];
	  }

	  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
	}


	// NOTE: These type checking functions intentionally don't use `instanceof`
	// because it is fragile and can be easily faked with `Object.create()`.
	function isArray(ar) {
	  return Array.isArray(ar);
	}
	exports.isArray = isArray;

	function isBoolean(arg) {
	  return typeof arg === 'boolean';
	}
	exports.isBoolean = isBoolean;

	function isNull(arg) {
	  return arg === null;
	}
	exports.isNull = isNull;

	function isNullOrUndefined(arg) {
	  return arg == null;
	}
	exports.isNullOrUndefined = isNullOrUndefined;

	function isNumber(arg) {
	  return typeof arg === 'number';
	}
	exports.isNumber = isNumber;

	function isString(arg) {
	  return typeof arg === 'string';
	}
	exports.isString = isString;

	function isSymbol(arg) {
	  return typeof arg === 'symbol';
	}
	exports.isSymbol = isSymbol;

	function isUndefined(arg) {
	  return arg === void 0;
	}
	exports.isUndefined = isUndefined;

	function isRegExp(re) {
	  return isObject(re) && objectToString(re) === '[object RegExp]';
	}
	exports.isRegExp = isRegExp;

	function isObject(arg) {
	  return typeof arg === 'object' && arg !== null;
	}
	exports.isObject = isObject;

	function isDate(d) {
	  return isObject(d) && objectToString(d) === '[object Date]';
	}
	exports.isDate = isDate;

	function isError(e) {
	  return isObject(e) &&
	      (objectToString(e) === '[object Error]' || e instanceof Error);
	}
	exports.isError = isError;

	function isFunction(arg) {
	  return typeof arg === 'function';
	}
	exports.isFunction = isFunction;

	function isPrimitive(arg) {
	  return arg === null ||
	         typeof arg === 'boolean' ||
	         typeof arg === 'number' ||
	         typeof arg === 'string' ||
	         typeof arg === 'symbol' ||  // ES6 symbol
	         typeof arg === 'undefined';
	}
	exports.isPrimitive = isPrimitive;

	exports.isBuffer = __webpack_require__(485);

	function objectToString(o) {
	  return Object.prototype.toString.call(o);
	}


	function pad(n) {
	  return n < 10 ? '0' + n.toString(10) : n.toString(10);
	}


	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
	              'Oct', 'Nov', 'Dec'];

	// 26 Feb 16:19:34
	function timestamp() {
	  var d = new Date();
	  var time = [pad(d.getHours()),
	              pad(d.getMinutes()),
	              pad(d.getSeconds())].join(':');
	  return [d.getDate(), months[d.getMonth()], time].join(' ');
	}


	// log is just a thin wrapper to console.log that prepends a timestamp
	exports.log = function() {
	  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
	};


	/**
	 * Inherit the prototype methods from one constructor into another.
	 *
	 * The Function.prototype.inherits from lang.js rewritten as a standalone
	 * function (not on Function.prototype). NOTE: If this file is to be loaded
	 * during bootstrapping this function needs to be rewritten using some native
	 * functions as prototype setup using normal JavaScript does not work as
	 * expected during bootstrapping (see mirror.js in r114903).
	 *
	 * @param {function} ctor Constructor function which needs to inherit the
	 *     prototype.
	 * @param {function} superCtor Constructor function to inherit prototype from.
	 */
	exports.inherits = __webpack_require__(486);

	exports._extend = function(origin, add) {
	  // Don't do anything if add isn't an object
	  if (!add || !isObject(add)) return origin;

	  var keys = Object.keys(add);
	  var i = keys.length;
	  while (i--) {
	    origin[keys[i]] = add[keys[i]];
	  }
	  return origin;
	};

	function hasOwnProperty(obj, prop) {
	  return Object.prototype.hasOwnProperty.call(obj, prop);
	}

	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(30)))

/***/ },
/* 485 */
/***/ function(module, exports) {

	module.exports = function isBuffer(arg) {
	  return arg && typeof arg === 'object'
	    && typeof arg.copy === 'function'
	    && typeof arg.fill === 'function'
	    && typeof arg.readUInt8 === 'function';
	}

/***/ },
/* 486 */
/***/ function(module, exports) {

	if (typeof Object.create === 'function') {
	  // implementation from standard node.js 'util' module
	  module.exports = function inherits(ctor, superCtor) {
	    ctor.super_ = superCtor
	    ctor.prototype = Object.create(superCtor.prototype, {
	      constructor: {
	        value: ctor,
	        enumerable: false,
	        writable: true,
	        configurable: true
	      }
	    });
	  };
	} else {
	  // old school shim for old browsers
	  module.exports = function inherits(ctor, superCtor) {
	    ctor.super_ = superCtor
	    var TempCtor = function () {}
	    TempCtor.prototype = superCtor.prototype
	    ctor.prototype = new TempCtor()
	    ctor.prototype.constructor = ctor
	  }
	}


/***/ },
/* 487 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function encodeQueryData(data) {
	  var ret = [];
	  for (var d in data) {
	    ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
	  }return ret.join('&');
	}

	var Stats = function Stats() {
	  _classCallCheck(this, Stats);

	  var div = document.getElementById("projects_registrations_stats");
	  var params = new URLSearchParams(new URL(window.location).search);
	  if (!div) return;
	  var encodedParams = encodeQueryData({ 'project_id': div.attributes.project_id.value, 'project_session_id': div.attributes.project_session_id.value });
	  console.log(encodedParams);
	  $(document).ready(function () {
	    $.ajax({
	      url: '/projects/' + div.attributes.project_id.value + '/registration_stats' + '?' + encodedParams,
	      method: 'GET',
	      data: ""
	    }).done(function (response) {
	      $(div).html(response);
	    }).fail(function (response) {
	      $(div).html('<div class="row" style="text-align: center; height: 60px"><div class="fa fa-frown fa-3x center" style="color: #C0C0C0"></div></div>');
	    });
	  });
	};

	exports.default = Stats;

/***/ },
/* 488 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Sentry = function Sentry() {
	  //Init Raven Sentry tracker
	  // Raven.config('https://b1f006a853eb4315a5f9aa6ee392c7ee@sentry.42.fr/9', {
	  //   ignoreUrls: [
	  //     /http(s)?:\/\/(www.)?localhost.*/
	  //   ],
	  //   ignoreErrors: [
	  //     'Error: Existing connection must be closed before opening'
	  //   ],
	  //   environment: _environment,
	  //   tags: {
	  //     git_commit: _git_commit
	  //   }
	  // }).install()

	  // Raven.setUser({
	  //   username: _user.login,
	  //   id: _user.id
	  // })

	  //Raven.setExtraContext({ })

	  _classCallCheck(this, Sentry);
	};

	exports.default = Sentry;

/***/ },
/* 489 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _jquery = __webpack_require__(5);

	var _jquery2 = _interopRequireDefault(_jquery);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Mailer = function Mailer() {
	  _classCallCheck(this, Mailer);

	  var PreventRefresh = true;
	  if ((0, _jquery2.default)("#mailer_content").length == 0) return;

	  window.mde_message = new SimpleMDE({
	    element: document.getElementById("mailer_content"),
	    status: false,
	    spellChecker: false,
	    lineWrapping: false,
	    parsingConfig: {
	      strikethrough: true,
	      allowAtxHeaderWithoutSpace: true
	    }
	  });

	  var PreventRefreshFct = function PreventRefreshFct(e) {
	    var mailer_content = window.mde_message.value();
	    var message = "Are you sure you want to leave this page ?";

	    e = e || window.event;
	    if (e) {
	      e.preventDefault();
	      e.returnValue = message;
	    }

	    console.log((0, _jquery2.default)("#mailer_subtitle").val());
	    ["#mailer_title", "#mailer_subject", "#mailer_subtitle"].forEach(function (e) {
	      localStorage.setItem(e, (0, _jquery2.default)(e).val());
	    });
	    localStorage.setItem("#mailer_content", mailer_content);
	    return message;
	  };
	  window.onbeforeunload = PreventRefreshFct;

	  var destroyLocalStorage = function destroyLocalStorage() {
	    console.log('je destroy le localstorage');
	    ["#mailer_title", "#mailer_subject", "#mailer_content", "#mailer_subtitle"].forEach(function (e) {
	      localStorage.removeItem(e);
	    });
	  };

	  (0, _jquery2.default)(document).ready(function () {
	    if ((0, _jquery2.default)("#mailer_content").length == 0) return;
	    if ((0, _jquery2.default)(".notifications-flash-top-bar alter-success").length != 0) {
	      destroyLocalStorage();
	      return;
	    }
	    ["#mailer_title", "#mailer_subject", "#mailer_subtitle"].forEach(function (e) {
	      (0, _jquery2.default)(e).val(localStorage.getItem(e) || '');
	    });
	    window.mde_message.value(localStorage.getItem("#mailer_content") || '');
	  });

	  (0, _jquery2.default)("#mailer_from").on("input", function () {
	    _jquery2.default.ajax({
	      url: "/users/login_exist",
	      type: "POST",
	      data: {
	        login: (0, _jquery2.default)(this).val()
	      },
	      success: function success(data) {
	        if (data.exist === true) {
	          (0, _jquery2.default)("#mailer_from").closest('.input-group').before("<small id='mail_from_danger' class='text-danger'>The email prefix must not match an existing user’s login. Please change it or you won’t be able to send this email.</small>");
	        } else {
	          (0, _jquery2.default)('#mail_from_danger').remove();
	        }
	      }
	    });
	  });

	  (0, _jquery2.default)('#mailer_kind').select2().val((0, _jquery2.default)('#mailer_kind').children('option').map(function () {
	    return (0, _jquery2.default)(this).text();
	  })).change();
	  (0, _jquery2.default)("#mailer_simple_to").select2({
	    ajax: {
	      url: "/users/query",
	      dataType: 'json',
	      delay: 250,
	      data: function data(params) {
	        return {
	          q: params.term, // search term
	          page: params.page
	        };
	      },
	      processResults: function processResults(data, params) {
	        params.page = params.page || 1;
	        return {
	          results: data.items,
	          pagination: {
	            more: params.page * 30 < data.total_count
	          }
	        };
	      },
	      cache: true
	    },
	    minimumInputLength: 2,
	    dropdownAutoWidth: true,
	    escapeMarkup: function escapeMarkup(markup) {
	      return markup;
	    }, // let our custom formatter work
	    templateResult: function templateResult(data) {
	      return "<span><b>" + data.entity_type + "</b> " + (data.login || data.slug || data.name) + "</span>";
	    },
	    templateSelection: function templateSelection(data) {
	      return "<span><b>" + data.entity_type + "</b> " + (data.login || data.slug || data.name) + "</span>";
	    }
	  });

	  (0, _jquery2.default)('input.mailer_from_who').click(function (e) {
	    e.stopPropagation();
	    var newId = e.currentTarget.value;
	    if (newId === "custom") {
	      (0, _jquery2.default)("#mailer_from").removeAttr("readonly");
	      (0, _jquery2.default)("#mailer_from").val("");
	    } else {
	      (0, _jquery2.default)("#mailer_from").attr("readonly", "readonly");
	      (0, _jquery2.default)('#mailer_from').val(newId);
	    }
	  });

	  (0, _jquery2.default)('select#mailer_from_campus').change(function () {
	    _jquery2.default.ajax({
	      url: "/users/domain_check",
	      type: "POST",
	      data: {
	        domain: (0, _jquery2.default)(this).val()
	      },
	      success: function success(data) {
	        if (data.exist === false) {
	          (0, _jquery2.default)("#mailer_from").closest('.input-group').before("<small id='mail_from_campus_danger' class='text-danger'>The domain name you selected is not the default one of your campus. Please make sure that it is properly configured to send emails from the intranet’s SMTP.</small>");
	        } else {
	          (0, _jquery2.default)('#mail_from_campus_danger').remove();
	        }
	      }
	    });
	  });

	  (0, _jquery2.default)('#btn-send-mail').click(function () {
	    var to = data_to();

	    (0, _jquery2.default)('#mailer').modal();
	    (0, _jquery2.default)('#details tbody').html('<tr><td colspan="2">Loading...</td></tr>');
	    _jquery2.default.ajax({
	      url: "/users/users_count",
	      data: { mailer: { to: to } },
	      type: 'POST',
	      success: function success(d) {
	        var mfc = null;
	        if ((0, _jquery2.default)('select#mailer_from_campus').length === 0) mfc = (0, _jquery2.default)('#mailer_from_campus').html();else mfc = (0, _jquery2.default)('select#mailer_from_campus').find(":selected").text();

	        (0, _jquery2.default)('#mailer_modal_email_from').html((0, _jquery2.default)("#mailer_from").val() + mfc);
	        (0, _jquery2.default)('#details tbody, #details ~ #extras').html('');
	        if (d.users_count == 0 || d.users_count && d.emails_count == 0 || Object.keys(d).length == 0) {
	          (0, _jquery2.default)('#details tbody').html('<tr><td colspan="2">No users</td></tr>');
	          (0, _jquery2.default)('[type="submit"]').attr('disabled', true);
	        } else {
	          (0, _jquery2.default)('[type="submit"]').removeAttr('disabled');
	          for (var key in d.details) {
	            (0, _jquery2.default)('#details tbody').append(function () {
	              return "<tr><td>" + key + "</td><td>" + d.details[key] + "</td></tr>";
	            });
	          }

	          // extras
	          if (d.emails_count > 0) (0, _jquery2.default)('#details ~ #extras').text("Extras email: " + d.emails_count);
	        }
	      }
	    });
	  });

	  (0, _jquery2.default)('form.mailer').submit(function (e) {
	    PreventRefresh = false;
	    window.onbeforeunload = undefined;
	    mailer_to.value = JSON.stringify(data_to());
	    mailer_content.value = window.mde_message.options.previewRender(window.mde_message.value());
	    // destroyLocalStorage();
	  });

	  (0, _jquery2.default)('form.mailer input').on('keypress', function (e) {
	    return e.key !== 'Enter';
	  });

	  (0, _jquery2.default)('#mailer_logins, #mailer_emails').on('input', function () {
	    var extras_logins = parse_extras((0, _jquery2.default)('#mailer_logins').val());
	    var extras_emails = parse_extras((0, _jquery2.default)('#mailer_emails').val());
	    if (!extras_logins || !extras_emails) {
	      (0, _jquery2.default)('#malformatted_data').show().text(function () {
	        return (0, _jquery2.default)(this).data().malformattedData;
	      }).siblings('button').attr('disabled', 'disabled');
	      (0, _jquery2.default)('#modal_extras_link p').addClass('error').children('span.text').text(function () {
	        return (0, _jquery2.default)(this).parents('p').data().malformattedData;
	      });
	      return;
	    }
	    // email validations
	    var errs = [];
	    extras_emails.forEach(function (el) {
	      if (!/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(el)) {
	        (0, _jquery2.default)('#malformatted_data').show().text(function () {
	          return (0, _jquery2.default)(this).data().invalidEmail;
	        }).siblings('button').attr('disabled', 'disabled');
	        errs.push(el);
	        return false;
	      }
	    });
	    if (errs.length != 0) return;
	    // end email validation

	    (0, _jquery2.default)('#malformatted_data').hide().siblings('button').removeAttr('disabled');
	    (0, _jquery2.default)('#modal_extras_link p').removeClass('error');

	    (0, _jquery2.default)('#modal_extras_link .text').text(function () {
	      if ((!extras_logins ? 0 : extras_logins.length) == 0 && (!extras_emails ? 0 : extras_emails.length) == 0) return (0, _jquery2.default)(this).parents('p').data().emptyText;

	      return (!extras_logins ? 0 : extras_logins.length) + " extra(s) login(s) and " + (!extras_emails ? 0 : extras_emails.length) + " extra(s) email(s)";
	    });
	  });

	  window.data_to = function () {
	    var data = (0, _jquery2.default)('#mailer_simple_to').select2('data'),
	        hash = {};
	    data.forEach(function (element) {
	      var entity_type = element.entity_type.toLowerCase();
	      if (entity_type != "pool") {
	        if (typeof hash[entity_type] === "undefined") {
	          hash[entity_type] = {};
	          hash[entity_type][entity_type + "_ids"] = new Array();
	        }
	        hash[entity_type][entity_type + "_ids"].push(element.entity_id);
	      } else {
	        if (entity_type == "pool") {
	          if (typeof hash['pools'] === "undefined") hash['pools'] = new Array();
	          hash['pools'].push(element.id);
	        }
	      }
	    });

	    hash['exclude_alumnis'] = (0, _jquery2.default)('#mailer_exclude_alumnis').is(':checked');
	    hash['include_future_users'] = (0, _jquery2.default)('#mailer_include_future_users').is(':checked');

	    if ((0, _jquery2.default)('#mailer_is_done').is(':checked')) {
	      if (typeof hash['projects'] === "undefined") hash['projects'] = {};
	      hash['projects']['is_done'] = true;
	    }

	    if ((0, _jquery2.default)('#mailer_is_primary').is(':checked')) {
	      if (typeof hash['campus'] === "undefined") hash['campus'] = {};
	      hash['campus']['is_primary'] = true;
	    }

	    if ((0, _jquery2.default)('#mailer_kind').select2('data').length >= 1) if (typeof hash['users'] === "undefined") hash['users'] = {};
	    hash['users']['kind'] = (0, _jquery2.default)('#mailer_kind').select2('data').map(function (x) {
	      return x.id;
	    });

	    var extras_logins = parse_extras((0, _jquery2.default)('#mailer_logins').val());
	    var extras_emails = parse_extras((0, _jquery2.default)('#mailer_emails').val());
	    if (extras_logins.length > 0 || extras_emails.length > 0) {
	      hash['extras'] = {};
	      if (extras_logins && extras_logins.length >= 1) hash['extras']['logins'] = extras_logins;
	      if (extras_emails && extras_emails.length >= 1) hash['extras']['emails'] = extras_emails;
	    }
	    return hash;
	  };

	  window.parse_extras = function (text) {
	    if (text.match(/^\[|\]$/gi)) {
	      try {
	        return JSON.parse(text);
	      } catch (e) {
	        return false;
	      }
	    } else {
	      if (text.match(/;/gi)) return text.split(';').filter(function (n) {
	        return n != "";
	      });else if (text.match(/,/gi)) return text.split(',').filter(function (n) {
	        return n != "";
	      });else if (text.match(/\n/gi)) return text.split('\n').filter(function (n) {
	        return n != "";
	      });else if (text == "") return [];else if (text.length > 0) return [text];else return false;
	    }
	  };
	};

	exports.default = Mailer;

/***/ }
/******/ ]);
